wip: in-progress mars theme work (saved before auth refactor)
This commit is contained in:
@@ -5,7 +5,6 @@ import { useParams } from 'next/navigation';
|
|||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import { wishlistsApi, itemsApi, claimingApi, type Wishlist, type Item } from '@/lib/api';
|
import { wishlistsApi, itemsApi, claimingApi, type Wishlist, type Item } from '@/lib/api';
|
||||||
import Header from '@/components/header';
|
import Header from '@/components/header';
|
||||||
import Footer from '@/components/footer';
|
|
||||||
import PasswordLockGuard from '@/components/password-lock-guard';
|
import PasswordLockGuard from '@/components/password-lock-guard';
|
||||||
|
|
||||||
export default function PublicWishlistPage() {
|
export default function PublicWishlistPage() {
|
||||||
@@ -285,9 +284,6 @@ export default function PublicWishlistPage() {
|
|||||||
</div>
|
</div>
|
||||||
) : item.claimedAt ? (
|
) : item.claimedAt ? (
|
||||||
<div className="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded p-3">
|
<div className="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded p-3">
|
||||||
<p className="text-sm font-medium text-green-800 dark:text-green-200">
|
|
||||||
Reservado por {item.claimedByName}
|
|
||||||
</p>
|
|
||||||
{item.claimedByNote && (
|
{item.claimedByNote && (
|
||||||
<p className="text-xs text-green-700 dark:text-green-300 mt-1">
|
<p className="text-xs text-green-700 dark:text-green-300 mt-1">
|
||||||
Nota: {item.claimedByNote}
|
Nota: {item.claimedByNote}
|
||||||
@@ -357,8 +353,6 @@ export default function PublicWishlistPage() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</PasswordLockGuard>
|
</PasswordLockGuard>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import ProtectedRoute from '@/components/protected-route';
|
|||||||
import { useAuth } from '@/lib/auth-context';
|
import { useAuth } from '@/lib/auth-context';
|
||||||
import { wishlistsApi, itemsApi, settingsApi, type Wishlist, type Settings } from '@/lib/api';
|
import { wishlistsApi, itemsApi, settingsApi, type Wishlist, type Settings } from '@/lib/api';
|
||||||
import Header from '@/components/header';
|
import Header from '@/components/header';
|
||||||
import Footer from '@/components/footer';
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import StatsGrid from '@/components/admin/StatsGrid';
|
import StatsGrid from '@/components/admin/StatsGrid';
|
||||||
import SettingsSection from '@/components/admin/SettingsSection';
|
import SettingsSection from '@/components/admin/SettingsSection';
|
||||||
@@ -230,8 +229,6 @@ export default function AdminPage() {
|
|||||||
onCreate={handleCreateWishlist}
|
onCreate={handleCreateWishlist}
|
||||||
error={createError}
|
error={createError}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
@variant dark (.dark &);
|
|
||||||
|
|
||||||
/* Mars palette — warm rust, terracotta, dusty sand, deep crater shadows */
|
/* Mars palette — warm rust, terracotta, dusty sand, deep crater shadows */
|
||||||
:root {
|
:root {
|
||||||
--background: #fff5ee; /* warm sand mist */
|
--background: #fff5ee; /* warm sand mist */
|
||||||
@@ -26,30 +24,6 @@
|
|||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme="dark"],
|
|
||||||
.dark {
|
|
||||||
--background: #1a0c08; /* night side of Mars */
|
|
||||||
--foreground: #f4e2d4;
|
|
||||||
--ink: #f4e2d4;
|
|
||||||
--ink-soft: #d6b39d;
|
|
||||||
--muted: #a48068;
|
|
||||||
--card: #2a140d;
|
|
||||||
--card-soft: #341a12;
|
|
||||||
--border: #4a261a;
|
|
||||||
--accent: #e26d3d; /* glowing rust */
|
|
||||||
--accent-soft: #3d1a10;
|
|
||||||
--success: #b3c275;
|
|
||||||
--success-soft: #2a2615;
|
|
||||||
--success-border: #4a4528;
|
|
||||||
--success-ink: #d8de9c;
|
|
||||||
--halo-1: rgba(231, 111, 65, 0.30);
|
|
||||||
--halo-2: rgba(196, 76, 39, 0.30);
|
|
||||||
--halo-3: rgba(120, 40, 25, 0.40);
|
|
||||||
--planet-core: #d65a30;
|
|
||||||
--planet-rim: #6e2412;
|
|
||||||
color-scheme: dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
--color-foreground: var(--foreground);
|
--color-foreground: var(--foreground);
|
||||||
@@ -85,19 +59,6 @@ body {
|
|||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .bg-cosmic {
|
|
||||||
background-image:
|
|
||||||
radial-gradient(circle at 12% 18%, var(--halo-1) 0%, transparent 38%),
|
|
||||||
radial-gradient(circle at 88% 14%, var(--halo-2) 0%, transparent 44%),
|
|
||||||
radial-gradient(circle at 50% 92%, var(--halo-3) 0%, transparent 50%),
|
|
||||||
radial-gradient(1px 1px at 22% 30%, rgba(255, 220, 200, 0.85) 50%, transparent 51%),
|
|
||||||
radial-gradient(1px 1px at 70% 22%, rgba(255, 220, 200, 0.75) 50%, transparent 51%),
|
|
||||||
radial-gradient(1px 1px at 40% 70%, rgba(255, 220, 200, 0.75) 50%, transparent 51%),
|
|
||||||
radial-gradient(1px 1px at 82% 60%, rgba(255, 220, 200, 0.85) 50%, transparent 51%),
|
|
||||||
radial-gradient(1px 1px at 18% 82%, rgba(255, 220, 200, 0.75) 50%, transparent 51%),
|
|
||||||
linear-gradient(180deg, var(--background) 0%, #0a0604 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mars-disk glyph: a soft layered radial gradient that reads as a planet.
|
* Mars-disk glyph: a soft layered radial gradient that reads as a planet.
|
||||||
* Used as a decorative ::before in the header.
|
* Used as a decorative ::before in the header.
|
||||||
@@ -147,21 +108,3 @@ body {
|
|||||||
:root textarea::placeholder {
|
:root textarea::placeholder {
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme="dark"] input,
|
|
||||||
:root[data-theme="dark"] textarea,
|
|
||||||
:root[data-theme="dark"] select,
|
|
||||||
.dark input,
|
|
||||||
.dark textarea,
|
|
||||||
.dark select {
|
|
||||||
color: var(--ink);
|
|
||||||
background-color: var(--card-soft);
|
|
||||||
border-color: var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root[data-theme="dark"] input::placeholder,
|
|
||||||
:root[data-theme="dark"] textarea::placeholder,
|
|
||||||
.dark input::placeholder,
|
|
||||||
.dark textarea::placeholder {
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { AuthProvider } from "@/lib/auth-context";
|
import { AuthProvider } from "@/lib/auth-context";
|
||||||
import { ThemeProvider } from "@/components/theme-provider";
|
|
||||||
import { db, settings } from "@/lib/db";
|
import { db, settings } from "@/lib/db";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
@@ -53,7 +52,7 @@ export default function RootLayout({
|
|||||||
</head>
|
</head>
|
||||||
<body className="font-sans antialiased bg-cosmic">
|
<body className="font-sans antialiased bg-cosmic">
|
||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
<ThemeProvider>{children}</ThemeProvider>
|
{children}
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import Header from '@/components/header';
|
import Header from '@/components/header';
|
||||||
import Footer from '@/components/footer';
|
|
||||||
|
|
||||||
export default function LockPage() {
|
export default function LockPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -88,8 +87,6 @@ export default function LockPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useEffect, useState } from 'react';
|
|||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import { wishlistsApi, itemsApi, claimingApi, settingsApi, type Wishlist, type Item, type Settings } from '@/lib/api';
|
import { wishlistsApi, itemsApi, claimingApi, settingsApi, type Wishlist, type Item, type Settings } from '@/lib/api';
|
||||||
import Header from '@/components/header';
|
import Header from '@/components/header';
|
||||||
import Footer from '@/components/footer';
|
|
||||||
import PasswordLockGuard from '@/components/password-lock-guard';
|
import PasswordLockGuard from '@/components/password-lock-guard';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
@@ -248,9 +247,6 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
) : item.claimedAt ? (
|
) : item.claimedAt ? (
|
||||||
<div className="bg-[color:var(--success-soft)] border border-[color:var(--success-border)] rounded-xl p-3">
|
<div className="bg-[color:var(--success-soft)] border border-[color:var(--success-border)] rounded-xl p-3">
|
||||||
<p className="text-sm font-medium text-[color:var(--success-ink)]">
|
|
||||||
Reservado por {item.claimedByName}
|
|
||||||
</p>
|
|
||||||
{item.claimedByNote && (
|
{item.claimedByNote && (
|
||||||
<p className="text-xs text-[color:var(--success-ink)] mt-1">
|
<p className="text-xs text-[color:var(--success-ink)] mt-1">
|
||||||
Nota: {item.claimedByNote}
|
Nota: {item.claimedByNote}
|
||||||
@@ -318,8 +314,6 @@ export default function Home() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</PasswordLockGuard>
|
</PasswordLockGuard>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useTheme } from '@/components/theme-provider';
|
|
||||||
|
|
||||||
export default function Footer() {
|
|
||||||
const { theme, toggleTheme } = useTheme();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
|
|
||||||
<div className="flex flex-col items-center gap-2 text-sm">
|
|
||||||
<button
|
|
||||||
onClick={toggleTheme}
|
|
||||||
className="flex items-center gap-2 px-4 py-2 rounded-full bg-card-soft hover:bg-[color:var(--accent-soft)] border border-[color:var(--border)] transition-colors text-[color:var(--ink-soft)] font-medium shadow-soft"
|
|
||||||
aria-label="Alternar tema"
|
|
||||||
>
|
|
||||||
{theme === 'light' ? (
|
|
||||||
<>
|
|
||||||
<svg
|
|
||||||
className="w-5 h-5"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={2}
|
|
||||||
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<span>Modo escuro</span>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<svg
|
|
||||||
className="w-5 h-5"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={2}
|
|
||||||
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<span>Modo claro</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { createContext, useContext, useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
type Theme = 'light' | 'dark';
|
|
||||||
|
|
||||||
interface ThemeContextType {
|
|
||||||
theme: Theme;
|
|
||||||
toggleTheme: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
|
||||||
|
|
||||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
||||||
const [theme, setTheme] = useState<Theme>('light');
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
// Load theme from localStorage
|
|
||||||
const savedTheme = localStorage.getItem('theme') as Theme | null;
|
|
||||||
const initialTheme = savedTheme || 'light';
|
|
||||||
|
|
||||||
setTheme(initialTheme);
|
|
||||||
document.documentElement.setAttribute('data-theme', initialTheme);
|
|
||||||
|
|
||||||
if (initialTheme === 'dark') {
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark');
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const toggleTheme = () => {
|
|
||||||
const newTheme = theme === 'light' ? 'dark' : 'light';
|
|
||||||
setTheme(newTheme);
|
|
||||||
localStorage.setItem('theme', newTheme);
|
|
||||||
document.documentElement.setAttribute('data-theme', newTheme);
|
|
||||||
if (newTheme === 'dark') {
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ThemeContext.Provider value={{ theme, toggleTheme }}>
|
|
||||||
{children}
|
|
||||||
</ThemeContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useTheme() {
|
|
||||||
const context = useContext(ThemeContext);
|
|
||||||
if (context === undefined) {
|
|
||||||
throw new Error('useTheme must be used within a ThemeProvider');
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user