diff options
| author | Frank <[email protected]> | 2025-09-18 10:59:01 -0400 |
|---|---|---|
| committer | Frank <[email protected]> | 2025-09-18 10:59:01 -0400 |
| commit | 4ceabdffa07b1af8d99eb73622a4d549d99ec6d2 (patch) | |
| tree | 72e2ae62084a9e24cc76caffbd1f30dafc69ea56 /packages/console/app/src/component/workspace/new-user-section.tsx | |
| parent | c87480cf931a6f8f8b55552558ef521f1918b578 (diff) | |
| download | opencode-4ceabdffa07b1af8d99eb73622a4d549d99ec6d2.tar.gz opencode-4ceabdffa07b1af8d99eb73622a4d549d99ec6d2.zip | |
wip: zen
Diffstat (limited to 'packages/console/app/src/component/workspace/new-user-section.tsx')
| -rw-r--r-- | packages/console/app/src/component/workspace/new-user-section.tsx | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/packages/console/app/src/component/workspace/new-user-section.tsx b/packages/console/app/src/component/workspace/new-user-section.tsx new file mode 100644 index 000000000..5909072dd --- /dev/null +++ b/packages/console/app/src/component/workspace/new-user-section.tsx @@ -0,0 +1,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/console-core/key.js" +import { Billing } from "@opencode/console-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> + ) +} |
