diff --git a/apps/frontend/index.html b/apps/frontend/index.html index 3df409b..0c6bf41 100644 --- a/apps/frontend/index.html +++ b/apps/frontend/index.html @@ -2,11 +2,11 @@ - + PlayZer - +
diff --git a/apps/frontend/src/App.css b/apps/frontend/src/App.css index e87c16a..e69de29 100644 --- a/apps/frontend/src/App.css +++ b/apps/frontend/src/App.css @@ -1,182 +0,0 @@ -.counter { - font-size: 16px; - padding: 5px 10px; - border-radius: 5px; - color: var(--accent); - background: var(--accent-bg); - border: 2px solid transparent; - transition: border-color 0.3s; - margin-bottom: 24px; - - &:hover { - border-color: var(--accent-border); - } - &:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -.hero { - position: relative; - - .base, - .framework, - .vite { - inset-inline: 0; - margin: 0 auto; - } - - .base { - width: 170px; - position: relative; - z-index: 0; - } - - .framework, - .vite { - position: absolute; - } - - .framework { - z-index: 1; - top: 34px; - height: 28px; - transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) scale(1.4); - } - - .vite { - z-index: 0; - top: 107px; - height: 26px; - width: auto; - transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) scale(0.8); - } -} - -#center { - display: flex; - flex-direction: column; - gap: 25px; - place-content: center; - place-items: center; - flex-grow: 1; - - @media (max-width: 1024px) { - padding: 32px 20px 24px; - gap: 18px; - } -} - -#next-steps { - display: flex; - border-top: 1px solid var(--border); - text-align: left; - - & > div { - flex: 1 1 0; - padding: 32px; - @media (max-width: 1024px) { - padding: 24px 20px; - } - } - - .icon { - margin-bottom: 16px; - width: 22px; - height: 22px; - } - - @media (max-width: 1024px) { - flex-direction: column; - text-align: center; - } -} - -#docs { - border-right: 1px solid var(--border); - - @media (max-width: 1024px) { - border-right: none; - border-bottom: 1px solid var(--border); - } -} - -#next-steps ul { - list-style: none; - padding: 0; - display: flex; - gap: 8px; - margin: 32px 0 0; - - .logo { - height: 18px; - } - - a { - color: var(--text-h); - font-size: 16px; - border-radius: 6px; - background: var(--social-bg); - display: flex; - padding: 6px 12px; - align-items: center; - gap: 8px; - text-decoration: none; - transition: box-shadow 0.3s; - - &:hover { - box-shadow: var(--shadow); - } - .button-icon { - height: 18px; - width: 18px; - } - } - - @media (max-width: 1024px) { - margin-top: 20px; - flex-wrap: wrap; - justify-content: center; - - li { - flex: 1 1 calc(50% - 8px); - } - - a { - width: 100%; - justify-content: center; - box-sizing: border-box; - } - } -} - -#spacer { - height: 88px; - border-top: 1px solid var(--border); - @media (max-width: 1024px) { - height: 48px; - } -} - -.ticks { - position: relative; - width: 100%; - - &::before, - &::after { - content: ""; - position: absolute; - top: -4.5px; - border: 5px solid transparent; - } - - &::before { - left: 0; - border-left-color: var(--border); - } - &::after { - right: 0; - border-right-color: var(--border); - } -} diff --git a/apps/frontend/src/assets/playzer-favicon-512-transparent.png b/apps/frontend/src/assets/playzer-favicon-512-transparent.png new file mode 100644 index 0000000..c4d6d05 Binary files /dev/null and b/apps/frontend/src/assets/playzer-favicon-512-transparent.png differ diff --git a/apps/frontend/src/assets/playzer-favicon-transparent.ico b/apps/frontend/src/assets/playzer-favicon-transparent.ico new file mode 100644 index 0000000..b8e278e Binary files /dev/null and b/apps/frontend/src/assets/playzer-favicon-transparent.ico differ diff --git a/apps/frontend/src/assets/playzer-favicon.ico b/apps/frontend/src/assets/playzer-favicon.ico new file mode 100644 index 0000000..4477a2d Binary files /dev/null and b/apps/frontend/src/assets/playzer-favicon.ico differ diff --git a/apps/frontend/src/assets/playzer-icon-p-transparent.png b/apps/frontend/src/assets/playzer-icon-p-transparent.png new file mode 100644 index 0000000..8bbdd61 Binary files /dev/null and b/apps/frontend/src/assets/playzer-icon-p-transparent.png differ diff --git a/apps/frontend/src/assets/playzer-icon-p-transparent.svg b/apps/frontend/src/assets/playzer-icon-p-transparent.svg new file mode 100644 index 0000000..e64166b --- /dev/null +++ b/apps/frontend/src/assets/playzer-icon-p-transparent.svg @@ -0,0 +1,4 @@ + + Playzer P icon + + diff --git a/apps/frontend/src/assets/playzer-icon-p.svg b/apps/frontend/src/assets/playzer-icon-p.svg new file mode 100644 index 0000000..7b16b70 --- /dev/null +++ b/apps/frontend/src/assets/playzer-icon-p.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/frontend/src/assets/playzer-logo-transparent.png b/apps/frontend/src/assets/playzer-logo-transparent.png new file mode 100644 index 0000000..3beb022 Binary files /dev/null and b/apps/frontend/src/assets/playzer-logo-transparent.png differ diff --git a/apps/frontend/src/assets/playzer-logo-transparent.svg b/apps/frontend/src/assets/playzer-logo-transparent.svg new file mode 100644 index 0000000..ad8ff04 --- /dev/null +++ b/apps/frontend/src/assets/playzer-logo-transparent.svg @@ -0,0 +1,4 @@ + + Playzer logo + + diff --git a/apps/frontend/src/assets/playzer-logo.svg b/apps/frontend/src/assets/playzer-logo.svg new file mode 100644 index 0000000..b6a8a3c --- /dev/null +++ b/apps/frontend/src/assets/playzer-logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/frontend/src/components/header.tsx b/apps/frontend/src/components/header.tsx new file mode 100644 index 0000000..41c4454 --- /dev/null +++ b/apps/frontend/src/components/header.tsx @@ -0,0 +1,243 @@ +import { useState } from "react" +import { CalendarDays, LogOut, Menu, Settings, User, X } from "lucide-react" + +import PlayzerIcon from "@/assets/playzer-favicon-512-transparent.png" +import { Link, useLocation } from "@tanstack/react-router" + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet" +import { useAuth } from "@/lib/auth" + +interface NavItemProps { + to: string + label: string + isMobile?: boolean + onClick?: () => void +} + +function NavItem({ to, label, isMobile, onClick }: NavItemProps) { + const location = useLocation() + const currentPath = location.pathname + const isActive = to === "/" ? currentPath === "/" : currentPath.startsWith(to) + + return ( + + + + ) +} + +export function Header() { + const [open, setOpen] = useState(false) + const { user, isAuthenticated, displayName, avatarUrl, signOut } = useAuth(); + + const menuItems = [ + { label: "Inicio", to: "/" }, + { label: "Reservas", to: "/booking" }, + { label: "Canchas", to: "/canchas" }, + { label: "Dashboard", to: "/dashboard" }, + { label: "Contacto", to: "/contacto" }, + ] + + return ( +
+
+ +
+ +
+ Playzer +
+ + + Playzer + + + + + +
+ +
+ +
+ + + + + + + + +
+ + + + JD + + + +
+ {displayName} + + {user?.email} + +
+
+
+ + + + + + Mi Perfil + + + + + Configuración + + + + + + + Cerrar sesión + +
+
+ + + + + + + +
+
+
+ + + + JD + + + +
+

John Doe

+

+ john@example.com +

+
+
+
+ + + + + +
+

+ Cuenta +

+ + +
+
+
+
+
+ +
+
+ ) +} \ No newline at end of file diff --git a/apps/frontend/src/components/layout.tsx b/apps/frontend/src/components/layout.tsx new file mode 100644 index 0000000..27bdf15 --- /dev/null +++ b/apps/frontend/src/components/layout.tsx @@ -0,0 +1,34 @@ +import type { ReactNode } from "react" +import { Header } from "./header" + +interface LayoutProps { + children: ReactNode +} + +export function Layout({ children }: LayoutProps) { + return ( +
+ +
+
+ {children} +
+
+ ) +} + +function Background() { + return ( +
+
+ +
+
+
+ +
+ +
+
+ ) +} \ No newline at end of file diff --git a/apps/frontend/src/components/ui/dialog.tsx b/apps/frontend/src/components/ui/dialog.tsx index bfb17f0..1e383c6 100644 --- a/apps/frontend/src/components/ui/dialog.tsx +++ b/apps/frontend/src/components/ui/dialog.tsx @@ -90,7 +90,7 @@ function DialogFooter({
) { + return +} + +function SheetTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function SheetClose({ + ...props +}: React.ComponentProps) { + return +} + +function SheetPortal({ + ...props +}: React.ComponentProps) { + return +} + +function SheetOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function SheetContent({ + className, + children, + side = "right", + showCloseButton = true, + ...props +}: React.ComponentProps & { + side?: "top" | "right" | "bottom" | "left" + showCloseButton?: boolean +}) { + return ( + + + + {children} + {showCloseButton && ( + + + + )} + + + ) +} + +function SheetHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function SheetFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function SheetTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function SheetDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + Sheet, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +} diff --git a/apps/frontend/src/index.css b/apps/frontend/src/index.css index e49f238..dac14b1 100644 --- a/apps/frontend/src/index.css +++ b/apps/frontend/src/index.css @@ -1,44 +1,80 @@ @import "tailwindcss"; @import "tw-animate-css"; @import "shadcn/tailwind.css"; -@import "@fontsource-variable/geist"; +/* @import "@fontsource-variable/inter"; */ @custom-variant dark (&:is(.dark *)); +@source "../../../apps/**/*.{ts,tsx}"; +@source "../../../components/**/*.{ts,tsx}"; +@source "../**/*.{ts,tsx}"; + +html, +body, +#root { + width: 100%; + min-height: 100%; + margin: 0; +} + @theme inline { --font-heading: var(--font-sans); - --font-sans: "Geist Variable", sans-serif; - --color-sidebar-ring: var(--sidebar-ring); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar: var(--sidebar); - --color-chart-5: var(--chart-5); - --color-chart-4: var(--chart-4); - --color-chart-3: var(--chart-3); - --color-chart-2: var(--chart-2); - --color-chart-1: var(--chart-1); - --color-ring: var(--ring); - --color-input: var(--input); - --color-border: var(--border); - --color-destructive: var(--destructive); - --color-accent-foreground: var(--accent-foreground); - --color-accent: var(--accent); - --color-muted-foreground: var(--muted-foreground); - --color-muted: var(--muted); - --color-secondary-foreground: var(--secondary-foreground); - --color-secondary: var(--secondary); - --color-primary-foreground: var(--primary-foreground); - --color-primary: var(--primary); - --color-popover-foreground: var(--popover-foreground); - --color-popover: var(--popover); - --color-card-foreground: var(--card-foreground); - --color-card: var(--card); - --color-foreground: var(--foreground); + --color-background: var(--background); + --color-foreground: var(--foreground); + + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + + --color-success: var(--success); + --color-success-foreground: var(--success-foreground); + + --color-reserved: var(--reserved); + --color-reserved-foreground: var(--reserved-foreground); + + --color-maintenance: var(--maintenance); + --color-maintenance-foreground: var(--maintenance-foreground); + + --color-warning: var(--warning); + --color-warning-foreground: var(--warning-foreground); + + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); + --radius-sm: calc(var(--radius) * 0.6); --radius-md: calc(var(--radius) * 0.8); --radius-lg: var(--radius); @@ -46,85 +82,137 @@ --radius-2xl: calc(var(--radius) * 1.8); --radius-3xl: calc(var(--radius) * 2.2); --radius-4xl: calc(var(--radius) * 2.6); + + --font-sans: "Inter Variable", sans-serif; } :root { - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); + --background: oklch(0.985 0.004 240); + --foreground: oklch(0.18 0.012 245); + --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); + --card-foreground: oklch(0.18 0.012 245); + --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.87 0 0); - --chart-2: oklch(0.556 0 0); - --chart-3: oklch(0.439 0 0); - --chart-4: oklch(0.371 0 0); - --chart-5: oklch(0.269 0 0); - --radius: 0.625rem; - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); + --popover-foreground: oklch(0.18 0.012 245); + + --primary: oklch(0.63 0.19 158); + --primary-foreground: oklch(0.985 0.004 160); + + --secondary: oklch(0.94 0.01 240); + --secondary-foreground: oklch(0.28 0.018 245); + + --muted: oklch(0.95 0.008 240); + --muted-foreground: oklch(0.52 0.018 245); + + --accent: oklch(0.93 0.035 158); + --accent-foreground: oklch(0.34 0.12 158); + + --destructive: oklch(0.62 0.22 25); + --destructive-foreground: oklch(0.98 0.01 25); + + --success: oklch(0.63 0.19 158); + --success-foreground: oklch(0.985 0.004 160); + + --reserved: oklch(0.58 0.19 255); + --reserved-foreground: oklch(0.985 0.01 255); + + --maintenance: oklch(0.64 0.22 25); + --maintenance-foreground: oklch(0.985 0.01 25); + + --warning: oklch(0.78 0.16 75); + --warning-foreground: oklch(0.18 0.04 75); + + --border: oklch(0.86 0.01 245 / 65%); + --input: oklch(0.86 0.01 245 / 75%); + --ring: oklch(0.63 0.19 158); + + --chart-1: oklch(0.63 0.19 158); + --chart-2: oklch(0.58 0.19 255); + --chart-3: oklch(0.64 0.22 25); + --chart-4: oklch(0.78 0.16 75); + --chart-5: oklch(0.68 0.16 205); + + --radius: 0.875rem; + + --sidebar: oklch(0.98 0.004 240); + --sidebar-foreground: oklch(0.18 0.012 245); + --sidebar-primary: oklch(0.63 0.19 158); + --sidebar-primary-foreground: oklch(0.985 0.004 160); + --sidebar-accent: oklch(0.94 0.01 240); + --sidebar-accent-foreground: oklch(0.28 0.018 245); + --sidebar-border: oklch(0.86 0.01 245 / 65%); + --sidebar-ring: oklch(0.63 0.19 158); } .dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.87 0 0); - --chart-2: oklch(0.556 0 0); - --chart-3: oklch(0.439 0 0); - --chart-4: oklch(0.371 0 0); - --chart-5: oklch(0.269 0 0); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); + --background: #081118; + --foreground: oklch(0.96 0.006 245); + + --card: oklch(0.19 0.022 240); + --card-foreground: oklch(0.96 0.006 245); + + --popover: oklch(0.18 0.022 240); + --popover-foreground: oklch(0.96 0.006 245); + + --primary: oklch(0.67 0.21 158); + --primary-foreground: oklch(0.12 0.02 158); + + --secondary: oklch(0.235 0.024 240); + --secondary-foreground: oklch(0.9 0.008 245); + + --muted: oklch(0.24 0.022 240); + --muted-foreground: oklch(0.68 0.018 245); + + --accent: oklch(0.28 0.06 158); + --accent-foreground: oklch(0.9 0.04 158); + + --destructive: oklch(0.66 0.23 25); + --destructive-foreground: oklch(0.98 0.01 25); + + --success: oklch(0.67 0.21 158); + --success-foreground: oklch(0.12 0.02 158); + + --reserved: oklch(0.61 0.2 255); + --reserved-foreground: oklch(0.97 0.012 255); + + --maintenance: oklch(0.66 0.23 25); + --maintenance-foreground: oklch(0.98 0.01 25); + + --warning: oklch(0.78 0.17 75); + --warning-foreground: oklch(0.18 0.04 75); + + --border: oklch(1 0 0 / 11%); + --input: oklch(1 0 0 / 14%); + --ring: oklch(0.67 0.21 158); + + --chart-1: oklch(0.67 0.21 158); + --chart-2: oklch(0.61 0.2 255); + --chart-3: oklch(0.66 0.23 25); + --chart-4: oklch(0.78 0.17 75); + --chart-5: oklch(0.7 0.16 205); + + --sidebar: oklch(0.165 0.02 240); + --sidebar-foreground: oklch(0.96 0.006 245); + --sidebar-primary: oklch(0.67 0.21 158); + --sidebar-primary-foreground: oklch(0.12 0.02 158); + --sidebar-accent: oklch(0.235 0.024 240); + --sidebar-accent-foreground: oklch(0.9 0.008 245); + --sidebar-border: oklch(1 0 0 / 11%); + --sidebar-ring: oklch(0.67 0.21 158); } @layer base { * { @apply border-border outline-ring/50; } + body { - @apply bg-background text-foreground; + @apply bg-background text-foreground antialiased; } - html { - @apply font-sans; + + button:not(:disabled), + [role="button"]:not(:disabled) { + cursor: pointer; } -} +} \ No newline at end of file diff --git a/apps/frontend/src/routes/__root.tsx b/apps/frontend/src/routes/__root.tsx index 986e608..ad27d02 100644 --- a/apps/frontend/src/routes/__root.tsx +++ b/apps/frontend/src/routes/__root.tsx @@ -1,3 +1,4 @@ +import { Layout } from '@/components/layout'; import { NotFoundPage } from '@/features/not-found/not-found-page'; import { ServerErrorPage } from '@/features/server-error/server-error-page'; import type { ApiClient } from '@/lib/api-client'; @@ -10,7 +11,17 @@ type RouterContext = { }; export const Route = createRootRouteWithContext()({ - component: Outlet, + component: RootRoute, errorComponent: ServerErrorPage, notFoundComponent: NotFoundPage, }); + +function RootRoute() { + return ( + +
+ +
+
+ ) +} \ No newline at end of file