diff --git a/sql/auth/user_preferences.sql b/sql/auth/user_preferences.sql index b16b5ab..8078c4f 100644 --- a/sql/auth/user_preferences.sql +++ b/sql/auth/user_preferences.sql @@ -3,37 +3,35 @@ CREATE TABLE IF NOT EXISTS user_preferences ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, hide_from_leaderboard BOOLEAN NOT NULL DEFAULT false, + theme TEXT NOT NULL DEFAULT 'light', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(user_id) ); - -- Create RLS policies for user_preferences table ALTER TABLE user_preferences ENABLE ROW LEVEL SECURITY; - +-- Drop existing policies if they exist +DROP POLICY IF EXISTS "Users can read their own preferences" ON user_preferences; +DROP POLICY IF EXISTS "Users can insert their own preferences" ON user_preferences; +DROP POLICY IF EXISTS "Users can update their own preferences" ON user_preferences; -- Users can read their own preferences CREATE POLICY "Users can read their own preferences" ON user_preferences FOR SELECT USING (auth.uid() = user_id); - -- Users can insert their own preferences CREATE POLICY "Users can insert their own preferences" ON user_preferences FOR INSERT WITH CHECK (auth.uid() = user_id); - -- Users can update their own preferences CREATE POLICY "Users can update their own preferences" ON user_preferences FOR UPDATE USING (auth.uid() = user_id); - -- Create function to automatically create user preferences on new user creation -CREATE OR REPLACE FUNCTION public.handle_new_user_preferences() RETURNS TRIGGER AS $$ -BEGIN - INSERT INTO public.user_preferences (user_id, hide_from_leaderboard) - VALUES (NEW.id, false); - RETURN NEW; +CREATE OR REPLACE FUNCTION public.handle_new_user_preferences() RETURNS TRIGGER AS $$ BEGIN +INSERT INTO public.user_preferences (user_id, hide_from_leaderboard, theme) +VALUES (NEW.id, false, 'light'); +RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; - -- Create trigger to call the function when a new user is created DROP TRIGGER IF EXISTS on_auth_user_created_preferences ON auth.users; CREATE TRIGGER on_auth_user_created_preferences -AFTER INSERT ON auth.users -FOR EACH ROW EXECUTE FUNCTION public.handle_new_user_preferences(); +AFTER +INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION public.handle_new_user_preferences(); \ No newline at end of file diff --git a/src/app.css b/src/app.css index 14a18ea..54ff7d0 100644 --- a/src/app.css +++ b/src/app.css @@ -5,27 +5,27 @@ @layer theme { :root { /* Fonts */ - --font-sans: - Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, - 'Open Sans', 'Helvetica Neue', sans-serif; + --font-sans: 'Courier New', Courier, monospace; --font-mono: 'Fira Mono', monospace; - /* Colors */ + /* Colors - Retro Computer Theme - Blue & Pink */ + /* These are the default colors that will be overridden by theme selection */ + /* The same variables are defined in src/lib/theme-options/retro-blue-light.js */ --color-white: oklch(1 0 0); --color-black: oklch(0 0 0); - --color-primary: oklch(0.12 0 0); - --color-secondary: oklch(0.19 0 0); - --color-tertiary: oklch(0.28 0 0); - --color-accent: oklch(0.65 0.26 296.88); - --color-heading: oklch(1 0 0 / 0.87); - --color-text: oklch(1 0 0 / 0.6); - --color-text-muted: oklch(1 0 0 / 0.4); - --color-background: oklch(0.19 0 0 / 0.7); - --color-border: oklch(0.44 0 0); - --color-link: oklch(0.65 0.26 296.88); - --color-link-subtle: oklch(0.8 0.1 296.88); - --color-link-nav: oklch(1 0 0 / 0.8); - --color-username: oklch(0.65 0.26 296.88); /* Purple color for usernames */ + --color-primary: oklch(0.9 0.03 240); /* Light blue background */ + --color-secondary: oklch(0.95 0.02 240); /* Lighter blue for cards */ + --color-tertiary: oklch(0.85 0.04 240); /* Slightly darker blue for headers */ + --color-accent: oklch(0.7 0.2 350); /* Pink accent */ + --color-heading: oklch(0.2 0 0 / 0.9); /* Dark text for headings */ + --color-text: oklch(0.2 0 0 / 0.8); /* Dark text for body */ + --color-text-muted: oklch(0.2 0 0 / 0.5); /* Muted dark text */ + --color-background: oklch(0.9 0.03 240 / 0.7); /* Transparent blue background */ + --color-border: oklch(0.75 0.05 240); /* Border color */ + --color-link: oklch(0.7 0.2 350); /* Pink links */ + --color-link-subtle: oklch(0.75 0.15 350); /* Subtle pink links */ + --color-link-nav: oklch(0.2 0 0 / 0.9); /* Dark nav links */ + --color-username: oklch(0.6 0.25 30); /* Orange for usernames */ --color-solved-row: color-mix( in oklab, rgb(34 197 94) 15%, @@ -74,6 +74,12 @@ body { background-color: var(--color-primary); color: var(--color-text); overscroll-behavior: none; + font-family: var(--font-sans); + background-image: linear-gradient( + to bottom, + var(--color-primary), + color-mix(in oklab, var(--color-primary) 90%, var(--color-tertiary)) + ); } #app { @@ -190,31 +196,34 @@ img { /* Component styles */ .card { background-color: var(--color-secondary); - border-radius: 0.5rem; + border-radius: 0.25rem; + border: 1px solid var(--color-border); padding: 1.5rem; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.1); margin-bottom: 1rem; } .table { width: 100%; border-collapse: collapse; + border: 1px solid var(--color-border); } .table th { text-align: left; padding: 0.75rem; - border-bottom: 1px solid var(--color-tertiary); + border-bottom: 1px solid var(--color-border); color: var(--color-heading); + background-color: var(--color-tertiary); } .table td { padding: 0.75rem; - border-bottom: 1px solid var(--color-tertiary); + border-bottom: 1px solid var(--color-border); } .table tr:hover { - background-color: var(--color-tertiary); + background-color: color-mix(in oklab, var(--color-tertiary) 50%, transparent); } .badge { @@ -228,16 +237,19 @@ img { .badge-easy { background-color: oklch(0.73 0.2 142.5); color: white; + border: 1px solid oklch(0.63 0.2 142.5); } .badge-medium { background-color: oklch(0.71 0.19 54.65); color: white; + border: 1px solid oklch(0.61 0.19 54.65); } .badge-hard { background-color: oklch(0.65 0.27 29.23); color: white; + border: 1px solid oklch(0.55 0.27 29.23); } /* Responsive utilities */ @@ -302,3 +314,14 @@ img { width: 100%; margin: 0 auto; } + +/* Dark theme specific overrides */ +body.dark-theme .text-red-500, +body.dark-theme .text-red-600, +body.dark-theme .text-red-700 { + color: rgb(252, 165, 165) !important; /* lighter red for dark theme */ +} + +body.dark-theme .text-[var(--color-accent)] { + color: rgb(252, 165, 165) !important; /* lighter red for dark theme */ +} diff --git a/src/app.html b/src/app.html index 7c51eb5..c7852f5 100644 --- a/src/app.html +++ b/src/app.html @@ -7,6 +7,69 @@ name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" /> + + + + + %sveltekit.head% diff --git a/src/lib/components/ContestTable.svelte b/src/lib/components/ContestTable.svelte index e06c386..c1df5f5 100644 --- a/src/lib/components/ContestTable.svelte +++ b/src/lib/components/ContestTable.svelte @@ -148,14 +148,16 @@ function getDifficultyColorClass(difficulty: number | undefined): string {
-
+
- - - @@ -308,16 +315,16 @@ function getDifficultyColorClass(difficulty: number | undefined): string { class="relative border-b border-[var(--color-border)] transition-colors duration-200 last:border-b-0 ${contest.id && userParticipation.has(contest.id) ? 'border-l-4 border-l-[rgb(34_197_94)] bg-[var(--color-solved-row)]' - : 'hover:bg-black/5'}" + : 'hover:bg-[var(--color-tertiary)]/30'}" >
@@ -213,7 +215,7 @@ function getDifficultyColorClass(difficulty: number | undefined): string { ICPC
@@ -233,7 +235,7 @@ function getDifficultyColorClass(difficulty: number | undefined): string {
Codeforces
@@ -256,16 +258,18 @@ function getDifficultyColorClass(difficulty: number | undefined): string { {/if}
+ Contest Duration @@ -285,7 +289,9 @@ function getDifficultyColorClass(difficulty: number | undefined): string { Difficulty +
{#if contest.id} {@const hasParticipated = userParticipation.has(contest.id)} {:else}