109 lines
3.3 KiB
Svelte
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>
|