summaryrefslogtreecommitdiffhomepage
path: root/cloud/app/src/component/workspace/new-user-section.tsx
blob: 6e031e3712301ea6297ee8cd36bcfb6878dfc42f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { query, useParams, createAsync } from "@solidjs/router"
import { createMemo, createSignal, Show } from "solid-js"
import { IconCopy, IconCheck } from "~/component/icon"
import { Key } from "@opencode/cloud-core/key.js"
import { Billing } from "@opencode/cloud-core/billing.js"
import { withActor } from "~/context/auth.withActor"
import styles from "./new-user-section.module.css"

const getUsageInfo = query(async (workspaceID: string) => {
  "use server"
  return withActor(async () => {
    return await Billing.usages()
  }, workspaceID)
}, "usage.list")

const listKeys = query(async (workspaceID: string) => {
  "use server"
  return withActor(() => Key.list(), workspaceID)
}, "key.list")

export function NewUserSection() {
  const params = useParams()
  const [copiedKey, setCopiedKey] = createSignal(false)
  const keys = createAsync(() => listKeys(params.id))
  const usage = createAsync(() => getUsageInfo(params.id))
  const isNew = createMemo(() => {
    const keysList = keys()
    const usageList = usage()
    return keysList?.length === 1 && (!usageList || usageList.length === 0)
  })
  const defaultKey = createMemo(() => keys()?.at(-1)?.key)

  return (
    <Show when={isNew()}>
      <div class={styles.root}>
        <div data-component="feature-grid">
          <div data-slot="feature">
            <h3>Tested & Verified Models</h3>
            <p>We've benchmarked and tested models specifically for coding agents to ensure the best performance.</p>
          </div>
          <div data-slot="feature">
            <h3>Highest Quality</h3>
            <p>Access models configured for optimal performance - no downgrades or routing to cheaper providers.</p>
          </div>
          <div data-slot="feature">
            <h3>No Lock-in</h3>
            <p>Use Zen with any coding agent, and continue using other providers with opencode whenever you want.</p>
          </div>
        </div>

        <div data-component="api-key-highlight">
          <Show when={defaultKey()}>
            <div data-slot="key-display">
              <div data-slot="key-container">
                <code data-slot="key-value">{defaultKey()}</code>
                <button
                  data-color="primary"
                  disabled={copiedKey()}
                  onClick={async () => {
                    await navigator.clipboard.writeText(defaultKey() ?? "")
                    setCopiedKey(true)
                    setTimeout(() => setCopiedKey(false), 2000)
                  }}
                  title="Copy API key"
                >
                  <Show
                    when={copiedKey()}
                    fallback={
                      <>
                        <IconCopy style={{ width: "16px", height: "16px" }} /> Copy Key
                      </>
                    }
                  >
                    <IconCheck style={{ width: "16px", height: "16px" }} /> Copied!
                  </Show>
                </button>
              </div>
            </div>
          </Show>
        </div>

        <div data-component="next-steps">
          <ol>
            <li>Enable billing</li>
            <li>
              Run <code>opencode auth login</code> and select opencode
            </li>
            <li>Paste your API key</li>
            <li>
              Start opencode and run <code>/models</code> to select a model
            </li>
          </ol>
        </div>
      </div>
    </Show>
  )
}