diff --git a/packages/frontend/src/lib/i18n/locales/en.ts b/packages/frontend/src/lib/i18n/locales/en.ts
index c6c6805..84725b0 100644
--- a/packages/frontend/src/lib/i18n/locales/en.ts
+++ b/packages/frontend/src/lib/i18n/locales/en.ts
@@ -91,6 +91,23 @@ export default {
me: {
title: "Dashboard",
welcome: "Welcome back, {name}",
+ nav: {
+ profile: "Profile",
+ security: "Security",
+ recordings: "Recordings",
+ analytics: "Analytics",
+ back_to_site: "← Back to site",
+ back_mobile: "← Back",
+ },
+ analytics: {
+ title: "Analytics",
+ description: "Track your content performance and audience engagement",
+ total_videos: "Total Videos",
+ total_likes: "Total Likes",
+ total_plays: "Total Plays",
+ video_performance: "Video Performance",
+ video_performance_description: "Detailed metrics for each video",
+ },
view_profile: "View Public Profile",
settings: {
title: "Settings",
diff --git a/packages/frontend/src/routes/me/+layout.server.ts b/packages/frontend/src/routes/me/+layout.server.ts
new file mode 100644
index 0000000..341546d
--- /dev/null
+++ b/packages/frontend/src/routes/me/+layout.server.ts
@@ -0,0 +1,12 @@
+import { redirect } from "@sveltejs/kit";
+import { isModel } from "$lib/api";
+
+export async function load({ locals }) {
+ if (!locals.authStatus.authenticated) {
+ throw redirect(302, "/login");
+ }
+ return {
+ authStatus: locals.authStatus,
+ isModel: isModel(locals.authStatus.user!),
+ };
+}
diff --git a/packages/frontend/src/routes/me/+layout.svelte b/packages/frontend/src/routes/me/+layout.svelte
new file mode 100644
index 0000000..89d2524
--- /dev/null
+++ b/packages/frontend/src/routes/me/+layout.svelte
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {@render children()}
+
+
+
+
diff --git a/packages/frontend/src/routes/me/+page.server.ts b/packages/frontend/src/routes/me/+page.server.ts
index 04741dc..17cef2d 100644
--- a/packages/frontend/src/routes/me/+page.server.ts
+++ b/packages/frontend/src/routes/me/+page.server.ts
@@ -1,25 +1,4 @@
import { redirect } from "@sveltejs/kit";
-import { getAnalytics, getFolders, getRecordings } from "$lib/services";
-import { isModel } from "$lib/api";
-
-export async function load({ locals, fetch }) {
- // Redirect to login if not authenticated
- if (!locals.authStatus.authenticated) {
- throw redirect(302, "/login");
- }
-
- const recordings = await getRecordings(fetch).catch(() => []);
-
- const analytics = isModel(locals.authStatus.user!)
- ? await getAnalytics(fetch).catch(() => null)
- : null;
-
- const folders = await getFolders(fetch).catch(() => []);
-
- return {
- authStatus: locals.authStatus,
- folders,
- recordings,
- analytics,
- };
+export function load() {
+ throw redirect(302, "/me/profile");
}
diff --git a/packages/frontend/src/routes/me/+page.svelte b/packages/frontend/src/routes/me/+page.svelte
index fd1c8f9..e69de29 100644
--- a/packages/frontend/src/routes/me/+page.svelte
+++ b/packages/frontend/src/routes/me/+page.svelte
@@ -1,690 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
{$_("me.title")}
-
- {$_("me.welcome", { values: { name: data.authStatus.user!.artist_name } })}
-
-
- {#if isModel(data.authStatus.user!)}
-
- {/if}
-
-
-
-
-
-
-
- {$_("me.settings.title")}
-
-
-
- {$_("me.recordings.title")}
-
- {#if data.analytics}
-
-
- Analytics
-
- {/if}
-
-
-
-
-
-
-
-
- {$_("me.settings.profile_title")}
- {$_("me.settings.profile_subtitle")}
-
-
-
-
-
-
-
-
-
- {$_("me.settings.privacy_title")}
- {$_("me.settings.privacy_subtitle")}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {$_("me.recordings.title")}
-
-
- {$_("me.recordings.description")}
-
-
-
-
-
- {#if recordings.length === 0}
-
-
-
-
-
-
-
- {$_("me.recordings.no_recordings")}
-
-
- {$_("me.recordings.no_recordings_description")}
-
-
-
-
-
- {:else}
-
- {#each recordings as recording (recording.id)}
-
- {/each}
-
- {/if}
-
-
-
- {#if data.analytics}
-
-
-
Analytics Dashboard
-
- Track your content performance and audience engagement
-
-
-
-
-
-
-
-
-
- Total Videos
-
-
-
- {data.analytics.total_videos}
-
-
-
-
-
-
- Total Likes
-
-
-
- {data.analytics.total_likes.toLocaleString()}
-
-
-
-
-
-
- Total Plays
-
-
-
- {data.analytics.total_plays.toLocaleString()}
-
-
-
-
-
-
-
- Video Performance
- Detailed metrics for each video
-
-
-
-
-
-
- | Title |
- Likes |
- Plays |
- Completion Rate |
- Avg Watch Time |
-
-
-
- {#each data.analytics.videos as video (video.slug)}
-
- |
-
- {video.title}
-
- |
-
- {video.likes}
- |
-
- {video.plays}
- |
-
-
- {video.completion_rate.toFixed(1)}%
-
- |
-
- {Math.floor(video.avg_watch_time / 60)}:{(video.avg_watch_time % 60)
- .toString()
- .padStart(2, "0")}
- |
-
- {/each}
-
-
-
-
-
-
- {/if}
-
-
-
-
-
-
-
- {$_("me.recordings.delete_confirm")}
- This cannot be undone.
-
-
-
-
-
-
-
diff --git a/packages/frontend/src/routes/me/analytics/+page.server.ts b/packages/frontend/src/routes/me/analytics/+page.server.ts
new file mode 100644
index 0000000..4d6019f
--- /dev/null
+++ b/packages/frontend/src/routes/me/analytics/+page.server.ts
@@ -0,0 +1,12 @@
+import { redirect } from "@sveltejs/kit";
+import { isModel } from "$lib/api";
+import { getAnalytics } from "$lib/services";
+
+export async function load({ locals, fetch }) {
+ if (!isModel(locals.authStatus.user!)) {
+ throw redirect(302, "/me/profile");
+ }
+ return {
+ analytics: await getAnalytics(fetch).catch(() => null),
+ };
+}
diff --git a/packages/frontend/src/routes/me/analytics/+page.svelte b/packages/frontend/src/routes/me/analytics/+page.svelte
new file mode 100644
index 0000000..2a6967e
--- /dev/null
+++ b/packages/frontend/src/routes/me/analytics/+page.svelte
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
{$_("me.analytics.title")}
+
{$_("me.analytics.description")}
+
+
+
+
+ {#if data.analytics}
+
+
+
+
+
+
+ {$_("me.analytics.total_videos")}
+
+
+
+ {data.analytics.total_videos}
+
+
+
+
+
+
+
+ {$_("me.analytics.total_likes")}
+
+
+
+ {data.analytics.total_likes.toLocaleString()}
+
+
+
+
+
+
+
+ {$_("me.analytics.total_plays")}
+
+
+
+ {data.analytics.total_plays.toLocaleString()}
+
+
+
+
+
+
+
+ {$_("me.analytics.video_performance")}
+ {$_("me.analytics.video_performance_description")}
+
+
+
+
+
+
+ | Title |
+ Likes |
+ Plays |
+ Completion Rate |
+ Avg Watch Time |
+
+
+
+ {#each data.analytics.videos as video (video.slug)}
+
+ |
+
+ {video.title}
+
+ |
+
+ {video.likes}
+ |
+
+ {video.plays}
+ |
+
+
+ {video.completion_rate.toFixed(1)}%
+
+ |
+
+ {Math.floor(video.avg_watch_time / 60)}:{(video.avg_watch_time % 60)
+ .toString()
+ .padStart(2, "0")}
+ |
+
+ {/each}
+
+
+
+
+
+ {:else}
+
+
+
+
+
+
+
No analytics available
+
+ Analytics data will appear here once your content starts getting views.
+
+
+
+
+ {/if}
+
+
diff --git a/packages/frontend/src/routes/me/profile/+page.svelte b/packages/frontend/src/routes/me/profile/+page.svelte
new file mode 100644
index 0000000..2162669
--- /dev/null
+++ b/packages/frontend/src/routes/me/profile/+page.svelte
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
{$_("me.settings.profile_title")}
+ {#if isModel(data.authStatus.user!)}
+
+ {/if}
+
+
+
+
+
+ {$_("me.settings.profile_title")}
+ {$_("me.settings.profile_subtitle")}
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/routes/me/recordings/+page.server.ts b/packages/frontend/src/routes/me/recordings/+page.server.ts
new file mode 100644
index 0000000..c87da3e
--- /dev/null
+++ b/packages/frontend/src/routes/me/recordings/+page.server.ts
@@ -0,0 +1,7 @@
+import { getRecordings } from "$lib/services";
+
+export async function load({ fetch }) {
+ return {
+ recordings: await getRecordings(fetch).catch(() => []),
+ };
+}
diff --git a/packages/frontend/src/routes/me/recordings/+page.svelte b/packages/frontend/src/routes/me/recordings/+page.svelte
new file mode 100644
index 0000000..30da96c
--- /dev/null
+++ b/packages/frontend/src/routes/me/recordings/+page.svelte
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
{$_("me.recordings.title")}
+
+
+
+
+ {#if recordings.length === 0}
+
+
+
+
+
+
+
+ {$_("me.recordings.no_recordings")}
+
+
+ {$_("me.recordings.no_recordings_description")}
+
+
+
+
+
+ {:else}
+
+ {#each recordings as recording (recording.id)}
+
+ {/each}
+
+ {/if}
+
+
+
+
+
+
+ {$_("me.recordings.delete_confirm")}
+ This cannot be undone.
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/routes/me/security/+page.svelte b/packages/frontend/src/routes/me/security/+page.svelte
new file mode 100644
index 0000000..0971bdf
--- /dev/null
+++ b/packages/frontend/src/routes/me/security/+page.svelte
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
{$_("me.settings.privacy_title")}
+
+
+
+
+
+ {$_("me.settings.privacy_title")}
+ {$_("me.settings.privacy_subtitle")}
+
+
+
+
+
+
+