From c9cab93d129b7b58f8885747ee3c4f562756986a Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Fri, 20 Mar 2026 00:35:36 +0300 Subject: [PATCH] feat: port original frontend UI to Notify Bridge Port the full polished frontend from Immich Watcher: - Sidebar layout with collapsible nav, mobile bottom nav - Login/setup pages with gradient mesh background, animations - 11 reusable components: Card, Modal, ConfirmModal, Snackbar, IconPicker, JinjaEditor, MdiIcon, PageHeader, Loading, Hint, IconButton - Auth state with getAuth() reactive pattern, token refresh - Theme: light/dark/system with media query listener - i18n: EN/RU with nested JSON, auto-detect locale - Snackbar notification store Branding changes: - "Immich Watcher" -> "Notify Bridge" - /servers -> /providers in nav and routes - Login icon: mdiEye -> mdiLan Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/routes/+error.svelte | 13 + frontend/src/routes/+layout.svelte | 301 ++++++++++++++++-- frontend/src/routes/+page.svelte | 25 +- frontend/src/routes/login/+page.svelte | 273 ++++++++++++++-- .../src/routes/providers/new/+page.svelte | 133 ++++++++ frontend/src/routes/setup/+page.svelte | 237 ++++++++++++-- 6 files changed, 895 insertions(+), 87 deletions(-) create mode 100644 frontend/src/routes/+error.svelte create mode 100644 frontend/src/routes/providers/new/+page.svelte diff --git a/frontend/src/routes/+error.svelte b/frontend/src/routes/+error.svelte new file mode 100644 index 0000000..983436b --- /dev/null +++ b/frontend/src/routes/+error.svelte @@ -0,0 +1,13 @@ + + +
+
+

{page.status}

+

{page.error?.message || 'Page not found'}

+ + Go home + +
+
diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 7ddbf6b..22b9798 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -1,33 +1,294 @@ -{#if !mounted || isLoading()} +{#if isAuthPage} + {@render children()} +{:else if auth.loading}
-

Loading...

+
+
+

{t('common.loading')}

+
+
+{:else if auth.user} +
+ + + + + + + +
+ {#key page.url.pathname} +
+ {@render children()} +
+ {/key} +
{:else} - {@render children()} +
+
+
+

{t('common.loading')}

+
+
{/if} + + + { showPasswordForm = false; pwdMsg = ''; pwdSuccess = false; }}> +
+
+ + +
+
+ + +
+ {#if pwdMsg} +

{pwdMsg}

+ {/if} + +
+
+ + + + diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 6a4cd9a..18492f9 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,18 +1,13 @@ - -
-
-

{t('app.name')}

-

{t('app.tagline')}

- -
+ + +
+

{t('dashboard.noEvents')}

diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index b6d0762..2660884 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -1,47 +1,272 @@ -
-
-

{t('app.name')}

+
+ +
+
-
{ e.preventDefault(); handleLogin(); }} class="space-y-4"> -
- - + +
+
+ +
+ +
-
- - + + +
+
+ +
+

+ Notify Bridge +

+

{t('auth.signInTitle')}

{#if error} -

{error}

+
+ + {error} +
{/if} - - +
+
+ + +
+
+ + +
+ +
+
+ + diff --git a/frontend/src/routes/providers/new/+page.svelte b/frontend/src/routes/providers/new/+page.svelte new file mode 100644 index 0000000..c17091e --- /dev/null +++ b/frontend/src/routes/providers/new/+page.svelte @@ -0,0 +1,133 @@ + + +
+ + +

{t('provider.addProvider')}

+ +
+ +
+ + +
+ + +
+ + +
+ + {#if providerType === 'immich'} + +
+ + +
+ + +
+ + +
+ + +
+ + +

Public-facing URL for notification links. Falls back to server URL.

+
+ {/if} + + {#if error} +

{error}

+ {/if} + + {#if testResult} +
+ {testResult.message} +
+ {/if} + +
+ + + + {t('common.cancel')} + +
+
+
diff --git a/frontend/src/routes/setup/+page.svelte b/frontend/src/routes/setup/+page.svelte index fbc44f0..d754808 100644 --- a/frontend/src/routes/setup/+page.svelte +++ b/frontend/src/routes/setup/+page.svelte @@ -1,48 +1,229 @@ -
-
-

{t('app.name')}

-

Create your admin account

+
+
+
-
{ e.preventDefault(); handleSetup(); }} class="space-y-4"> -
- - -
-
- - +
+
+
+
+ +
+

+ Notify Bridge +

+

{t('auth.setupDescription')}

{#if error} -

{error}

+
+ + {error} +
{/if} - - +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +