Das Teamdropdown stand als eigenes Bedienelement neben dem Namen — ein zweiter Schalter fuer eine Sache, die schon einen Menuepunkt hat. Jetzt klappt der Menuepunkt Team beim Ueberfahren auf: die eigenen Teams, ein Klick wechselt und oeffnet die Teamseite, darunter "Team erstellen". Die Zeiger- und Tastenhandler von bits-ui werden am Trigger bewusst ueberschrieben. Deren onclick ruft preventDefault und macht den Link tot, ihr pointerdown klappt zu, was der Hover gerade aufgeklappt hat — zwei Herren ueber dasselbe open, das Ergebnis war Flackern statt Navigation. Das Menue verzichtet zudem auf Fokusfang und Scrollsperre; beides gehoert zu einem Dialog, nicht zu etwas, ueber das der Zeiger nur streift. Der Anlegedialog liegt jetzt als CreateTeamDialog vor: Es gibt zwei Einstiege, und ein neues Team muss an beiden dasselbe bedeuten — Team anlegen, Standardsatz Flag-Typen dazu, ab dann ist es das aktive. Das Logo ragt mit -my-3 leicht ueber die Kopfleiste hinaus, verlinkt aufs Dashboard und teilt sich den Hover mit dessen Menuepunkt. Der aktive Menuepunkt traegt das Primary-Design. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P32KoesVtABd6xWsqMKzhr
76 lines
2.7 KiB
Svelte
76 lines
2.7 KiB
Svelte
<script lang="ts">
|
|
/**
|
|
* Dialog „Neues Team". Liegt als eigene Komponente vor, weil es zwei
|
|
* Einstiege gibt — den Teamwechsler im Kopf und die Teamseite — und ein
|
|
* neues Team an beiden Stellen dasselbe bedeuten muss: Team anlegen, den
|
|
* Standardsatz Flag-Typen dazu, und ab dann ist es das aktive Team.
|
|
*
|
|
* Ein Team ohne Flag-Typen kann zwar Marker aufnehmen, aber nichts
|
|
* einordnen. Deshalb kommt der Standardsatz gleich mit — änderbar und,
|
|
* wie alle Flag-Typen, allein Sache dieses Teams.
|
|
*/
|
|
import { getTeamContext } from '$lib/stores/teams.svelte'
|
|
import { getTrailFlagContext } from '$lib/stores/trailFlags.svelte'
|
|
import { Button } from '@/components/ui/button'
|
|
import * as Dialog from '@/components/ui/dialog'
|
|
import { Input } from '@/components/ui/input'
|
|
import { Label } from '@/components/ui/label'
|
|
|
|
let { open = $bindable(false) }: { open?: boolean } = $props()
|
|
|
|
const teams = getTeamContext()
|
|
const flags = getTrailFlagContext()
|
|
|
|
let name = $state('')
|
|
let error = $state<string | null>(null)
|
|
let busy = $state(false)
|
|
|
|
async function submit() {
|
|
if (!name.trim() || busy) return
|
|
|
|
busy = true
|
|
error = null
|
|
try {
|
|
const created = await teams.create(name.trim())
|
|
|
|
try {
|
|
await flags.seedDefaults(created.id)
|
|
} catch (e: any) {
|
|
error =
|
|
'Das Team wurde angelegt, die Standard-Flag-Typen aber nicht: ' +
|
|
(e.message ?? 'unbekannter Fehler') +
|
|
' Du kannst sie unter „Flag-Typen" nachholen.'
|
|
return
|
|
}
|
|
|
|
open = false
|
|
name = ''
|
|
} catch (e: any) {
|
|
error = e.message ?? 'Das Team konnte nicht angelegt werden.'
|
|
} finally {
|
|
busy = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<Dialog.Root bind:open>
|
|
<Dialog.Content>
|
|
<Dialog.Header>
|
|
<Dialog.Title>Neues Team</Dialog.Title>
|
|
<Dialog.Description>Du wirst automatisch Owner.</Dialog.Description>
|
|
</Dialog.Header>
|
|
<div class="space-y-4">
|
|
<div class="space-y-2">
|
|
<Label for="team-name">Name</Label>
|
|
<Input id="team-name" bind:value={name} placeholder="Mein Team" onkeydown={(e) => e.key === 'Enter' && submit()} />
|
|
</div>
|
|
{#if error}
|
|
<p class="text-sm text-destructive">{error}</p>
|
|
{/if}
|
|
</div>
|
|
<Dialog.Footer>
|
|
<Button variant="ghost" onclick={() => (open = false)}>Abbrechen</Button>
|
|
<Button onclick={submit} disabled={!name.trim() || busy}>Erstellen</Button>
|
|
</Dialog.Footer>
|
|
</Dialog.Content>
|
|
</Dialog.Root>
|