143 lines
3.6 KiB
Svelte
143 lines
3.6 KiB
Svelte
<script lang="ts">
|
|
import { X, FolderPlus } from 'lucide-svelte';
|
|
import { Button } from '$lib/components/ui/button';
|
|
import { Input } from '$lib/components/ui/input';
|
|
import { Label } from '$lib/components/ui/label';
|
|
import { enhance } from '$app/forms';
|
|
import { invalidateAll } from '$app/navigation';
|
|
|
|
let {
|
|
parentFolderId = null,
|
|
onClose,
|
|
onSuccess
|
|
}: {
|
|
parentFolderId?: string | null;
|
|
onClose: () => void;
|
|
onSuccess?: () => void;
|
|
} = $props();
|
|
|
|
let isSubmitting = $state(false);
|
|
let folderName = $state('');
|
|
let visibility = $state('members');
|
|
|
|
function handleKeydown(e: KeyboardEvent) {
|
|
if (e.key === 'Escape') {
|
|
onClose();
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:window onkeydown={handleKeydown} />
|
|
|
|
<!-- Modal Backdrop -->
|
|
<div
|
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="create-folder-title"
|
|
>
|
|
<!-- Modal Content -->
|
|
<div class="w-full max-w-md rounded-2xl bg-white shadow-xl">
|
|
<!-- Header -->
|
|
<div class="flex items-center justify-between border-b border-slate-200 px-6 py-4">
|
|
<div class="flex items-center gap-3">
|
|
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-amber-100 text-amber-600">
|
|
<FolderPlus class="h-5 w-5" />
|
|
</div>
|
|
<h2 id="create-folder-title" class="text-lg font-semibold text-slate-900">
|
|
Create New Folder
|
|
</h2>
|
|
</div>
|
|
<button
|
|
onclick={onClose}
|
|
class="rounded-lg p-2 text-slate-400 hover:bg-slate-100 hover:text-slate-600"
|
|
aria-label="Close"
|
|
>
|
|
<X class="h-5 w-5" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Form -->
|
|
<form
|
|
method="POST"
|
|
action="?/createFolder"
|
|
use:enhance={() => {
|
|
isSubmitting = true;
|
|
return async ({ result, update }) => {
|
|
await invalidateAll();
|
|
isSubmitting = false;
|
|
if (result.type === 'success') {
|
|
onClose();
|
|
onSuccess?.();
|
|
}
|
|
await update();
|
|
};
|
|
}}
|
|
class="p-6 space-y-4"
|
|
>
|
|
{#if parentFolderId}
|
|
<input type="hidden" name="parent_id" value={parentFolderId} />
|
|
{/if}
|
|
|
|
<div class="space-y-2">
|
|
<Label for="folder-name">Folder Name</Label>
|
|
<Input
|
|
id="folder-name"
|
|
name="name"
|
|
type="text"
|
|
bind:value={folderName}
|
|
placeholder="Enter folder name..."
|
|
required
|
|
autofocus
|
|
disabled={isSubmitting}
|
|
class="h-11"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="folder-visibility">Visibility</Label>
|
|
<select
|
|
id="folder-visibility"
|
|
name="visibility"
|
|
bind:value={visibility}
|
|
disabled={isSubmitting}
|
|
class="w-full h-11 rounded-lg border border-slate-200 bg-white px-3 text-sm focus:border-monaco-500 focus:outline-none focus:ring-2 focus:ring-monaco-500/20"
|
|
>
|
|
<option value="members">Members Only</option>
|
|
<option value="board">Board Only</option>
|
|
<option value="admin">Admin Only</option>
|
|
<option value="public">Public</option>
|
|
</select>
|
|
<p class="text-xs text-slate-500">
|
|
Who can see this folder and its contents
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div class="flex justify-end gap-3 pt-4">
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onclick={onClose}
|
|
disabled={isSubmitting}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
type="submit"
|
|
variant="monaco"
|
|
disabled={isSubmitting || !folderName.trim()}
|
|
>
|
|
{#if isSubmitting}
|
|
<div class="mr-2 h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
|
|
Creating...
|
|
{:else}
|
|
<FolderPlus class="mr-2 h-4 w-4" />
|
|
Create Folder
|
|
{/if}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|