upload media modal

This commit is contained in:
2025-04-30 20:07:56 +02:00
parent 9b3930dcb6
commit aadb4098cc
3 changed files with 185 additions and 11 deletions

View File

@@ -1,17 +1,14 @@
<script lang="ts">
import type { components } from '$lib/api/api.gen';
import { video, photos, upload } from '$lib/paraglide/messages';
import UploadMediaModal from '$lib/profile/editors/UploadMediaModal.svelte';
export let person: components['schemas']['PersonProperties'];
export let editorMode = false;
let uploadModal = false;
let mediaType: 'audio' | 'video' | 'photo' | undefined = undefined;
</script>
{#if editorMode}
<button class="btn bg-neutral text-neutral-content btn-xs" on:click={() => {}}>
{upload()}
</button>
{/if}
{#if person.photos?.length || person.videos?.length}
<div class="divider">{photos()} & {video()}</div>
<div class="grid grid-cols-2 gap-4 md:grid-cols-4">
@@ -30,3 +27,43 @@
{/each}
</div>
{/if}
{#if editorMode}
<div class="divider">{upload()}</div>
<div class="grid grid-cols-2 gap-4">
<button
class="btn btn-soft btn-xs"
on:click={() => {
uploadModal = true;
mediaType = 'photo';
}}
>
{'+ '+photos()}
</button>
<button
class="btn btn-soft btn-xs"
on:click={() => {
uploadModal = true;
mediaType = 'video';
}}
>
{'+ '+video()}
</button>
</div>
{/if}
{#if uploadModal}
<UploadMediaModal
closeModal={() => {
uploadModal = false;
}}
{mediaType}
onCreation={(newMedia: { url: string; name: string; description: string; date: string }) => {
if (mediaType === 'photo') {
person.photos = [...(person.photos ?? []), newMedia];
} else if (mediaType === 'video') {
person.videos = [...(person.videos ?? []), newMedia];
}
}}
/>
{/if}

View File

@@ -1,4 +1,5 @@
<script lang="ts">
import { died } from './../paraglide/messages/en.js';
import { fade } from 'svelte/transition';
import ModalButtons from './ModalButtons.svelte';
@@ -11,7 +12,12 @@
let {
closeModal = () => {},
person = {}
}: { closeModal: () => void; person: components['schemas']['PersonProperties'] } = $props();
}: {
closeModal: () => void;
person: components['schemas']['PersonProperties'] & {
id?: string;
};
} = $props();
let editorMode = $state(false);
let draftPerson = $state({} as components['schemas']['PersonProperties']);
@@ -22,7 +28,9 @@
field: keyof components['schemas']['PersonProperties'],
value: any
) {
console.log('Draft person change:', field, value);
draftPerson[field] = value;
console.log('Draft person:', draftPerson);
}
function close() {
@@ -35,20 +43,48 @@
editorMode = !editorMode;
}
function save() {
// Save logic here
async function save() {
try {
const response = await fetch(`/api/person/${person.id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(draftPerson)
});
if (!response.ok) {
alert('Error saving person data, status: ' + response.status);
return;
}
if (response.status === 200) {
person = { ...person, ...draftPerson };
const data = (await response.json()) as {
person?: components['schemas']['Person'];
};
console.log('Person data updated successfully:', draftPerson);
console.log('Person data saved successfully:', data);
return;
} else {
const errorDetails = await response.json();
alert('Error saving person data, status: ' + response.status + ' ' + JSON.stringify(errorDetails));
}
} catch (error) {
alert('An unexpected error occurred: ' + error);
}
editorMode = false;
}
</script>
<div class="modal modal-open" transition:fade>
<div class="modal-box max-h-screen w-full max-w-5xl overflow-y-auto">
<div class="bg-base-100 sticky top-0 z-10">
<div class="bg-base-100 sticky top-0 z-7">
<ModalButtons {editorMode} onClose={close} onSave={save} onToggleEdit={toggleEdit} />
<div class="divider"></div>
</div>
<ProfileHeader {person} {editorMode} onChange={handleDraftPersonChange} />
<MediaGallery {person} />
<MediaGallery {person} {editorMode} />
<LifeEventsTimeline
person_life_events={person.life_events}
{editorMode}

View File

@@ -0,0 +1,101 @@
<script lang="ts">
import { date, description, file, media_title, title, upload } from '$lib/paraglide/messages';
export let closeModal: () => void;
export let onCreation:(newMedia:{
url: string,
name: string,
description: string,
date: string
}) => void = () => {};
export let mediaType: 'audio' | 'video' | 'photo' = 'photo';
let selectedFile: File | null = null;
let newMedia = {
url: '',
name: '',
description: '',
date: ''
};
// Determine accepted input types based on mediaType
$: acceptTypes =
mediaType === 'audio' ? 'audio/*' : mediaType === 'video' ? 'video/*' : 'image/*';
function handleFileChange(e: Event) {
const input = e.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
selectedFile = input.files[0];
}
}
async function uploadMedia() {
if (!selectedFile) {
alert('Please select a file');
return;
}
// Simulate file upload (replace with actual upload logic)
newMedia.url = URL.createObjectURL(selectedFile);
// Emit event using custom dispatch
const uploadEvent = new CustomEvent('upload', {
detail: { ...newMedia }
});
dispatchEvent(uploadEvent);
// Clean up
selectedFile = null;
newMedia = { url: '', name: '', description: '', date: '' };
onCreation(newMedia);
closeModal();
}
</script>
<div class="modal modal-open z-8">
<div class="modal-box w-full max-w-xl">
<h3 class="text-lg font-bold">{upload()+mediaType}</h3>
<div class="form-control mt-4">
<label for="mfile" class="label">{upload() + ' ' + file()}</label>
<input
id="mfile"
type="file"
accept={acceptTypes}
class="file-input file-input-bordered w-full"
on:change={handleFileChange}
/>
</div>
<div class="form-control mt-4">
<label for="mtitle" class="label">{media_title()}</label>
<input id="mtitle" bind:value={newMedia.name} class="input input-bordered w-full" />
</div>
<div class="form-control mt-4">
<label for="mdesc" class="label">{description()}</label>
<textarea
id="mdesc"
bind:value={newMedia.description}
class="textarea textarea-bordered w-full"
>
</textarea>
</div>
<div class="form-control mt-4">
<label for="mdate" class="label">{date()}</label>
<input
id="mdate"
type="date"
bind:value={newMedia.date}
class="input input-bordered w-full"
/>
</div>
<div class="modal-action">
<button class="btn btn-outline" on:click={closeModal}>Cancel</button>
<button class="btn btn-primary" on:click={uploadMedia}>Upload</button>
</div>
</div>
</div>