feat: add environment variables, update dashboard layout, and enhance routing components

This commit is contained in:
juan 2025-11-08 19:40:44 +01:00
parent e5c6278c90
commit 06f99c0eef
8 changed files with 180 additions and 26 deletions

5
.env Normal file
View File

@ -0,0 +1,5 @@
SUPABASE_URL="https://qsssikzgwomudkwfmgad.supabase.co"
# DATABASE_URL="postgresql://postgres.qsssikzgwomudkwfmgad:etrTXNz3ZOwaLJmT@aws-0-eu-north-1.pooler.supabase.com:6543/postgres"
DATABASE_URL="postgresql://postgres.qsssikzgwomudkwfmgad:Wrongly1-Untimed0-Peculiar0-Unlikable7-Cubbyhole8@aws-0-eu-north-1.pooler.supabase.com:6543/postgre"
APIKEY_MAPS="AIzaSyAwfOShBqkBcS46WqmlsIVWQJ8gpdOPk_4"
SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFzc3Npa3pnd29tdWRrd2ZtZ2FkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQzMjY1NTQsImV4cCI6MjA2OTkwMjU1NH0.BTSscdTcPP1GVmMB-H5caLpWsfuAw1V6mXiqogF8TjU"

1
.gitignore vendored
View File

@ -4,7 +4,6 @@ dist
dist-ssr dist-ssr
*.local *.local
count.txt count.txt
.env
.nitro .nitro
.tanstack .tanstack
.output .output

BIN
public/drone.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB

BIN
public/profile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -53,7 +53,15 @@ function RootDocument({ children }: { children: React.ReactNode }) {
<HeadContent /> <HeadContent />
</head> </head>
<body> <body>
<HeroUIProvider>{children}</HeroUIProvider> <div
className="min-h-screen bg-gradient-to-br from-green-200 to-emerald-400"
style={{
backgroundImage:
"radial-gradient(50% 50% at 95% 5%, #34d399 0%, #6ee7b7 70%, #f5f5f5 100%)"
}}
>
<HeroUIProvider>{children}</HeroUIProvider>
</div>
<SonnerProvider /> <SonnerProvider />
<TanStackRouterDevtools /> <TanStackRouterDevtools />
<Scripts /> <Scripts />

View File

@ -1,4 +1,11 @@
import { createFileRoute } from "@tanstack/react-router" import {
Avatar,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownTrigger
} from "@heroui/react"
import { createFileRoute, Outlet } from "@tanstack/react-router"
import { getProfile } from "@/lib/server/user" import { getProfile } from "@/lib/server/user"
export const Route = createFileRoute("/_authed")({ export const Route = createFileRoute("/_authed")({
@ -8,7 +15,7 @@ export const Route = createFileRoute("/_authed")({
// TODO: Redirect to login page // TODO: Redirect to login page
} }
}, },
loader: ({context: {queryClient, user}} ) => { loader: ({ context: { queryClient, user } }) => {
queryClient.ensureQueryData({ queryClient.ensureQueryData({
queryKey: ["profile"], queryKey: ["profile"],
queryFn: () => getProfile({ data: { id: user?.id as string } }) queryFn: () => getProfile({ data: { id: user?.id as string } })
@ -23,5 +30,38 @@ export const Route = createFileRoute("/_authed")({
) )
} }
throw error throw error
} },
component: RouteComponent
}) })
function RouteComponent() {
const navigate = Route.useNavigate()
return (
<div>
<nav className="flex gap-2 p-2 mb-2 rounded-md bg-clip-padding backdrop-filter backdrop-blur-xl bg-opacity-10 sticky top-0 z-20">
<div className="w-full justify-between flex items-center">
<div />
<h1 className="font-black text-2xl md:text-4xl">FindYourPilots</h1>
<Dropdown>
<DropdownTrigger>
<Avatar isBordered src="/profile.png" />
</DropdownTrigger>
<DropdownMenu
onAction={(key) => {
if (key === "exit") {
navigate({ to: "/logout" })
}
}}
>
<DropdownItem color="danger" key="exit">
Logout
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
<div></div>
</nav>
<Outlet />
</div>
)
}

View File

@ -1,4 +1,12 @@
import { Button } from "@heroui/react" import {
Avatar,
Card,
CardBody,
CardFooter,
CardHeader,
Chip,
Divider
} from "@heroui/react"
import { useQuery } from "@tanstack/react-query" import { useQuery } from "@tanstack/react-query"
import { createFileRoute } from "@tanstack/react-router" import { createFileRoute } from "@tanstack/react-router"
import { getAllUsers, getProfile } from "@/lib/server/user" import { getAllUsers, getProfile } from "@/lib/server/user"
@ -8,9 +16,8 @@ export const Route = createFileRoute("/_authed/dashboard")({
}) })
function RouteComponent() { function RouteComponent() {
const navigate = Route.useNavigate()
const { user } = Route.useRouteContext() const { user } = Route.useRouteContext()
console.log("User in dashboard:", user)
const { data } = useQuery({ const { data } = useQuery({
queryKey: ["users"], queryKey: ["users"],
queryFn: async () => { queryFn: async () => {
@ -25,24 +32,110 @@ function RouteComponent() {
} }
}) })
console.log(data)
console.log(profile)
return ( return (
<div> <div className="flex justify-center items-center flex-col gap-2">
Hello "/_authed/dashboard"!{" "} <Card className="max-w-6xl border-none" fullWidth shadow="none">
<div> <CardHeader className="mb-0 pb-0 justify-between flex-wrap gap-2">
{" "} <Chip variant="light" size="lg">
<Button Inicio {profile?.firstName ?? "demo"}
onPress={() => </Chip>
navigate({ <div className="rounded-md bg-warning/30 border-2 border-warning/70 px-3 py-1">
to: "/logout" <p> 🏗 La web está en mantenimiento</p>
}) </div>
} </CardHeader>
> <CardBody>
Logout {/* === GRID PRINCIPAL === */}
</Button> <div className="grid sm:grid-cols-3 grid-rows-[auto_1fr] gap-5 mt-2">
</div> {/* === Tarjeta 1: Mis drones === */}
<Card
shadow="none"
className="rounded-md max-w-sm bg-default-50"
isPressable
>
<CardHeader className="flex justify-between items-center gap-2">
<div className="flex flex-col gap-1 justify-start items-start">
<h2 className="text-start font-semibold text-lg">
Mis drones
</h2>
<p className="text-default-500 text-sm text-start">
Actualiza tus drones en uso o pilotados.
</p>
</div>
<Avatar
src="/drone.webp"
alt="Drone"
className="rounded-full"
/>
</CardHeader>
<CardFooter>
<p className="text-default-500 text-sm text-start">Ver más</p>
</CardFooter>
</Card>
{/* === Tarjeta 2: Datos personales === */}
<Card
shadow="none"
className="rounded-md max-w-sm bg-default-50"
isPressable
>
<CardHeader className="flex justify-between items-center gap-2">
<div className="flex flex-col gap-1 justify-start items-start">
<h2 className="text-start font-semibold text-lg">
Datos personales
</h2>
<p className="text-default-500 text-sm text-start">
Actualiza tu información, ubicación y detalles.
</p>
</div>
<Avatar
src="/profile.png"
alt="User"
className="rounded-full"
/>
</CardHeader>
<CardFooter>
<p className="text-default-500 text-sm">Ver más</p>
</CardFooter>
</Card>
{/* === Tarjeta 3: Ofertas de vuelo === */}
<Card
shadow="none"
className="rounded-md max-w-sm bg-default-50 row-span-2 self-end h-full"
isPressable
>
<CardHeader className="flex justify-between items-center gap-2">
<div className="flex flex-col gap-1 justify-start items-start">
<h2 className="text-start font-semibold text-lg">
Ofertas de vuelo
</h2>
<p className="text-default-500 text-sm text-start">
Explora y gestiona tus ofertas de vuelo activas.
</p>
</div>
<Avatar
src="/profile.png"
alt="User"
className="rounded-full"
/>
</CardHeader>
<CardBody>
<p className="text-default-500 text-sm">Próximamente...</p>
</CardBody>
<CardFooter>
<p className="text-default-500 text-sm">Ver más</p>
</CardFooter>
</Card>
{/* === Mapa (ocupa 2 columnas) === */}
<div className="w-full h-[400px] bg-default-100 col-span-2 rounded-md flex justify-center items-center">
{/* Aquí irá el mapa */}
</div>
</div>
</CardBody>
</Card>
</div> </div>
) )
} }
export default RouteComponent

View File

@ -1,3 +1,4 @@
@import url('https://fonts.googleapis.com/css2?family=Luckiest+Guy&family=Outfit:wght@100..900&family=Rubik+Vinyl&display=swap');
@import "tailwindcss"; @import "tailwindcss";
@plugin '../integrations/heroui/heroui.ts'; @plugin '../integrations/heroui/heroui.ts';
@ -13,7 +14,15 @@ body {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
@theme {
--font-outfit: "Outfit", sans-serif;
--font-rubik-vinyl: "Rubik Vinyl", cursive;
--font-luckiest-guy: "Luckiest Guy", cursive;
}
code { code {
font-family: font-family:
source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
} }