feat: add design persistence functionality with Auth0 and Supabase integration

- Implemented `useDesignPersistence` composable for managing design records.
- Enhanced `useSlipmatDesigner` to support loading designs from JSON.
- Created global authentication middleware for route protection.
- Added Supabase client plugin for database interactions.
- Developed API endpoints for fetching, saving, and retrieving designs.
- Introduced utility functions for Auth0 token verification and Supabase client retrieval.
- Updated Nuxt configuration to include Auth0 and Supabase environment variables.
- Added necessary dependencies for Auth0 and Supabase.
- Enhanced TypeScript configuration for improved type support.
This commit is contained in:
Frank John Begornia
2025-11-07 00:01:52 +08:00
parent e2955debb7
commit 4d91925fad
20 changed files with 1242 additions and 19 deletions

View File

@@ -4,12 +4,17 @@ const props = defineProps<{
templateLabel: string;
productionPixels: number;
isExporting: boolean;
projectName: string;
isSaving: boolean;
canSave: boolean;
}>();
const emit = defineEmits<{
(e: "download-preview"): void;
(e: "download-production"): void;
(e: "export"): void;
(e: "update:projectName", value: string): void;
(e: "save"): void;
}>();
const viewMode = ref<"flat" | "turntable">("flat");
@@ -23,6 +28,14 @@ const handleSelectView = (mode: "flat" | "turntable") => {
const handleExport = () => emit("export");
const handleDownloadPreview = () => emit("download-preview");
const handleDownloadProduction = () => emit("download-production");
const handleProjectNameInput = (event: Event) => {
const target = event.target as HTMLInputElement;
emit("update:projectName", target.value);
};
const handleSave = () => emit("save");
const isSaveDisabled = computed(
() => !props.previewUrl || props.isSaving || !props.canSave
);
</script>
<template>
@@ -95,6 +108,30 @@ const handleDownloadProduction = () => emit("download-production");
No preview yetstart designing!
</div>
</div>
<div class="mt-4 grid gap-3 md:grid-cols-[minmax(0,1fr)_auto] md:items-end">
<label class="flex flex-col gap-2">
<span class="text-xs font-semibold uppercase tracking-wide text-slate-400">
Project Name
</span>
<input
type="text"
class="w-full rounded-xl border border-slate-800 bg-slate-900 px-3 py-2 text-sm text-slate-100 shadow-inner shadow-black/20 focus:border-sky-500 focus:outline-none focus:ring-1 focus:ring-sky-500"
:value="props.projectName"
:disabled="props.isSaving"
maxlength="120"
placeholder="e.g. Midnight Mix Vol. 1"
@input="handleProjectNameInput"
/>
</label>
<button
type="button"
class="h-11 rounded-xl bg-emerald-500 px-6 text-sm font-semibold text-emerald-50 transition hover:bg-emerald-400 disabled:cursor-not-allowed disabled:bg-slate-700/70 disabled:text-slate-400"
:disabled="isSaveDisabled"
@click="handleSave"
>
{{ props.isSaving ? "Saving…" : "Save to Library" }}
</button>
</div>
<div class="mt-4 flex flex-wrap gap-3">
<button
type="button"