nexus-5-frontend-2/src/lib/components/session/SessionMediaUploadForm.svelte
2026-01-26 11:28:04 -05:00

109 lines
3.3 KiB
Svelte

<script lang="ts">
type MediaType = 'photo' | 'video';
interface Props {
mediaType: MediaType;
onUpload: (file: File, title: string, notes: string, internal: boolean) => Promise<void>;
onCancel: () => void;
}
let { mediaType, onUpload, onCancel }: Props = $props();
let file = $state<File | null>(null);
let title = $state('');
let notes = $state('');
let internal = $state(true);
let submitting = $state(false);
function handleFileSelect(event: Event) {
const input = event.target as HTMLInputElement;
if (input.files && input.files[0]) {
file = input.files[0];
}
}
async function handleUpload() {
if (!file) return;
try {
submitting = true;
// Use filename as default title if not provided
const finalTitle = title || file.name;
await onUpload(file, finalTitle, notes, internal);
} catch (err) {
console.error(`Failed to upload ${mediaType}:`, err);
} finally {
submitting = false;
}
}
function handleCancel() {
file = null;
title = '';
notes = '';
internal = true;
onCancel();
}
let isPhoto = $derived(mediaType === 'photo');
let acceptType = $derived(isPhoto ? 'image/*' : 'video/*');
let uploadLabel = $derived(isPhoto ? 'Upload Photo' : 'Upload Video');
</script>
<div class="w-full space-y-4">
<h3 class="text-xl font-semibold text-[rgb(var(--text-primary))]">
{uploadLabel}
</h3>
<div>
<input
type="file"
accept={acceptType}
onchange={handleFileSelect}
class="w-full rounded-lg border border-[rgb(var(--border))] bg-[rgb(var(--surface-secondary))] p-3 text-[rgb(var(--text-primary))] file:mr-4 file:rounded file:border-0 file:bg-primary-500 file:px-4 file:py-2 file:text-sm file:font-medium file:text-white"
/>
</div>
{#if file}
<p class="text-sm text-[rgb(var(--text-secondary))]">
Selected: {file.name}
</p>
{/if}
<input
type="text"
bind:value={title}
placeholder="Title (optional - defaults to filename)"
class="w-full rounded-lg border border-[rgb(var(--border))] bg-[rgb(var(--surface-secondary))] p-3 text-[rgb(var(--text-primary))] placeholder-[rgb(var(--text-secondary))] focus:border-primary-500 focus:outline-none"
/>
<textarea
bind:value={notes}
placeholder="Notes (optional)"
rows="2"
class="w-full rounded-lg border border-[rgb(var(--border))] bg-[rgb(var(--surface-secondary))] p-3 text-[rgb(var(--text-primary))] placeholder-[rgb(var(--text-secondary))] focus:border-primary-500 focus:outline-none"
></textarea>
<div class="flex items-center gap-2">
<input
type="checkbox"
id="{mediaType}-internal"
bind:checked={internal}
class="h-4 w-4 rounded border-[rgb(var(--border))] text-primary-500 focus:ring-primary-500"
/>
<label for="{mediaType}-internal" class="text-sm text-[rgb(var(--text-secondary))]">
Internal (not visible to customer)
</label>
</div>
<div class="flex justify-end gap-3">
<button
onclick={handleCancel}
class="rounded-lg px-4 py-2 text-sm font-medium text-[rgb(var(--text-secondary))] transition-colors hover:text-[rgb(var(--text-primary))]"
>
Cancel
</button>
<button
onclick={handleUpload}
disabled={submitting || !file}
class="rounded-lg bg-primary-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-primary-600 disabled:cursor-not-allowed disabled:opacity-50"
>
{submitting ? 'Uploading...' : 'Upload'}
</button>
</div>
</div>