mirror of
https://github.com/System-End/spaces.git
synced 2026-04-19 16:38:24 +00:00
QoL stuff
This commit is contained in:
parent
3ab58eec3e
commit
0f17308379
13 changed files with 709 additions and 110 deletions
|
|
@ -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,6 +14,8 @@
|
|||
let showAdminPanel = false;
|
||||
|
||||
onMount(() => {
|
||||
applyTheme(get(currentTheme));
|
||||
|
||||
const storedAuth = localStorage.getItem('auth_token');
|
||||
const storedUser = localStorage.getItem('user_data');
|
||||
|
||||
|
|
@ -89,6 +94,7 @@
|
|||
|
||||
<main>
|
||||
{#if isAuthenticated && user}
|
||||
<ThemeSwitcher />
|
||||
{#if showAdminPanel && user.is_admin}
|
||||
<div class="admin-header">
|
||||
<button on:click={() => showAdminPanel = false}>Back to Dashboard</button>
|
||||
|
|
@ -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);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -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%;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
client/src/assets/flag.svg
Normal file
20
client/src/assets/flag.svg
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
<svg
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
stroke-linejoin="round"
|
||||
stroke-miterlimit="1.414"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="flag"
|
||||
viewBox="0 0 32 32"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
fill="0"
|
||||
width="256"
|
||||
height="256"
|
||||
>
|
||||
|
||||
<g>
|
||||
<path d="M10.953 5.034a1 1 0 0 0-1.225.707L4.034 26.992a1 1 0 1 0 1.932.517l5.694-21.25a1 1 0 0 0-.707-1.225zm2.107 9.005c.425-1.703.798-3.036 1.225-4.079.429-1.058.766-1.43.912-1.532a.216.216 0 0 0 .022-.023l.017.003c.131-.022.133-.021.353.073l.065.028c.584.23 1.492.826 2.826 2.076 1.584 1.462 3.173 2.338 4.36 2.738a9.906 9.906 0 0 0 2.045.4c-.312 1.161-.627 2.297-1.028 3.334-.405 1.061-.756 1.774-1.284 2.307-.385.41-.719.542-1.131.527-.519-.018-1.447-.289-2.901-1.37-1.746-1.291-3.25-2.073-4.327-2.514a17.61 17.61 0 0 0-1.498-.524c.08-.375.193-.838.344-1.444zm12.104-1.615a.522.522 0 0 1 0 0zm-13.21 2.816l.017.008a.08.08 0 0 1-.017-.008zm-.834-1.685c1.727-6.93 3.174-9.634 8.727-4.43 2.833 2.655 4.933 2.646 6.14 2.641 1.16-.005 1.494-.007.86 2.359-1.294 4.83-3.053 10.796-9.5 6-2.638-1.962-4.392-2.486-5.449-2.801-1.526-.456-1.599-.478-.778-3.769z" />
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -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 @@
|
|||
<img class="flag-banner" src="https://assets.hackclub.com/flag-orpheus-top.svg" alt="Hack Club"/>
|
||||
</a>
|
||||
|
||||
<div class="auth-container" class:signup-mode={mode === 'signup'}>
|
||||
<div class="auth-container" class:signup-mode={authIntent === 'signup'} class:verify-mode={mode === 'verify' && authIntent === 'login'}>
|
||||
<div class="auth-panel auth-form-panel">
|
||||
<div class="auth-form-content">
|
||||
<div class="auth-header">
|
||||
<img class="auth-logo" src="https://icons.hackclub.com/api/icons/ec3750/clubs" alt="Hack Club" />
|
||||
<img class="auth-logo" src="https://icons.hackclub.com/api/icons/ec3750/flag" alt="Hack Club" />
|
||||
<h2 class="auth-title">{displayMode === 'signup' ? 'Join Hack Club Spaces' : 'Welcome Back'}</h2>
|
||||
<p class="auth-subtitle">Lorem ipsum dolor sit amet</p>
|
||||
<p class="auth-subtitle">Build amazing projects in the cloud</p>
|
||||
</div>
|
||||
|
||||
{#if mode === 'login' || mode === 'signup'}
|
||||
<form on:submit|preventDefault={sendVerificationCode}>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="email">Email</label>
|
||||
<label class="form-label" for="email">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
class="form-input"
|
||||
id="email"
|
||||
|
|
@ -152,7 +168,9 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group username-field" class:show={mode === 'signup'}>
|
||||
<label class="form-label" for="username">Username</label>
|
||||
<label class="form-label" for="username">
|
||||
Username
|
||||
</label>
|
||||
<input
|
||||
class="form-input"
|
||||
id="username"
|
||||
|
|
@ -172,7 +190,7 @@
|
|||
<div class="success-message">{message}</div>
|
||||
{/if}
|
||||
|
||||
<button class="primary-button" type="submit" disabled={loading || !email}>
|
||||
<button class="primary-button" type="submit" disabled={loading || !email || (mode === 'signup' && !username)}>
|
||||
{loading ? 'Sending...' : 'Send Verification Code'}
|
||||
</button>
|
||||
</form>
|
||||
|
|
@ -184,12 +202,56 @@
|
|||
Already have an account? <span class="auth-mode-link" on:click={() => switchMode('login')} on:keypress={(e) => e.key === 'Enter' && switchMode('login')} role="button" tabindex="0">Log in</span>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if mode === 'verify'}
|
||||
<p class="info-message">Check your email for the verification code</p>
|
||||
{/if}
|
||||
|
||||
<form on:submit|preventDefault={authIntent === 'login' ? handleLogin : handleSignup}>
|
||||
{#if authIntent === 'signup'}
|
||||
<div class="verification-code-section" class:show={mode === 'verify'}>
|
||||
<div class="verification-notice">
|
||||
<p class="verification-title">Check your email</p>
|
||||
<p class="verification-text">We sent a verification code to <strong>{email}</strong></p>
|
||||
</div>
|
||||
|
||||
<form on:submit|preventDefault={handleSignup}>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="code">
|
||||
Verification Code
|
||||
</label>
|
||||
<input
|
||||
class="form-input"
|
||||
id="code"
|
||||
type="text"
|
||||
bind:value={verificationCode}
|
||||
required
|
||||
placeholder="Enter code from email"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
<div class="error-message">{error}</div>
|
||||
{/if}
|
||||
|
||||
<button class="primary-button" type="submit" disabled={loading || !verificationCode}>
|
||||
{loading ? 'Verifying...' : 'Complete Sign Up'}
|
||||
</button>
|
||||
|
||||
<button class="secondary-button" type="button" on:click={sendVerificationCode}>
|
||||
Resend Code
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if mode === 'verify' && authIntent === 'login'}
|
||||
<div class="verification-notice">
|
||||
<p class="verification-title">Check your email</p>
|
||||
<p class="verification-text">We sent a verification code to <strong>{email}</strong></p>
|
||||
</div>
|
||||
|
||||
<form on:submit|preventDefault={handleLogin}>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="code">Verification Code</label>
|
||||
<label class="form-label" for="code">
|
||||
Verification Code
|
||||
</label>
|
||||
<input
|
||||
class="form-input"
|
||||
id="code"
|
||||
|
|
@ -205,10 +267,10 @@
|
|||
{/if}
|
||||
|
||||
<button class="primary-button" type="submit" disabled={loading || !verificationCode}>
|
||||
{loading ? 'Verifying...' : authIntent === 'signup' ? 'Complete Sign Up' : 'Login'}
|
||||
{loading ? 'Verifying...' : 'Login'}
|
||||
</button>
|
||||
|
||||
<button class="secondary-button" type="button" on:click={() => switchMode(mode)}>
|
||||
<button class="secondary-button" type="button" on:click={() => switchMode('login')}>
|
||||
Resend Code
|
||||
</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { API_BASE, ERROR_MESSAGES } from '../config.js';
|
||||
import '../styles/dashboard.css';
|
||||
import { currentTheme } from '../stores/theme.js';
|
||||
import { themes } from '../themes.js';
|
||||
import FlagIcon from '../assets/flag.svg?raw';
|
||||
|
||||
export let spaces = [];
|
||||
export let authorization = '';
|
||||
|
|
@ -237,6 +240,14 @@
|
|||
|
||||
$: selectedType = spaceTypes.find(type => type.value === newSpaceType) || spaceTypes[0];
|
||||
|
||||
$: logoColor = (() => {
|
||||
const theme = themes[$currentTheme];
|
||||
if (theme && theme.colors['--red']) {
|
||||
return theme.colors['--red'];
|
||||
}
|
||||
return '#ec3750';
|
||||
})();
|
||||
|
||||
function togglePasswordVisibility() {
|
||||
showPassword = !showPassword;
|
||||
}
|
||||
|
|
@ -245,7 +256,9 @@
|
|||
<div class="dashboard">
|
||||
<header class="dashboard-header">
|
||||
<div class="header-content">
|
||||
<img class="dashboard-logo" src="https://icons.hackclub.com/api/icons/ec3750/clubs" alt="Hack Club" />
|
||||
<div class="dashboard-logo" style="color: {logoColor}">
|
||||
{@html FlagIcon}
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="dashboard-title">Hack Club Spaces</h1>
|
||||
<p class="welcome-text">Welcome, {username}!</p>
|
||||
|
|
|
|||
126
client/src/lib/ThemeSwitcher.svelte
Normal file
126
client/src/lib/ThemeSwitcher.svelte
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<script>
|
||||
import { currentTheme, setTheme } from '../stores/theme.js';
|
||||
import { themes } from '../themes.js';
|
||||
|
||||
let isOpen = false;
|
||||
|
||||
function toggleMenu() {
|
||||
isOpen = !isOpen;
|
||||
}
|
||||
|
||||
function selectTheme(themeName) {
|
||||
setTheme(themeName);
|
||||
isOpen = false;
|
||||
}
|
||||
|
||||
function handleClickOutside(event) {
|
||||
if (isOpen && !event.target.closest('.theme-switcher')) {
|
||||
isOpen = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:click={handleClickOutside} />
|
||||
|
||||
<div class="theme-switcher">
|
||||
<button class="theme-toggle" on:click|stopPropagation={toggleMenu} aria-label="Switch theme">
|
||||
theme: {themes[$currentTheme]?.name || 'light'}
|
||||
</button>
|
||||
|
||||
{#if isOpen}
|
||||
<div class="theme-menu">
|
||||
{#each Object.entries(themes) as [key, theme]}
|
||||
<button
|
||||
class="theme-option"
|
||||
class:active={$currentTheme === key}
|
||||
on:click={() => selectTheme(key)}
|
||||
>
|
||||
{theme.name}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.theme-switcher {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 20px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.theme-toggle {
|
||||
padding: 8px 16px;
|
||||
background: var(--white);
|
||||
border: 2px solid var(--smoke);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--black);
|
||||
transition: all 0.15s ease;
|
||||
font-family: 'Phantom Sans', sans-serif;
|
||||
}
|
||||
|
||||
.theme-toggle:hover {
|
||||
border-color: var(--blue);
|
||||
background: var(--snow);
|
||||
}
|
||||
|
||||
.theme-menu {
|
||||
position: absolute;
|
||||
bottom: 42px;
|
||||
left: 0;
|
||||
background: var(--white);
|
||||
border: 2px solid var(--smoke);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
overflow: hidden;
|
||||
animation: slideUp 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.theme-option {
|
||||
padding: 8px 16px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--black);
|
||||
text-align: left;
|
||||
transition: all 0.1s ease;
|
||||
font-family: 'Phantom Sans', sans-serif;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.theme-option:hover {
|
||||
background: var(--snow);
|
||||
}
|
||||
|
||||
.theme-option.active {
|
||||
background: var(--blue);
|
||||
color: var(--white);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.theme-switcher {
|
||||
bottom: 16px;
|
||||
left: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
37
client/src/stores/theme.js
Normal file
37
client/src/stores/theme.js
Normal file
|
|
@ -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());
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
188
client/src/themes.js
Normal file
188
client/src/themes.js
Normal file
|
|
@ -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';
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
3
package-lock.json
generated
3
package-lock.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue