diff --git a/client/jsconfig.json b/client/jsconfig.json index e596c58..064fccf 100644 --- a/client/jsconfig.json +++ b/client/jsconfig.json @@ -30,4 +30,4 @@ * to avoid limiting type declarations. */ "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] -} +} \ No newline at end of file diff --git a/client/src/App.svelte b/client/src/App.svelte index 614b057..3dda031 100644 --- a/client/src/App.svelte +++ b/client/src/App.svelte @@ -3,7 +3,10 @@ import Auth from './lib/Auth.svelte'; import Dashboard from './lib/Dashboard.svelte'; import AdminPanel from './lib/AdminPanel.svelte'; + import ThemeSwitcher from './lib/ThemeSwitcher.svelte'; import { API_BASE } from './config.js'; + import { applyTheme, currentTheme } from './stores/theme.js'; + import { get } from 'svelte/store'; let isAuthenticated = false; let user = null; @@ -11,9 +14,11 @@ let showAdminPanel = false; onMount(() => { + applyTheme(get(currentTheme)); + const storedAuth = localStorage.getItem('auth_token'); const storedUser = localStorage.getItem('user_data'); - + if (storedAuth && storedUser) { try { isAuthenticated = true; @@ -89,6 +94,7 @@
{#if isAuthenticated && user} + {#if showAdminPanel && user.is_admin}
@@ -120,20 +126,22 @@ .admin-header, .admin-link { padding: 10px 20px; - background-color: #f8f9fa; - border-bottom: 1px solid #ddd; + background-color: var(--snow); + border-bottom: 1px solid var(--smoke); } .admin-header button, .admin-link button { padding: 8px 16px; - background-color: #007bff; - color: white; + background-color: var(--blue); + color: var(--white); border: none; border-radius: 4px; cursor: pointer; + transition: all 0.2s ease; } .admin-header button:hover, .admin-link button:hover { - background-color: #0056b3; + background-color: var(--cyan); + transform: translateY(-1px); } \ No newline at end of file diff --git a/client/src/app.css b/client/src/app.css index dcf9269..a43fe1f 100644 --- a/client/src/app.css +++ b/client/src/app.css @@ -96,3 +96,64 @@ button { input, textarea, select { font-family: 'Phantom Sans', sans-serif; } + +[data-theme="darkGradient"] body { + background: linear-gradient(135deg, #0a0f1a 0%, #0f1a2a 25%, #1a2a3a 50%, #0f1a2a 75%, #0a0f1a 100%); + background-size: 400% 400%; + animation: gradientShift 15s ease infinite; +} + +[data-theme="lgbtq"] body { + position: relative; + background: + radial-gradient(circle at 20% 80%, rgba(228, 3, 3, 0.8) 0%, transparent 50%), + radial-gradient(circle at 80% 20%, rgba(255, 140, 0, 0.8) 0%, transparent 50%), + radial-gradient(circle at 40% 40%, rgba(255, 237, 0, 0.8) 0%, transparent 40%), + radial-gradient(circle at 80% 80%, rgba(0, 128, 38, 0.8) 0%, transparent 50%), + radial-gradient(circle at 20% 20%, rgba(36, 64, 142, 0.8) 0%, transparent 50%), + radial-gradient(circle at 60% 60%, rgba(115, 41, 130, 0.8) 0%, transparent 40%), + linear-gradient(135deg, #1a0616 0%, #2a0a26 100%); + background-size: 200% 200%; + animation: prideShift 30s ease infinite; +} + +[data-theme="lgbtq"] .dashboard, +[data-theme="lgbtq"] .auth-container, +[data-theme="lgbtq"] .create-form, +[data-theme="lgbtq"] .space-card, +[data-theme="lgbtq"] .theme-menu, +[data-theme="lgbtq"] .theme-toggle { + background: rgba(26, 6, 22, 0.7) !important; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); +} + +[data-theme="lgbtq"] .auth-form-panel { + background: rgba(26, 6, 22, 0.8) !important; + backdrop-filter: blur(30px); + -webkit-backdrop-filter: blur(30px); +} + +@keyframes gradientShift { + 0%, 100% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } +} + +@keyframes prideShift { + 0%, 100% { + background-position: 0% 0%; + } + 25% { + background-position: 100% 0%; + } + 50% { + background-position: 100% 100%; + } + 75% { + background-position: 0% 100%; + } +} diff --git a/client/src/assets/flag.svg b/client/src/assets/flag.svg new file mode 100644 index 0000000..a18907f --- /dev/null +++ b/client/src/assets/flag.svg @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/client/src/lib/Auth.svelte b/client/src/lib/Auth.svelte index d2e70da..50e86bc 100644 --- a/client/src/lib/Auth.svelte +++ b/client/src/lib/Auth.svelte @@ -35,7 +35,21 @@ message = 'Verification code sent to your email!'; mode = 'verify'; } else { - error = data.message || 'Failed to send verification code'; + if (response.status === 404 && mode === 'login') { + error = "We couldn't find your account. Let's create one!"; + setTimeout(() => { + error = ''; + authIntent = 'signup'; + setTimeout(() => { + mode = 'signup'; + }, 400); + setTimeout(() => { + displayMode = 'signup'; + }, 800); + }, 1500); + } else { + error = data.message || 'Failed to send verification code'; + } } } catch (err) { error = ERROR_MESSAGES.NETWORK_ERROR; @@ -128,19 +142,21 @@ Hack Club -
+
- +

{displayMode === 'signup' ? 'Join Hack Club Spaces' : 'Welcome Back'}

-

Lorem ipsum dolor sit amet

+

Build amazing projects in the cloud

{#if mode === 'login' || mode === 'signup'}
- +
- + {message}
{/if} - @@ -184,12 +202,56 @@ Already have an account? switchMode('login')} on:keypress={(e) => e.key === 'Enter' && switchMode('login')} role="button" tabindex="0">Log in {/if}
- {:else if mode === 'verify'} -

Check your email for the verification code

+ {/if} -
+ {#if authIntent === 'signup'} +
+
+

Check your email

+

We sent a verification code to {email}

+
+ + +
+ + +
+ + {#if error} +
{error}
+ {/if} + + + + + +
+ {/if} + + {#if mode === 'verify' && authIntent === 'login'} +
+

Check your email

+

We sent a verification code to {email}

+
+ +
- + - {loading ? 'Verifying...' : authIntent === 'signup' ? 'Complete Sign Up' : 'Login'} + {loading ? 'Verifying...' : 'Login'} - diff --git a/client/src/lib/Dashboard.svelte b/client/src/lib/Dashboard.svelte index 2f2114c..fd7c8f8 100644 --- a/client/src/lib/Dashboard.svelte +++ b/client/src/lib/Dashboard.svelte @@ -1,7 +1,10 @@ + + + +
+ + + {#if isOpen} +
+ {#each Object.entries(themes) as [key, theme]} + + {/each} +
+ {/if} +
+ + diff --git a/client/src/stores/theme.js b/client/src/stores/theme.js new file mode 100644 index 0000000..9c0561e --- /dev/null +++ b/client/src/stores/theme.js @@ -0,0 +1,37 @@ +import { writable } from 'svelte/store'; +import { themes, defaultTheme } from '../themes.js'; + +const getInitialTheme = () => { + if (typeof window !== 'undefined') { + const saved = localStorage.getItem('theme'); + return saved && themes[saved] ? saved : defaultTheme; + } + return defaultTheme; +}; + +export const currentTheme = writable(getInitialTheme()); + +export const setTheme = (themeName) => { + if (themes[themeName]) { + currentTheme.set(themeName); + if (typeof window !== 'undefined') { + localStorage.setItem('theme', themeName); + applyTheme(themeName); + } + } +}; + +export const applyTheme = (themeName) => { + const theme = themes[themeName]; + if (theme && typeof document !== 'undefined') { + const root = document.documentElement; + Object.entries(theme.colors).forEach(([key, value]) => { + root.style.setProperty(key, value); + }); + root.setAttribute('data-theme', themeName); + } +}; + +if (typeof window !== 'undefined') { + applyTheme(getInitialTheme()); +} diff --git a/client/src/styles/auth.css b/client/src/styles/auth.css index 7b9f874..6700954 100644 --- a/client/src/styles/auth.css +++ b/client/src/styles/auth.css @@ -1,7 +1,7 @@ .auth-container { display: flex; min-height: 100vh; - background: #f9fafc; + background: var(--snow); position: relative; overflow: hidden; } @@ -18,13 +18,13 @@ } .auth-form-panel { - background: #ffffff; + background: var(--white); left: 0; padding: 64px; } .auth-image-panel { - background: #f9fafc; + background: var(--snow); right: 0; padding: 0; } @@ -37,6 +37,15 @@ right: 50%; } +.auth-container.verify-mode:not(.signup-mode) .auth-image-content { + opacity: 0.6; +} + +.auth-container.verify-mode:not(.signup-mode) .auth-image-content::before { + background: linear-gradient(to bottom, rgba(51, 142, 218, 0.4) 0%, transparent 60%); + height: 200px; +} + .auth-form-content { width: 100%; max-width: 440px; @@ -84,13 +93,13 @@ left: 32px; font-size: 16px; font-weight: bold; - color: #ffffff; + color: var(--white); z-index: 2; text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); } .image-caption a { - color: #ffffff; + color: var(--white); text-decoration: underline; transition: opacity 0.125s ease-in-out; } @@ -121,7 +130,7 @@ .auth-title { font-size: 36px; font-weight: bold; - color: #1f2d3d; + color: var(--black); margin: 0 0 8px 0; line-height: 1.2; transition: opacity 0.3s ease-in-out; @@ -129,7 +138,7 @@ .auth-subtitle { font-size: 18px; - color: #8492a6; + color: var(--muted); margin: 0; line-height: 1.5; transition: opacity 0.3s ease-in-out; @@ -139,11 +148,11 @@ text-align: center; margin-top: 24px; font-size: 16px; - color: #8492a6; + color: var(--muted); } .auth-mode-link { - color: #ec3750; + color: var(--red); font-weight: bold; cursor: pointer; transition: color 0.125s ease-in-out; @@ -151,7 +160,7 @@ } .auth-mode-link:hover { - color: #ff8c37; + color: var(--orange); } .form-group { @@ -173,20 +182,30 @@ } .form-label { - display: block; + display: inline-flex; + align-items: center; + gap: 8px; margin-bottom: 8px; font-size: 16px; font-weight: bold; - color: #1f2d3d; + color: var(--black); +} + +.label-icon { + width: 18px; + height: 18px; + flex-shrink: 0; + display: inline-block; + vertical-align: middle; } .form-input { width: 100%; padding: 14px 16px; - border: 2px solid #e0e6ed; + border: 2px solid var(--smoke); border-radius: 8px; - background: #ffffff; - color: #1f2d3d; + background: var(--white); + color: var(--black); font-size: 16px; font-family: Phantom Sans, sans-serif; box-sizing: border-box; @@ -195,12 +214,12 @@ .form-input:focus { outline: none; - border-color: #338eda; + border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51, 142, 218, 0.1); } .form-input::placeholder { - color: #8492a6; + color: var(--muted); } .primary-button { @@ -209,8 +228,8 @@ margin-top: 8px; border: none; border-radius: 99999px; - background: #ec3750; - color: #ffffff; + background: var(--red); + color: var(--white); font-size: 18px; font-weight: bold; font-family: Phantom Sans, sans-serif; @@ -242,9 +261,9 @@ padding: 16px 32px; margin-top: 16px; background: transparent; - border: 2px solid #ec3750; + border: 2px solid var(--red); border-radius: 99999px; - color: #ec3750; + color: var(--red); font-size: 18px; font-weight: bold; font-family: Phantom Sans, sans-serif; @@ -269,9 +288,9 @@ padding: 12px 16px; margin-bottom: 16px; background: rgba(236, 55, 80, 0.1); - border: 2px solid #ec3750; + border: 2px solid var(--red); border-radius: 8px; - color: #ec3750; + color: var(--red); font-size: 16px; } @@ -279,19 +298,64 @@ padding: 12px 16px; margin-bottom: 16px; background: rgba(51, 214, 166, 0.1); - border: 2px solid #33d6a6; + border: 2px solid var(--green); border-radius: 8px; - color: #33d6a6; + color: var(--green); font-size: 16px; } .info-message { text-align: center; margin-bottom: 24px; - color: #8492a6; + color: var(--muted); font-size: 16px; } +.verification-notice { + padding: 20px; + margin-bottom: 24px; + background: rgba(51, 142, 218, 0.05); + border: 2px solid rgba(51, 142, 218, 0.2); + border-radius: 12px; +} + +.verification-title { + margin: 0 0 8px 0; + font-size: 18px; + font-weight: bold; + color: var(--black); +} + +.verification-text { + margin: 0; + font-size: 16px; + color: var(--muted); + line-height: 1.5; +} + +.verification-text strong { + color: var(--blue); + font-weight: bold; +} + +.verification-code-section { + max-height: 0; + opacity: 0; + overflow: hidden; + margin-top: 0; + padding-top: 0; + border-top: 2px solid transparent; + transition: opacity 0.4s ease-in-out, max-height 0.6s ease-in-out, margin-top 0.6s ease-in-out, padding-top 0.6s ease-in-out, border-color 0.3s ease-in-out; +} + +.verification-code-section.show { + max-height: 1000px; + opacity: 1; + margin-top: 32px; + padding-top: 32px; + border-top-color: var(--smoke); +} + @media (max-width: 768px) { .auth-container { diff --git a/client/src/styles/dashboard.css b/client/src/styles/dashboard.css index c517530..d7799c0 100644 --- a/client/src/styles/dashboard.css +++ b/client/src/styles/dashboard.css @@ -1,7 +1,7 @@ .dashboard { min-height: 100vh; padding: 32px; - background: #f9fafc; + background: var(--snow); } .dashboard-header { @@ -10,7 +10,7 @@ align-items: center; margin-bottom: 64px; padding-bottom: 32px; - border-bottom: 2px solid #e0e6ed; + border-bottom: 2px solid var(--smoke); } .header-content { @@ -24,25 +24,31 @@ height: 48px; } +.dashboard-logo svg { + width: 100%; + height: 100%; + fill: currentColor !important; +} + .dashboard-title { font-size: 32px; font-weight: bold; - color: #1f2d3d; + color: var(--black); margin: 0; } .welcome-text { margin: 8px 0 0 0; font-size: 16px; - color: #8492a6; + color: var(--muted); } .signout-button { padding: 12px 24px; background: transparent; - border: 2px solid #ec3750; + border: 2px solid var(--red); border-radius: 99999px; - color: #ec3750; + color: var(--red); font-size: 16px; font-weight: bold; font-family: Phantom Sans, sans-serif; @@ -73,8 +79,8 @@ .btn-primary { padding: 14px 32px; - background: #ec3750; - color: #ffffff; + background: var(--red); + color: var(--white); border: none; border-radius: 99999px; font-size: 16px; @@ -103,9 +109,9 @@ .btn-secondary { padding: 14px 32px; background: transparent; - border: 2px solid #ec3750; + border: 2px solid var(--red); border-radius: 99999px; - color: #ec3750; + color: var(--red); font-size: 16px; font-weight: bold; font-family: Phantom Sans, sans-serif; @@ -124,7 +130,7 @@ } .create-form { - background: #ffffff; + background: var(--white); padding: 32px; border-radius: 8px; margin-bottom: 32px; @@ -135,7 +141,7 @@ margin: 0 0 24px 0; font-size: 24px; font-weight: bold; - color: #1f2d3d; + color: var(--black); } .form-group { @@ -147,16 +153,16 @@ margin-bottom: 8px; font-size: 16px; font-weight: bold; - color: #1f2d3d; + color: var(--black); } .form-input { width: 100%; padding: 14px 16px; - border: 2px solid #e0e6ed; + border: 2px solid var(--smoke); border-radius: 8px; - background: #ffffff; - color: #1f2d3d; + background: var(--white); + color: var(--black); font-size: 16px; font-family: Phantom Sans, sans-serif; box-sizing: border-box; @@ -165,10 +171,17 @@ .form-input:focus { outline: none; - border-color: #338eda; + border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51, 142, 218, 0.1); } +.password-info { + margin-bottom: 8px; + font-size: 14px; + color: var(--muted); + line-height: 1.5; +} + .password-input-wrapper { position: relative; width: 100%; @@ -217,10 +230,10 @@ width: 100%; padding: 14px 16px; padding-right: 48px; - border: 2px solid #e0e6ed; + border: 2px solid var(--smoke); border-radius: 8px; - background: #ffffff; - color: #1f2d3d; + background: var(--white); + color: var(--black); font-size: 16px; font-family: Phantom Sans, sans-serif; font-weight: bold; @@ -231,11 +244,11 @@ } .select-trigger:hover { - border-color: #338eda; + border-color: var(--blue); } .select-trigger.open { - border-color: #338eda; + border-color: var(--blue); box-shadow: 0 0 0 3px rgba(51, 142, 218, 0.1); } @@ -248,7 +261,7 @@ height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; - border-top: 6px solid #3c4858; + border-top: 6px solid var(--slate); transition: transform 0.125s ease-in-out; pointer-events: none; } @@ -262,8 +275,8 @@ top: calc(100% + 8px); left: 0; right: 0; - background: #ffffff; - border: 2px solid #338eda; + background: var(--white); + border: 2px solid var(--blue); border-radius: 8px; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); z-index: 100; @@ -283,7 +296,7 @@ padding: 14px 16px; cursor: pointer; transition: background-color 0.125s ease-in-out; - border-bottom: 1px solid #e0e6ed; + border-bottom: 1px solid var(--smoke); } .select-option:last-child { @@ -291,34 +304,34 @@ } .select-option:hover { - background: #f9fafc; + background: var(--snow); } .select-option.selected { background: rgba(51, 142, 218, 0.1); - color: #338eda; + color: var(--blue); font-weight: bold; } .option-label { font-size: 16px; font-weight: bold; - color: #1f2d3d; + color: var(--black); margin-bottom: 4px; } .option-description { font-size: 14px; - color: #8492a6; + color: var(--muted); } .error-message { padding: 12px 16px; margin-bottom: 16px; background: rgba(236, 55, 80, 0.1); - border: 2px solid #ec3750; + border: 2px solid var(--red); border-radius: 8px; - color: #ec3750; + color: var(--red); font-size: 16px; } @@ -330,14 +343,14 @@ .section-title { font-size: 24px; font-weight: bold; - color: #1f2d3d; + color: var(--black); margin: 0 0 24px 0; } .empty-state { text-align: center; padding: 64px 32px; - color: #8492a6; + color: var(--muted); font-size: 16px; } @@ -348,15 +361,15 @@ } .space-card { - background: #ffffff; + background: var(--white); padding: 24px; border-radius: 8px; - border: 2px solid #e0e6ed; + border: 2px solid var(--smoke); transition: border-color 0.125s ease-in-out, box-shadow 0.125s ease-in-out; } .space-card:hover { - border-color: #338eda; + border-color: var(--blue); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.125); } @@ -370,7 +383,7 @@ .space-type { font-size: 20px; font-weight: bold; - color: #1f2d3d; + color: var(--black); margin: 0; text-transform: capitalize; } @@ -380,23 +393,23 @@ border-radius: 99999px; font-size: 14px; font-weight: bold; - color: #ffffff; + color: var(--white); } .status-running { - background: #33d6a6; + background: var(--green); } .status-stopped { - background: #ec3750; + background: var(--red); } .status-created { - background: #f1c40f; + background: var(--yellow); } .status-unknown { - background: #8492a6; + background: var(--muted); } .space-info { @@ -406,21 +419,21 @@ .space-info p { margin: 8px 0; - color: #8492a6; + color: var(--muted); } .space-info strong { - color: #3c4858; + color: var(--slate); } .space-info a { - color: #338eda; + color: var(--blue); text-decoration: none; transition: color 0.125s ease-in-out; } .space-info a:hover { - color: #ec3750; + color: var(--red); text-decoration: underline; } @@ -460,28 +473,33 @@ } .action-btn.start { - background: #33d6a6; - color: #ffffff; + background: var(--green); + color: var(--white); } .action-btn.stop { - background: #ec3750; - color: #ffffff; + background: var(--red); + color: var(--white); } .action-btn.open { - background: #338eda; - color: #ffffff; + background: var(--blue); + color: var(--white); } .action-btn.refresh { background: transparent; - border: 2px solid #338eda; - color: #338eda; + border: 2px solid var(--blue); + color: var(--blue); flex: 0 0 auto; min-width: 44px; } +.action-btn.delete { + background: var(--orange); + color: var(--white); +} + @media (max-width: 768px) { .dashboard { padding: 16px; diff --git a/client/src/themes.js b/client/src/themes.js new file mode 100644 index 0000000..52fe0fd --- /dev/null +++ b/client/src/themes.js @@ -0,0 +1,188 @@ +export const themes = { + light: { + name: 'Light', + icon: 'Default', + colors: { + '--red': '#ec3750', + '--orange': '#ff8c37', + '--yellow': '#f1c40f', + '--green': '#33d6a6', + '--cyan': '#5bc0de', + '--blue': '#338eda', + '--purple': '#a633d6', + '--muted': '#8492a6', + '--darker': '#121217', + '--dark': '#17171d', + '--darkless': '#252429', + '--black': '#1f2d3d', + '--steel': '#273444', + '--slate': '#3c4858', + '--smoke': '#e0e6ed', + '--snow': '#f9fafc', + '--white': '#ffffff' + } + }, + dark: { + name: 'Dark', + icon: 'Moon', + colors: { + '--red': '#ff4060', + '--orange': '#ff9c47', + '--yellow': '#f9d423', + '--green': '#3ae6b6', + '--cyan': '#6bd0ee', + '--blue': '#5098ea', + '--purple': '#b643e6', + '--muted': '#9aa2b0', + '--darker': '#f9fafc', + '--dark': '#e0e6ed', + '--darkless': '#c0c6cd', + '--black': '#ffffff', + '--steel': '#e0e6ed', + '--slate': '#c0c6cd', + '--smoke': '#2a2a2f', + '--snow': '#1a1a1f', + '--white': '#0f0f14' + } + }, + darkPurple: { + name: 'Dark Purple', + icon: 'Sparkle', + colors: { + '--red': '#ff6b9d', + '--orange': '#ffaa6b', + '--yellow': '#ffd966', + '--green': '#5de6c1', + '--cyan': '#7ddeff', + '--blue': '#7d9cff', + '--purple': '#c77dff', + '--muted': '#b4a5d6', + '--darker': '#f0e6ff', + '--dark': '#e0d1ff', + '--darkless': '#c9b3ff', + '--black': '#f5f0ff', + '--steel': '#d9ccff', + '--slate': '#c9b3ff', + '--smoke': '#2e1f47', + '--snow': '#1f0f3a', + '--white': '#15082b' + } + }, + darkGradient: { + name: 'Dark Gradient', + icon: 'Gradient', + colors: { + '--red': '#ff4d6d', + '--orange': '#ff9057', + '--yellow': '#ffda77', + '--green': '#06ffa5', + '--cyan': '#00d9ff', + '--blue': '#4d8cff', + '--purple': '#b366ff', + '--muted': '#a0b0c0', + '--darker': '#e8f4f8', + '--dark': '#d0e4f0', + '--darkless': '#b0d4e8', + '--black': '#ffffff', + '--steel': '#c0d8e8', + '--slate': '#a0c0d8', + '--smoke': '#1a2a3a', + '--snow': '#0f1a2a', + '--white': '#0a0f1a' + } + }, + lgbtq: { + name: 'Rainbow', + icon: 'Heart', + colors: { + '--red': '#E40303', + '--orange': '#FF8C00', + '--yellow': '#FFED00', + '--green': '#008026', + '--cyan': '#24408E', + '--blue': '#732982', + '--purple': '#732982', + '--muted': '#8b8b8b', + '--darker': '#ffffff', + '--dark': '#f5f5f5', + '--darkless': '#e8e8e8', + '--black': '#ffffff', + '--steel': '#e0e0e0', + '--slate': '#c0c0c0', + '--smoke': '#4a1942', + '--snow': '#2a0a26', + '--white': '#1a0616' + } + }, + sunset: { + name: 'Sunset', + icon: 'Sunset', + colors: { + '--red': '#ff6b6b', + '--orange': '#ffa06b', + '--yellow': '#ffe66d', + '--green': '#95e1d3', + '--cyan': '#6bcfff', + '--blue': '#a29bfe', + '--purple': '#fd79a8', + '--muted': '#b8a89d', + '--darker': '#2d3436', + '--dark': '#636e72', + '--darkless': '#95a5a6', + '--black': '#2d3436', + '--steel': '#636e72', + '--slate': '#95a5a6', + '--smoke': '#dfe6e9', + '--snow': '#f8f9fa', + '--white': '#ffffff' + } + }, + ocean: { + name: 'Ocean', + icon: 'Waves', + colors: { + '--red': '#ff6b9d', + '--orange': '#ff9f7f', + '--yellow': '#ffd97d', + '--green': '#69f0ae', + '--cyan': '#64d8cb', + '--blue': '#4d94ff', + '--purple': '#8c7ae6', + '--muted': '#7f8fa6', + '--darker': '#0f1c2e', + '--dark': '#1e3a5f', + '--darkless': '#2d5886', + '--black': '#e1f5fe', + '--steel': '#b3e5fc', + '--slate': '#81d4fa', + '--smoke': '#1e3a5f', + '--snow': '#0a1929', + '--white': '#021120' + } + }, + forest: { + name: 'Forest', + icon: 'Tree', + colors: { + '--red': '#e74c3c', + '--orange': '#f39c12', + '--yellow': '#f1c40f', + '--green': '#27ae60', + '--cyan': '#16a085', + '--blue': '#3498db', + '--purple': '#9b59b6', + '--muted': '#95a5a6', + '--darker': '#0e2f1f', + '--dark': '#1a4731', + '--darkless': '#275f43', + '--black': '#ecf0f1', + '--steel': '#d5e8df', + '--slate': '#bdd4c7', + '--smoke': '#2c5f3f', + '--snow': '#1a4731', + '--white': '#0e2f1f' + } + } +}; + +export const defaultTheme = 'light'; diff --git a/client/vite.config.js b/client/vite.config.js index 305678c..bd4493c 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -1,11 +1,16 @@ import { defineConfig } from 'vite' import { svelte } from '@sveltejs/vite-plugin-svelte' -// https://vitejs.dev/config/ export default defineConfig({ plugins: [svelte()], - server: { - host: '0.0.0.0', // Binds to all network interfaces, accessible from other devices - port: 5173, // Default port, can be changed + server: { + host: '0.0.0.0', + port: 5173, + proxy: { + '/api': { + target: 'http://localhost:3000', + changeOrigin: true, + } + } } }) diff --git a/package-lock.json b/package-lock.json index e5023dc..db816f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -776,7 +776,6 @@ "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -818,7 +817,6 @@ "version": "8.2.1", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", - "license": "MIT", "dependencies": { "ip-address": "10.0.1" }, @@ -2719,7 +2717,6 @@ "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "peer": true, "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1",