Spaces:
Running
Running
| <script lang="ts"> | |
| import * as Dialog from '$lib/components/ui/dialog/index.js'; | |
| import * as Select from '$lib/components/ui/select/index.js'; | |
| import { authState } from '$lib/state/auth.svelte'; | |
| import { Save } from '@lucide/svelte'; | |
| import Button from '../ui/button/button.svelte'; | |
| import Spinner from '../loading/Spinner.svelte'; | |
| let { open = $bindable(false) }: { open: boolean } = $props(); | |
| const planColors = { | |
| team: 'bg-purple-500/10 text-purple-600', | |
| enterprise: 'bg-green-500/10 text-green-600' | |
| }; | |
| let billingOption = $derived(authState.user?.billingOption || 'personal'); | |
| let selectedOrg = $derived(authState.user?.orgs?.find((org) => org.name === billingOption)); | |
| let loading = $state.raw<boolean>(false); | |
| async function saveSettings() { | |
| if (loading) return; | |
| loading = true; | |
| await new Promise((resolve) => setTimeout(resolve, 600)); | |
| loading = false; | |
| if (billingOption === 'personal') { | |
| localStorage.removeItem('hf-playground-billing-option'); | |
| } else { | |
| localStorage.setItem('hf-playground-billing-option', selectedOrg?.name ?? ''); | |
| } | |
| authState.user!.billingOption = billingOption; | |
| open = false; | |
| } | |
| function resetSettings() { | |
| billingOption = authState.user?.billingOption || 'personal'; | |
| } | |
| </script> | |
| <Dialog.Root | |
| bind:open | |
| onOpenChange={(value) => { | |
| if (!value) { | |
| resetSettings(); | |
| } | |
| }} | |
| > | |
| <Dialog.Content class="max-w-sm! p-0!"> | |
| <Dialog.Header class="mb-0 rounded-none border-b p-5"> | |
| <Dialog.Title>Billing Settings</Dialog.Title> | |
| <Dialog.Description>Manage your billing information.</Dialog.Description> | |
| </Dialog.Header> | |
| <Dialog.Description class="mt-0 px-5 pb-5"> | |
| <div> | |
| <p class="mb-1.5 font-medium text-primary"> | |
| Billing option <span class="font-normal text-muted-foreground" | |
| >(personal or organization)</span | |
| > | |
| </p> | |
| <Select.Root type="single" bind:value={billingOption}> | |
| <Select.Trigger | |
| class="flex w-full items-center justify-start gap-2 py-5!" | |
| disabled={loading} | |
| > | |
| {#if billingOption === 'personal'} | |
| <img | |
| src={authState.user?.avatarUrl} | |
| alt={authState.user?.name} | |
| class="size-5 rounded" | |
| /> | |
| {authState.user?.name} | |
| <span class="text-xs text-muted-foreground">(Personal Account)</span> | |
| {:else} | |
| <img | |
| src={selectedOrg?.avatarUrl} | |
| alt={selectedOrg?.fullname || selectedOrg?.name} | |
| class="size-5 rounded" | |
| /> | |
| {selectedOrg?.fullname || selectedOrg?.name} | |
| {#if selectedOrg?.plan} | |
| <span | |
| class="rounded px-1 py-0.5 text-[10px] font-semibold {planColors[ | |
| selectedOrg?.plan as keyof typeof planColors | |
| ]} uppercase" | |
| > | |
| {selectedOrg?.plan} | |
| </span> | |
| {/if} | |
| {/if} | |
| </Select.Trigger> | |
| <Select.Content class="space-y-3!"> | |
| <Select.Item value="personal" class="p-2.5!"> | |
| <div class="flex items-center gap-2"> | |
| <img | |
| src={authState.user?.avatarUrl} | |
| alt={authState.user?.name} | |
| class="size-5 rounded" | |
| /> | |
| {authState.user?.name} | |
| <span class="text-xs text-muted-foreground">(Personal Account)</span> | |
| </div> | |
| </Select.Item> | |
| {#each authState.user?.orgs as org} | |
| <Select.Item value={org.name} class="p-2.5!"> | |
| <div class="flex items-center gap-2 text-sm"> | |
| <img src={org.avatarUrl} alt={org.fullname || org.name} class="size-5 rounded" /> | |
| {org.fullname || org.name} | |
| {#if org.plan} | |
| <span | |
| class="rounded px-1 py-0.5 text-[10px] font-semibold {planColors[ | |
| org.plan as keyof typeof planColors | |
| ]} uppercase" | |
| > | |
| {org.plan} | |
| </span> | |
| {/if} | |
| </div> | |
| </Select.Item> | |
| {/each} | |
| </Select.Content> | |
| </Select.Root> | |
| </div> | |
| <div class="mt-5 flex items-center justify-end gap-3"> | |
| <Button variant="outline" onclick={resetSettings}>Reset</Button> | |
| <Button class="flex-1" onclick={saveSettings}> | |
| {#if loading} | |
| <Spinner className="text-lg" /> | |
| Saving... | |
| {:else} | |
| <Save /> | |
| Save settings | |
| {/if} | |
| </Button> | |
| </div> | |
| </Dialog.Description> | |
| </Dialog.Content> | |
| </Dialog.Root> | |