From cbd0cdced40eb4cf490292d655c03879d617b1cd Mon Sep 17 00:00:00 2001 From: BeauTroll <-> Date: Mon, 19 Jan 2026 18:09:23 +0100 Subject: [PATCH] biome lint applied --- biome.json | 70 +- docs/stories/1.1.story.md | 4 +- src/components/Header.tsx | 40 +- src/components/character-list.tsx | 820 ++++++++++++------------ src/components/confirmation-modal.tsx | 90 +-- src/components/layout/app-header.tsx | 120 ++-- src/components/layout/app-shell.tsx | 82 +-- src/components/layout/app-sidebar.tsx | 182 +++--- src/components/layout/dashboard.tsx | 492 +++++++------- src/components/progression-section.tsx | 180 +++--- src/components/team-detail-page.tsx | 404 ++++++------ src/components/ui/button.tsx | 108 ++-- src/components/ui/card.tsx | 150 ++--- src/components/ui/input.tsx | 34 +- src/components/ui/table.tsx | 188 +++--- src/data/demo.punk-songs.ts | 20 +- src/lib/server/db.ts | 22 +- src/lib/utils.ts | 6 +- src/routeTree.gen.ts | 361 +++++------ src/router.tsx | 20 +- src/routes/__root.tsx | 100 +-- src/routes/api/health.ts | 34 +- src/routes/demo/api.names.ts | 16 +- src/routes/demo/start.api-request.tsx | 47 +- src/routes/demo/start.server-funcs.tsx | 128 ++-- src/routes/demo/start.ssr.data-only.tsx | 38 +- src/routes/demo/start.ssr.full-ssr.tsx | 36 +- src/routes/demo/start.ssr.index.tsx | 38 +- src/routes/demo/start.ssr.spa-mode.tsx | 48 +- src/routes/index.tsx | 66 +- 30 files changed, 1973 insertions(+), 1971 deletions(-) diff --git a/biome.json b/biome.json index b908ab4..5079d3a 100644 --- a/biome.json +++ b/biome.json @@ -1,37 +1,37 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json", - "vcs": { - "enabled": true, - "clientKind": "git", - "useIgnoreFile": true - }, - "files": { - "includes": ["src/**/*.ts", "src/**/*.tsx"], - "ignoreUnknown": false - }, - "formatter": { - "enabled": true, - "indentStyle": "tab" - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true - } - }, - "javascript": { - "formatter": { - "quoteStyle": "single", - "semicolons": "always", - "trailingCommas": "all" - } - }, - "assist": { - "enabled": true, - "actions": { - "source": { - "organizeImports": "on" - } - } - } + "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "includes": ["src/**/*.ts", "src/**/*.tsx"], + "ignoreUnknown": false + }, + "formatter": { + "enabled": true, + "indentStyle": "tab" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "semicolons": "always", + "trailingCommas": "all" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + } } diff --git a/docs/stories/1.1.story.md b/docs/stories/1.1.story.md index 974e261..d9e4284 100644 --- a/docs/stories/1.1.story.md +++ b/docs/stories/1.1.story.md @@ -57,8 +57,8 @@ Draft - [ ] Task 5: Configure linting and formatting (AC: 5) - [x] Install Biome (as specified in tech stack, not ESLint+Prettier) - - [ ] Create `biome.json` with recommended rules - - [ ] Add lint and format scripts to `package.json` + - [x] Create `biome.json` with recommended rules + - [x] Add lint and format scripts to `package.json` - [ ] Verify linting works on project files - [ ] Task 6: Setup Gitea Actions workflow (AC: 6) diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 0347cfc..e4c28a0 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,27 +1,27 @@ -import { Link } from '@tanstack/react-router' +import { Link } from '@tanstack/react-router'; -import './Header.css' +import './Header.css'; export default function Header() { - return ( -
- +
+ ); } diff --git a/src/components/character-list.tsx b/src/components/character-list.tsx index f660fd3..6031558 100644 --- a/src/components/character-list.tsx +++ b/src/components/character-list.tsx @@ -1,437 +1,437 @@ -import * as React from "react"; import { - Search, - Plus, - ChevronDown, - ChevronUp, - ArrowUpDown, -} from "lucide-react"; -import { Input } from "@/components/ui/input"; -import { Button } from "@/components/ui/button"; -import { Checkbox } from "@/components/ui/checkbox"; + ArrowUpDown, + ChevronDown, + ChevronUp, + Plus, + Search, +} from 'lucide-react'; +import * as React from 'react'; +import { Button } from '@/components/ui/button'; +import { Checkbox } from '@/components/ui/checkbox'; import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from '@/components/ui/collapsible'; import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@/components/ui/collapsible"; + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { Input } from '@/components/ui/input'; +import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; -import { cn } from "@/lib/utils"; + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table'; +import { cn } from '@/lib/utils'; // Sample data const characters = [ - { - id: 1, - nom: "Krosmaster", - classe: "Cra", - niveau: 200, - serveur: "Imagiro", - compte: "Compte1", - }, - { - id: 2, - nom: "TankMaster", - classe: "Iop", - niveau: 200, - serveur: "Imagiro", - compte: "Compte1", - }, - { - id: 3, - nom: "MoneyMaker", - classe: "Enu", - niveau: 200, - serveur: "Imagiro", - compte: "Compte2", - }, - { - id: 4, - nom: "HealBot", - classe: "Eni", - niveau: 195, - serveur: "Tylezia", - compte: "Compte2", - }, - { - id: 5, - nom: "ShadowKill", - classe: "Sram", - niveau: 200, - serveur: "Draconiros", - compte: "Compte3", - }, - { - id: 6, - nom: "TimeWarp", - classe: "Elio", - niveau: 180, - serveur: "Imagiro", - compte: "Compte1", - }, - { - id: 7, - nom: "ArrowStorm", - classe: "Cra", - niveau: 200, - serveur: "Tylezia", - compte: "Compte4", - }, - { - id: 8, - nom: "BerserkerX", - classe: "Iop", - niveau: 175, - serveur: "Draconiros", - compte: "Compte3", - }, + { + id: 1, + nom: 'Krosmaster', + classe: 'Cra', + niveau: 200, + serveur: 'Imagiro', + compte: 'Compte1', + }, + { + id: 2, + nom: 'TankMaster', + classe: 'Iop', + niveau: 200, + serveur: 'Imagiro', + compte: 'Compte1', + }, + { + id: 3, + nom: 'MoneyMaker', + classe: 'Enu', + niveau: 200, + serveur: 'Imagiro', + compte: 'Compte2', + }, + { + id: 4, + nom: 'HealBot', + classe: 'Eni', + niveau: 195, + serveur: 'Tylezia', + compte: 'Compte2', + }, + { + id: 5, + nom: 'ShadowKill', + classe: 'Sram', + niveau: 200, + serveur: 'Draconiros', + compte: 'Compte3', + }, + { + id: 6, + nom: 'TimeWarp', + classe: 'Elio', + niveau: 180, + serveur: 'Imagiro', + compte: 'Compte1', + }, + { + id: 7, + nom: 'ArrowStorm', + classe: 'Cra', + niveau: 200, + serveur: 'Tylezia', + compte: 'Compte4', + }, + { + id: 8, + nom: 'BerserkerX', + classe: 'Iop', + niveau: 175, + serveur: 'Draconiros', + compte: 'Compte3', + }, ]; const classes = [ - { name: "Cra", count: 12 }, - { name: "Iop", count: 8 }, - { name: "Enu", count: 6 }, - { name: "Eni", count: 5 }, - { name: "Elio", count: 4 }, - { name: "Sram", count: 6 }, + { name: 'Cra', count: 12 }, + { name: 'Iop', count: 8 }, + { name: 'Enu', count: 6 }, + { name: 'Eni', count: 5 }, + { name: 'Elio', count: 4 }, + { name: 'Sram', count: 6 }, ]; -const serveurs = ["Imagiro", "Tylezia", "Draconiros"]; +const serveurs = ['Imagiro', 'Tylezia', 'Draconiros']; export function CharacterList() { - const [selectedIds, setSelectedIds] = React.useState([]); - const [classeOpen, setClasseOpen] = React.useState(true); - const [serveurOpen, setServeurOpen] = React.useState(true); - const [progressionOpen, setProgressionOpen] = React.useState(true); + const [selectedIds, setSelectedIds] = React.useState([]); + const [classeOpen, setClasseOpen] = React.useState(true); + const [serveurOpen, setServeurOpen] = React.useState(true); + const [progressionOpen, setProgressionOpen] = React.useState(true); - const toggleSelect = (id: number) => { - setSelectedIds((prev) => - prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id], - ); - }; + const toggleSelect = (id: number) => { + setSelectedIds((prev) => + prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id], + ); + }; - const toggleSelectAll = () => { - if (selectedIds.length === characters.length) { - setSelectedIds([]); - } else { - setSelectedIds(characters.map((c) => c.id)); - } - }; + const toggleSelectAll = () => { + if (selectedIds.length === characters.length) { + setSelectedIds([]); + } else { + setSelectedIds(characters.map((c) => c.id)); + } + }; - return ( -
- {/* Filter Sidebar */} - - {/* Main Content */} -
- {/* Toolbar */} -
-
- - -
+ {/* Main Content */} +
+ {/* Toolbar */} +
+
+ + +
-
- {selectedIds.length > 0 && ( - <> - - {selectedIds.length} sélectionné - {selectedIds.length > 1 ? "s" : ""} - - - - - - - - Exporter - - - Supprimer - - - - - )} - -
-
+
+ {selectedIds.length > 0 && ( + <> + + {selectedIds.length} sélectionné + {selectedIds.length > 1 ? 's' : ''} + + + + + + + + Exporter + + + Supprimer + + + + + )} + +
+
- {/* Table */} -
- - - - - 0 - } - onCheckedChange={toggleSelectAll} - className="border-[#475569] data-[state=checked]:bg-[#60A5FA] data-[state=checked]:border-[#60A5FA]" - /> - - - - - Classe - - - - Serveur - Compte - - - - {characters.map((character) => { - const isSelected = selectedIds.includes(character.id); - return ( - - - toggleSelect(character.id)} - className="border-[#475569] data-[state=checked]:bg-[#60A5FA] data-[state=checked]:border-[#60A5FA]" - /> - - - {character.nom} - - - {character.classe} - - - {character.niveau} - - - {character.serveur} - - - {character.compte} - - - ); - })} - -
-
+ {/* Table */} +
+ + + + + 0 + } + onCheckedChange={toggleSelectAll} + className="border-[#475569] data-[state=checked]:bg-[#60A5FA] data-[state=checked]:border-[#60A5FA]" + /> + + + + + Classe + + + + Serveur + Compte + + + + {characters.map((character) => { + const isSelected = selectedIds.includes(character.id); + return ( + + + toggleSelect(character.id)} + className="border-[#475569] data-[state=checked]:bg-[#60A5FA] data-[state=checked]:border-[#60A5FA]" + /> + + + {character.nom} + + + {character.classe} + + + {character.niveau} + + + {character.serveur} + + + {character.compte} + + + ); + })} + +
+
- {/* Pagination Footer */} -
- Showing 1-8 of 64 -
- - - - - -
-
-
-
- ); + {/* Pagination Footer */} +
+ Showing 1-8 of 64 +
+ + + + + +
+
+
+ + ); } diff --git a/src/components/confirmation-modal.tsx b/src/components/confirmation-modal.tsx index 6336fa3..3442d00 100644 --- a/src/components/confirmation-modal.tsx +++ b/src/components/confirmation-modal.tsx @@ -1,54 +1,54 @@ +import { Button } from '@/components/ui/button'; import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; -import { Button } from "@/components/ui/button"; + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; interface ConfirmationModalProps { - open: boolean; - onOpenChange: (open: boolean) => void; - progressionName: string; - incompleteCount: number; + open: boolean; + onOpenChange: (open: boolean) => void; + progressionName: string; + incompleteCount: number; } export function ConfirmationModal({ - open, - onOpenChange, - progressionName, - incompleteCount, + open, + onOpenChange, + progressionName, + incompleteCount, }: ConfirmationModalProps) { - const handleConfirm = () => { - // Do NOT implement actual update logic - onOpenChange(false); - }; + const handleConfirm = () => { + // Do NOT implement actual update logic + onOpenChange(false); + }; - return ( - - - - Confirmer la mise à jour - - Marquer {progressionName} comme fait pour {incompleteCount}{" "} - personnages ? - - - - - - - - - ); + return ( + + + + Confirmer la mise à jour + + Marquer {progressionName} comme fait pour {incompleteCount}{' '} + personnages ? + + + + + + + + + ); } diff --git a/src/components/layout/app-header.tsx b/src/components/layout/app-header.tsx index 6a79ed8..8a70698 100644 --- a/src/components/layout/app-header.tsx +++ b/src/components/layout/app-header.tsx @@ -1,72 +1,72 @@ -import { useLocation } from "@tanstack/react-router"; -import { Button } from "@/components/ui/button"; -import { Moon, Sun, ChevronRight } from "lucide-react"; +import { useLocation } from '@tanstack/react-router'; +import { ChevronRight, Moon, Sun } from 'lucide-react'; +import { Button } from '@/components/ui/button'; const routeLabels: Record = { - "/": "Dashboard", - "/characters": "Personnages", - "/accounts": "Comptes", - "/teams": "Teams", - "/settings": "Paramètres", + '/': 'Dashboard', + '/characters': 'Personnages', + '/accounts': 'Comptes', + '/teams': 'Teams', + '/settings': 'Paramètres', }; interface AppHeaderProps { - theme: "dark" | "light"; - onToggleTheme: () => void; + theme: 'dark' | 'light'; + onToggleTheme: () => void; } export function AppHeader({ theme, onToggleTheme }: AppHeaderProps) { - const { pathname } = useLocation(); + const { pathname } = useLocation(); - // Generate breadcrumb from pathname - const segments = pathname.split("/").filter(Boolean); - const breadcrumbs = - segments.length === 0 - ? [{ label: "Dashboard", href: "/" }] - : segments.map((segment, index) => { - const href = "/" + segments.slice(0, index + 1).join("/"); - const label = - routeLabels[href] || - segment.charAt(0).toUpperCase() + segment.slice(1); - return { label, href }; - }); + // Generate breadcrumb from pathname + const segments = pathname.split('/').filter(Boolean); + const breadcrumbs = + segments.length === 0 + ? [{ label: 'Dashboard', href: '/' }] + : segments.map((segment, index) => { + const href = '/' + segments.slice(0, index + 1).join('/'); + const label = + routeLabels[href] || + segment.charAt(0).toUpperCase() + segment.slice(1); + return { label, href }; + }); - return ( -
- {/* Breadcrumb */} - + return ( +
+ {/* Breadcrumb */} + - {/* Theme toggle */} - -
- ); + {/* Theme toggle */} + +
+ ); } diff --git a/src/components/layout/app-shell.tsx b/src/components/layout/app-shell.tsx index 997a190..b9ffed9 100644 --- a/src/components/layout/app-shell.tsx +++ b/src/components/layout/app-shell.tsx @@ -1,53 +1,53 @@ -import type React from "react"; +import type React from 'react'; -import { useState, useEffect } from "react"; -import { cn } from "@/lib/utils"; -import { AppSidebar } from "@/components/layout/app-sidebar"; -import { AppHeader } from "@/components/layout/app-header"; +import { useEffect, useState } from 'react'; +import { AppHeader } from '@/components/layout/app-header'; +import { AppSidebar } from '@/components/layout/app-sidebar'; +import { cn } from '@/lib/utils'; interface AppShellProps { - children: React.ReactNode; + children: React.ReactNode; } export function AppShell({ children }: AppShellProps) { - const [sidebarCollapsed, setSidebarCollapsed] = useState(false); - const [theme, setTheme] = useState<"dark" | "light">("dark"); + const [sidebarCollapsed, setSidebarCollapsed] = useState(false); + const [theme, setTheme] = useState<'dark' | 'light'>('dark'); - // Apply theme class to html element - useEffect(() => { - const root = document.documentElement; - if (theme === "light") { - root.classList.add("light"); - } else { - root.classList.remove("light"); - } - }, [theme]); + // Apply theme class to html element + useEffect(() => { + const root = document.documentElement; + if (theme === 'light') { + root.classList.add('light'); + } else { + root.classList.remove('light'); + } + }, [theme]); - const toggleTheme = () => { - setTheme((prev) => (prev === "dark" ? "light" : "dark")); - }; + const toggleTheme = () => { + setTheme((prev) => (prev === 'dark' ? 'light' : 'dark')); + }; - return ( -
- setSidebarCollapsed(!sidebarCollapsed)} - /> + return ( +
+ setSidebarCollapsed(!sidebarCollapsed)} + /> - {/* Main content area */} -
- + {/* Main content area */} +
+ - {/* Scrollable main content */} -
-
{children}
-
-
-
- ); + {/* Scrollable main content */} +
+
{children}
+
+
+
+ ); } diff --git a/src/components/layout/app-sidebar.tsx b/src/components/layout/app-sidebar.tsx index b965306..a1361ab 100644 --- a/src/components/layout/app-sidebar.tsx +++ b/src/components/layout/app-sidebar.tsx @@ -1,107 +1,107 @@ -import { Link, useLocation } from "@tanstack/react-router"; -import { cn } from "@/lib/utils"; -import { Button } from "@/components/ui/button"; +import { Link, useLocation } from '@tanstack/react-router'; import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip"; + ChevronLeft, + ChevronRight, + Folder, + Home, + Settings, + Swords, + Users, +} from 'lucide-react'; +import { Button } from '@/components/ui/button'; import { - Home, - Users, - Folder, - Swords, - Settings, - ChevronLeft, - ChevronRight, -} from "lucide-react"; + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui/tooltip'; +import { cn } from '@/lib/utils'; const navItems = [ - { icon: Home, label: "Dashboard", href: "/" }, - { icon: Users, label: "Personnages", href: "/characters" }, - { icon: Folder, label: "Comptes", href: "/accounts" }, - { icon: Swords, label: "Teams", href: "/teams" }, - { icon: Settings, label: "Paramètres", href: "/settings" }, + { icon: Home, label: 'Dashboard', href: '/' }, + { icon: Users, label: 'Personnages', href: '/characters' }, + { icon: Folder, label: 'Comptes', href: '/accounts' }, + { icon: Swords, label: 'Teams', href: '/teams' }, + { icon: Settings, label: 'Paramètres', href: '/settings' }, ]; interface AppSidebarProps { - collapsed: boolean; - onToggle: () => void; + collapsed: boolean; + onToggle: () => void; } export function AppSidebar({ collapsed, onToggle }: AppSidebarProps) { - const { pathname } = useLocation(); + const { pathname } = useLocation(); - return ( - - + + ); } diff --git a/src/components/layout/dashboard.tsx b/src/components/layout/dashboard.tsx index 8c946a9..f8817fb 100644 --- a/src/components/layout/dashboard.tsx +++ b/src/components/layout/dashboard.tsx @@ -1,273 +1,273 @@ -import type React from "react"; import { - FolderOpen, - Users, - Swords, - Coins, - BarChart3, - Plus, - ChevronDown, - ArrowRight, - RefreshCw, -} from "lucide-react"; + ArrowRight, + BarChart3, + ChevronDown, + Coins, + FolderOpen, + Plus, + RefreshCw, + Swords, + Users, +} from 'lucide-react'; +import type React from 'react'; +import { Button } from '@/components/ui/button'; import { - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; + Card, + CardContent, + CardFooter, + CardHeader, + CardTitle, +} from '@/components/ui/card'; import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; // Custom progress bar with color support function ColoredProgress({ - value, - color, + value, + color, }: { - value: number; - color: "success" | "warning" | "info"; + value: number; + color: 'success' | 'warning' | 'info'; }) { - const colorClasses = { - success: "bg-[#4ADE80]", - warning: "bg-[#FBBF24]", - info: "bg-[#60A5FA]", - }; + const colorClasses = { + success: 'bg-[#4ADE80]', + warning: 'bg-[#FBBF24]', + info: 'bg-[#60A5FA]', + }; - return ( -
-
-
- ); + return ( +
+
+
+ ); } // Stat card component with hover effect function StatCard({ - icon: Icon, - title, - mainStat, - secondary, - linkText, - children, - className = "", + icon: Icon, + title, + mainStat, + secondary, + linkText, + children, + className = '', }: { - icon: React.ElementType; - title: string; - mainStat?: string; - secondary?: React.ReactNode; - linkText: string; - children?: React.ReactNode; - className?: string; + icon: React.ElementType; + title: string; + mainStat?: string; + secondary?: React.ReactNode; + linkText: string; + children?: React.ReactNode; + className?: string; }) { - return ( - - -
-
- -
- - {title} - -
-
- - {mainStat && ( -

{mainStat}

- )} - {secondary &&
{secondary}
} - {children} -
- - - -
- ); + return ( + + +
+
+ +
+ + {title} + +
+
+ + {mainStat && ( +

{mainStat}

+ )} + {secondary &&
{secondary}
} + {children} +
+ + + +
+ ); } export function Dashboard() { - // Mock data - const currencies = [ - { name: "Doplons", amount: "12,450" }, - { name: "Orichor", amount: "3,200" }, - { name: "Kamas glace", amount: "8,100" }, - { name: "Nuggets", amount: "2,340" }, - ]; + // Mock data + const currencies = [ + { name: 'Doplons', amount: '12,450' }, + { name: 'Orichor', amount: '3,200' }, + { name: 'Kamas glace', amount: '8,100' }, + { name: 'Nuggets', amount: '2,340' }, + ]; - const progressions = [ - { label: "Dofus", value: 72, color: "success" as const }, - { label: "Donjons", value: 45, color: "warning" as const }, - { label: "Recherchés", value: 61, color: "info" as const }, - ]; + const progressions = [ + { label: 'Dofus', value: 72, color: 'success' as const }, + { label: 'Donjons', value: 45, color: 'warning' as const }, + { label: 'Recherchés', value: 61, color: 'info' as const }, + ]; - return ( -
- {/* Header */} -
-

DASHBOARD

- - - - - - - Personnage - - - Compte - - - Team - - - -
+ return ( +
+ {/* Header */} +
+

DASHBOARD

+ + + + + + + Personnage + + + Compte + + + Team + + + +
- {/* Widget Grid */} -
- {/* Comptes Card */} - + {/* Widget Grid */} +
+ {/* Comptes Card */} + - {/* Personnages Card */} - + {/* Personnages Card */} + - {/* Teams Card */} - - 87% complete - -
- } - linkText="Voir tout" - /> + {/* Teams Card */} + + 87% complete + +
+ } + linkText="Voir tout" + /> - {/* Monnaies Card - spans 2 columns on desktop */} - - -
-
- -
- - Monnaies - -
-
- -
- {currencies.map((currency) => ( -
-

{currency.name}

-

- {currency.amount} -

-
- ))} -
-
- - - -
+ {/* Monnaies Card - spans 2 columns on desktop */} + + +
+
+ +
+ + Monnaies + +
+
+ +
+ {currencies.map((currency) => ( +
+

{currency.name}

+

+ {currency.amount} +

+
+ ))} +
+
+ + + +
- {/* Progressions Card */} - - -
-
- -
- - Progressions - -
-
- - {progressions.map((prog) => ( -
-
- {prog.label} - {prog.value}% -
- -
- ))} -
- - - -
-
+ {/* Progressions Card */} + + +
+
+ +
+ + Progressions + +
+
+ + {progressions.map((prog) => ( +
+
+ {prog.label} + {prog.value}% +
+ +
+ ))} +
+ + + +
+
- {/* Quick Actions Section */} -
-

- Actions Rapides -

-
- - - - -
-
-
- ); + {/* Quick Actions Section */} +
+

+ Actions Rapides +

+
+ + + + +
+
+
+ ); } diff --git a/src/components/progression-section.tsx b/src/components/progression-section.tsx index 3e8c7dd..b4f6d59 100644 --- a/src/components/progression-section.tsx +++ b/src/components/progression-section.tsx @@ -1,106 +1,106 @@ -import { useState } from "react"; -import { ChevronDown, ChevronRight, Check } from "lucide-react"; -import { Checkbox } from "@/components/ui/checkbox"; +import { Check, ChevronDown, ChevronRight } from 'lucide-react'; +import { useState } from 'react'; +import { Checkbox } from '@/components/ui/checkbox'; import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@/components/ui/collapsible"; -import { cn } from "@/lib/utils"; + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from '@/components/ui/collapsible'; +import { cn } from '@/lib/utils'; interface ProgressionItem { - id: string; - name: string; - completed: boolean; - completedDate?: string; + id: string; + name: string; + completed: boolean; + completedDate?: string; } interface ProgressionSectionProps { - title: string; - items: ProgressionItem[]; - filter: "all" | "done" | "not-done"; + title: string; + items: ProgressionItem[]; + filter: 'all' | 'done' | 'not-done'; } export function ProgressionSection({ - title, - items, - filter, + title, + items, + filter, }: ProgressionSectionProps) { - const [isOpen, setIsOpen] = useState(true); - const [localItems, setLocalItems] = useState(items); + const [isOpen, setIsOpen] = useState(true); + const [localItems, setLocalItems] = useState(items); - const filteredItems = localItems.filter((item) => { - if (filter === "done") return item.completed; - if (filter === "not-done") return !item.completed; - return true; - }); + const filteredItems = localItems.filter((item) => { + if (filter === 'done') return item.completed; + if (filter === 'not-done') return !item.completed; + return true; + }); - const completedCount = localItems.filter((item) => item.completed).length; - const totalCount = localItems.length; + const completedCount = localItems.filter((item) => item.completed).length; + const totalCount = localItems.length; - const handleToggle = (id: string) => { - setLocalItems((prev) => - prev.map((item) => - item.id === id - ? { - ...item, - completed: !item.completed, - completedDate: !item.completed - ? new Date().toISOString().split("T")[0] - : undefined, - } - : item, - ), - ); - }; + const handleToggle = (id: string) => { + setLocalItems((prev) => + prev.map((item) => + item.id === id + ? { + ...item, + completed: !item.completed, + completedDate: !item.completed + ? new Date().toISOString().split('T')[0] + : undefined, + } + : item, + ), + ); + }; - if (filteredItems.length === 0) return null; + if (filteredItems.length === 0) return null; - return ( - - - {isOpen ? ( - - ) : ( - - )} - {title} - - ({completedCount}/{totalCount}) - - - - {filteredItems.map((item) => ( -
- handleToggle(item.id)} - className="border-muted-foreground data-[state=checked]:bg-primary data-[state=checked]:border-primary" - /> - - {item.completed ? ( -
- - {item.completedDate} -
- ) : ( - - )} -
- ))} -
-
- ); + return ( + + + {isOpen ? ( + + ) : ( + + )} + {title} + + ({completedCount}/{totalCount}) + + + + {filteredItems.map((item) => ( +
+ handleToggle(item.id)} + className="border-muted-foreground data-[state=checked]:bg-primary data-[state=checked]:border-primary" + /> + + {item.completed ? ( +
+ + {item.completedDate} +
+ ) : ( + + )} +
+ ))} +
+
+ ); } diff --git a/src/components/team-detail-page.tsx b/src/components/team-detail-page.tsx index 6f473d7..44dddae 100644 --- a/src/components/team-detail-page.tsx +++ b/src/components/team-detail-page.tsx @@ -1,225 +1,225 @@ -import { useState } from "react"; import { - ChevronRight, - Pencil, - Trash2, - CheckCircle, - XCircle, -} from "lucide-react"; -import { Card, CardContent } from "@/components/ui/card"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; + CheckCircle, + ChevronRight, + Pencil, + Trash2, + XCircle, +} from 'lucide-react'; +import { useState } from 'react'; +import { ConfirmationModal } from '@/components/confirmation-modal'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent } from '@/components/ui/card'; +import { Progress } from '@/components/ui/progress'; import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { Progress } from "@/components/ui/progress"; -import { Button } from "@/components/ui/button"; + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; -import { Badge } from "@/components/ui/badge"; -import { ConfirmationModal } from "@/components/confirmation-modal"; + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; // Mock data const teamMembers = [ - { id: 1, name: "Krosmaster", completed: true, date: "2026-01-10" }, - { id: 2, name: "TankMaster", completed: true, date: "2026-01-10" }, - { id: 3, name: "HealBot", completed: false, date: null }, - { id: 4, name: "SramKiller", completed: false, date: null }, - { id: 5, name: "Eniripsa", completed: true, date: "2026-01-09" }, - { id: 6, name: "Sacrieur", completed: true, date: "2026-01-08" }, - { id: 7, name: "Pandawa", completed: true, date: "2026-01-10" }, - { id: 8, name: "Eliotrope", completed: true, date: "2026-01-07" }, + { id: 1, name: 'Krosmaster', completed: true, date: '2026-01-10' }, + { id: 2, name: 'TankMaster', completed: true, date: '2026-01-10' }, + { id: 3, name: 'HealBot', completed: false, date: null }, + { id: 4, name: 'SramKiller', completed: false, date: null }, + { id: 5, name: 'Eniripsa', completed: true, date: '2026-01-09' }, + { id: 6, name: 'Sacrieur', completed: true, date: '2026-01-08' }, + { id: 7, name: 'Pandawa', completed: true, date: '2026-01-10' }, + { id: 8, name: 'Eliotrope', completed: true, date: '2026-01-07' }, ]; const progressions = [ - { id: "dofus-turquoise", name: "Dofus Turquoise" }, - { id: "donjon-bethel", name: "Donjon Bethel" }, - { id: "quete-ebene", name: "Quête Ébène" }, - { id: "succes-dimension", name: "Succès Dimension" }, + { id: 'dofus-turquoise', name: 'Dofus Turquoise' }, + { id: 'donjon-bethel', name: 'Donjon Bethel' }, + { id: 'quete-ebene', name: 'Quête Ébène' }, + { id: 'succes-dimension', name: 'Succès Dimension' }, ]; export default function TeamDetailPage() { - const [selectedProgression, setSelectedProgression] = - useState("dofus-turquoise"); - const [isModalOpen, setIsModalOpen] = useState(false); + const [selectedProgression, setSelectedProgression] = + useState('dofus-turquoise'); + const [isModalOpen, setIsModalOpen] = useState(false); - const completedCount = teamMembers.filter((m) => m.completed).length; - const totalCount = teamMembers.length; - const incompleteCount = totalCount - completedCount; - const progressPercentage = Math.round((completedCount / totalCount) * 100); + const completedCount = teamMembers.filter((m) => m.completed).length; + const totalCount = teamMembers.length; + const incompleteCount = totalCount - completedCount; + const progressPercentage = Math.round((completedCount / totalCount) * 100); - const selectedProgressionName = - progressions.find((p) => p.id === selectedProgression)?.name || ""; + const selectedProgressionName = + progressions.find((p) => p.id === selectedProgression)?.name || ''; - return ( -
-
- {/* Header with Breadcrumb and Actions */} -
- -
- - -
-
+ return ( +
+
+ {/* Header with Breadcrumb and Actions */} +
+ +
+ + +
+
- {/* Team Info Card */} - - -

MAIN TEAM

-

Type: Main

-
- {totalCount} membres - - - ✅ Active - - - {totalCount} comptes différents -
-
-
+ {/* Team Info Card */} + + +

MAIN TEAM

+

Type: Main

+
+ {totalCount} membres + + + ✅ Active + + + {totalCount} comptes différents +
+
+
- {/* Tabs */} - - - - Membres - - - Statut Progressions - - + {/* Tabs */} + + + + Membres + + + Statut Progressions + + - {/* Membres Tab - Placeholder */} - - - -

- Liste des membres à venir... -

-
-
-
+ {/* Membres Tab - Placeholder */} + + + +

+ Liste des membres à venir... +

+
+
+
- {/* Statut Progressions Tab */} - - {/* Progression Selector */} -
- - -
+ {/* Statut Progressions Tab */} + + {/* Progression Selector */} +
+ + +
- {/* Progress Summary */} - - -
-
-
- - {progressPercentage}% ({completedCount}/{totalCount}) - -
- -
- -
-
-
+ {/* Progress Summary */} + + +
+
+
+ + {progressPercentage}% ({completedCount}/{totalCount}) + +
+ +
+ +
+
+
- {/* Status Table */} - - - - - - Perso - Statut - Date - - - - {teamMembers.map((member) => ( - - - {member.name} - - - {member.completed ? ( - - ) : ( - - )} - - - {member.date || "—"} - - - ))} - -
-
-
-
-
-
+ {/* Status Table */} + + + + + + Perso + Statut + Date + + + + {teamMembers.map((member) => ( + + + {member.name} + + + {member.completed ? ( + + ) : ( + + )} + + + {member.date || '—'} + + + ))} + +
+
+
+ + +
- {/* Confirmation Modal */} - -
- ); + {/* Confirmation Modal */} + +
+ ); } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 37a7d4b..cfd2249 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,62 +1,62 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; +import type * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", - outline: - "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: - "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-9 px-4 py-2 has-[>svg]:px-3", - sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", - lg: "h-10 rounded-md px-6 has-[>svg]:px-4", - icon: "size-9", - "icon-sm": "size-8", - "icon-lg": "size-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: + 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', + outline: + 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', + secondary: + 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: + 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-9 px-4 py-2 has-[>svg]:px-3', + sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', + lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + icon: 'size-9', + 'icon-sm': 'size-8', + 'icon-lg': 'size-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + }, +); function Button({ - className, - variant = "default", - size = "default", - asChild = false, - ...props -}: React.ComponentProps<"button"> & - VariantProps & { - asChild?: boolean - }) { - const Comp = asChild ? Slot : "button" + className, + variant = 'default', + size = 'default', + asChild = false, + ...props +}: React.ComponentProps<'button'> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot : 'button'; - return ( - - ) + return ( + + ); } -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx index 681ad98..f50e940 100644 --- a/src/components/ui/card.tsx +++ b/src/components/ui/card.tsx @@ -1,92 +1,92 @@ -import * as React from "react" +import type * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -function Card({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) +function Card({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); } -function CardHeader({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) +function CardHeader({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); } -function CardTitle({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) +function CardTitle({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); } -function CardDescription({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) +function CardDescription({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); } -function CardAction({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) +function CardAction({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); } -function CardContent({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) +function CardContent({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); } -function CardFooter({ className, ...props }: React.ComponentProps<"div">) { - return ( -
- ) +function CardFooter({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ); } export { - Card, - CardHeader, - CardFooter, - CardTitle, - CardAction, - CardDescription, - CardContent, -} + Card, + CardHeader, + CardFooter, + CardTitle, + CardAction, + CardDescription, + CardContent, +}; diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 8916905..366363d 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -1,21 +1,21 @@ -import * as React from "react" +import type * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -function Input({ className, type, ...props }: React.ComponentProps<"input">) { - return ( - - ) +function Input({ className, type, ...props }: React.ComponentProps<'input'>) { + return ( + + ); } -export { Input } +export { Input }; diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx index 5513a5c..0ea811d 100644 --- a/src/components/ui/table.tsx +++ b/src/components/ui/table.tsx @@ -1,114 +1,114 @@ -import * as React from "react" +import type * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -function Table({ className, ...props }: React.ComponentProps<"table">) { - return ( -
- - - ) +function Table({ className, ...props }: React.ComponentProps<'table'>) { + return ( +
+
+ + ); } -function TableHeader({ className, ...props }: React.ComponentProps<"thead">) { - return ( - - ) +function TableHeader({ className, ...props }: React.ComponentProps<'thead'>) { + return ( + + ); } -function TableBody({ className, ...props }: React.ComponentProps<"tbody">) { - return ( - - ) +function TableBody({ className, ...props }: React.ComponentProps<'tbody'>) { + return ( + + ); } -function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) { - return ( - tr]:last:border-b-0", - className - )} - {...props} - /> - ) +function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) { + return ( + tr]:last:border-b-0', + className, + )} + {...props} + /> + ); } -function TableRow({ className, ...props }: React.ComponentProps<"tr">) { - return ( - - ) +function TableRow({ className, ...props }: React.ComponentProps<'tr'>) { + return ( + + ); } -function TableHead({ className, ...props }: React.ComponentProps<"th">) { - return ( -
[role=checkbox]]:translate-y-[2px]", - className - )} - {...props} - /> - ) +function TableHead({ className, ...props }: React.ComponentProps<'th'>) { + return ( + [role=checkbox]]:translate-y-[2px]', + className, + )} + {...props} + /> + ); } -function TableCell({ className, ...props }: React.ComponentProps<"td">) { - return ( - [role=checkbox]]:translate-y-[2px]", - className - )} - {...props} - /> - ) +function TableCell({ className, ...props }: React.ComponentProps<'td'>) { + return ( + [role=checkbox]]:translate-y-[2px]', + className, + )} + {...props} + /> + ); } function TableCaption({ - className, - ...props -}: React.ComponentProps<"caption">) { - return ( -
- ) + className, + ...props +}: React.ComponentProps<'caption'>) { + return ( + + ); } export { - Table, - TableHeader, - TableBody, - TableFooter, - TableHead, - TableRow, - TableCell, - TableCaption, -} + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +}; diff --git a/src/data/demo.punk-songs.ts b/src/data/demo.punk-songs.ts index bc6086d..ae5e7d4 100644 --- a/src/data/demo.punk-songs.ts +++ b/src/data/demo.punk-songs.ts @@ -1,13 +1,13 @@ -import { createServerFn } from '@tanstack/react-start' +import { createServerFn } from '@tanstack/react-start'; export const getPunkSongs = createServerFn({ - method: 'GET', + method: 'GET', }).handler(async () => [ - { id: 1, name: 'Teenage Dirtbag', artist: 'Wheatus' }, - { id: 2, name: 'Smells Like Teen Spirit', artist: 'Nirvana' }, - { id: 3, name: 'The Middle', artist: 'Jimmy Eat World' }, - { id: 4, name: 'My Own Worst Enemy', artist: 'Lit' }, - { id: 5, name: 'Fat Lip', artist: 'Sum 41' }, - { id: 6, name: 'All the Small Things', artist: 'blink-182' }, - { id: 7, name: 'Beverly Hills', artist: 'Weezer' }, -]) + { id: 1, name: 'Teenage Dirtbag', artist: 'Wheatus' }, + { id: 2, name: 'Smells Like Teen Spirit', artist: 'Nirvana' }, + { id: 3, name: 'The Middle', artist: 'Jimmy Eat World' }, + { id: 4, name: 'My Own Worst Enemy', artist: 'Lit' }, + { id: 5, name: 'Fat Lip', artist: 'Sum 41' }, + { id: 6, name: 'All the Small Things', artist: 'blink-182' }, + { id: 7, name: 'Beverly Hills', artist: 'Weezer' }, +]); diff --git a/src/lib/server/db.ts b/src/lib/server/db.ts index 64e0259..7301858 100644 --- a/src/lib/server/db.ts +++ b/src/lib/server/db.ts @@ -1,18 +1,18 @@ -import { PrismaClient } from "@prisma/client"; +import { PrismaClient } from '@prisma/client'; const globalForPrisma = globalThis as unknown as { - prisma: PrismaClient | undefined; + prisma: PrismaClient | undefined; }; export const prisma = - globalForPrisma.prisma ?? - new PrismaClient({ - log: - process.env.NODE_ENV === "development" - ? ["query", "error", "warn"] - : ["error"], - }); + globalForPrisma.prisma ?? + new PrismaClient({ + log: + process.env.NODE_ENV === 'development' + ? ['query', 'error', 'warn'] + : ['error'], + }); -if (process.env.NODE_ENV !== "production") { - globalForPrisma.prisma = prisma; +if (process.env.NODE_ENV !== 'production') { + globalForPrisma.prisma = prisma; } diff --git a/src/lib/utils.ts b/src/lib/utils.ts index bd0c391..256f86f 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,6 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index b13c274..80598d8 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -8,212 +8,213 @@ // You should NOT make any changes in this file as it will be overwritten. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. -import { Route as rootRouteImport } from './routes/__root' -import { Route as IndexRouteImport } from './routes/index' -import { Route as DemoStartServerFuncsRouteImport } from './routes/demo/start.server-funcs' -import { Route as DemoStartApiRequestRouteImport } from './routes/demo/start.api-request' -import { Route as DemoApiNamesRouteImport } from './routes/demo/api.names' -import { Route as DemoStartSsrIndexRouteImport } from './routes/demo/start.ssr.index' -import { Route as DemoStartSsrSpaModeRouteImport } from './routes/demo/start.ssr.spa-mode' -import { Route as DemoStartSsrFullSsrRouteImport } from './routes/demo/start.ssr.full-ssr' -import { Route as DemoStartSsrDataOnlyRouteImport } from './routes/demo/start.ssr.data-only' +import { Route as rootRouteImport } from './routes/__root'; +import { Route as DemoApiNamesRouteImport } from './routes/demo/api.names'; +import { Route as DemoStartApiRequestRouteImport } from './routes/demo/start.api-request'; +import { Route as DemoStartServerFuncsRouteImport } from './routes/demo/start.server-funcs'; +import { Route as DemoStartSsrDataOnlyRouteImport } from './routes/demo/start.ssr.data-only'; +import { Route as DemoStartSsrFullSsrRouteImport } from './routes/demo/start.ssr.full-ssr'; +import { Route as DemoStartSsrIndexRouteImport } from './routes/demo/start.ssr.index'; +import { Route as DemoStartSsrSpaModeRouteImport } from './routes/demo/start.ssr.spa-mode'; +import { Route as IndexRouteImport } from './routes/index'; const IndexRoute = IndexRouteImport.update({ - id: '/', - path: '/', - getParentRoute: () => rootRouteImport, -} as any) + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any); const DemoStartServerFuncsRoute = DemoStartServerFuncsRouteImport.update({ - id: '/demo/start/server-funcs', - path: '/demo/start/server-funcs', - getParentRoute: () => rootRouteImport, -} as any) + id: '/demo/start/server-funcs', + path: '/demo/start/server-funcs', + getParentRoute: () => rootRouteImport, +} as any); const DemoStartApiRequestRoute = DemoStartApiRequestRouteImport.update({ - id: '/demo/start/api-request', - path: '/demo/start/api-request', - getParentRoute: () => rootRouteImport, -} as any) + id: '/demo/start/api-request', + path: '/demo/start/api-request', + getParentRoute: () => rootRouteImport, +} as any); const DemoApiNamesRoute = DemoApiNamesRouteImport.update({ - id: '/demo/api/names', - path: '/demo/api/names', - getParentRoute: () => rootRouteImport, -} as any) + id: '/demo/api/names', + path: '/demo/api/names', + getParentRoute: () => rootRouteImport, +} as any); const DemoStartSsrIndexRoute = DemoStartSsrIndexRouteImport.update({ - id: '/demo/start/ssr/', - path: '/demo/start/ssr/', - getParentRoute: () => rootRouteImport, -} as any) + id: '/demo/start/ssr/', + path: '/demo/start/ssr/', + getParentRoute: () => rootRouteImport, +} as any); const DemoStartSsrSpaModeRoute = DemoStartSsrSpaModeRouteImport.update({ - id: '/demo/start/ssr/spa-mode', - path: '/demo/start/ssr/spa-mode', - getParentRoute: () => rootRouteImport, -} as any) + id: '/demo/start/ssr/spa-mode', + path: '/demo/start/ssr/spa-mode', + getParentRoute: () => rootRouteImport, +} as any); const DemoStartSsrFullSsrRoute = DemoStartSsrFullSsrRouteImport.update({ - id: '/demo/start/ssr/full-ssr', - path: '/demo/start/ssr/full-ssr', - getParentRoute: () => rootRouteImport, -} as any) + id: '/demo/start/ssr/full-ssr', + path: '/demo/start/ssr/full-ssr', + getParentRoute: () => rootRouteImport, +} as any); const DemoStartSsrDataOnlyRoute = DemoStartSsrDataOnlyRouteImport.update({ - id: '/demo/start/ssr/data-only', - path: '/demo/start/ssr/data-only', - getParentRoute: () => rootRouteImport, -} as any) + id: '/demo/start/ssr/data-only', + path: '/demo/start/ssr/data-only', + getParentRoute: () => rootRouteImport, +} as any); export interface FileRoutesByFullPath { - '/': typeof IndexRoute - '/demo/api/names': typeof DemoApiNamesRoute - '/demo/start/api-request': typeof DemoStartApiRequestRoute - '/demo/start/server-funcs': typeof DemoStartServerFuncsRoute - '/demo/start/ssr/data-only': typeof DemoStartSsrDataOnlyRoute - '/demo/start/ssr/full-ssr': typeof DemoStartSsrFullSsrRoute - '/demo/start/ssr/spa-mode': typeof DemoStartSsrSpaModeRoute - '/demo/start/ssr/': typeof DemoStartSsrIndexRoute + '/': typeof IndexRoute; + '/demo/api/names': typeof DemoApiNamesRoute; + '/demo/start/api-request': typeof DemoStartApiRequestRoute; + '/demo/start/server-funcs': typeof DemoStartServerFuncsRoute; + '/demo/start/ssr/data-only': typeof DemoStartSsrDataOnlyRoute; + '/demo/start/ssr/full-ssr': typeof DemoStartSsrFullSsrRoute; + '/demo/start/ssr/spa-mode': typeof DemoStartSsrSpaModeRoute; + '/demo/start/ssr/': typeof DemoStartSsrIndexRoute; } export interface FileRoutesByTo { - '/': typeof IndexRoute - '/demo/api/names': typeof DemoApiNamesRoute - '/demo/start/api-request': typeof DemoStartApiRequestRoute - '/demo/start/server-funcs': typeof DemoStartServerFuncsRoute - '/demo/start/ssr/data-only': typeof DemoStartSsrDataOnlyRoute - '/demo/start/ssr/full-ssr': typeof DemoStartSsrFullSsrRoute - '/demo/start/ssr/spa-mode': typeof DemoStartSsrSpaModeRoute - '/demo/start/ssr': typeof DemoStartSsrIndexRoute + '/': typeof IndexRoute; + '/demo/api/names': typeof DemoApiNamesRoute; + '/demo/start/api-request': typeof DemoStartApiRequestRoute; + '/demo/start/server-funcs': typeof DemoStartServerFuncsRoute; + '/demo/start/ssr/data-only': typeof DemoStartSsrDataOnlyRoute; + '/demo/start/ssr/full-ssr': typeof DemoStartSsrFullSsrRoute; + '/demo/start/ssr/spa-mode': typeof DemoStartSsrSpaModeRoute; + '/demo/start/ssr': typeof DemoStartSsrIndexRoute; } export interface FileRoutesById { - __root__: typeof rootRouteImport - '/': typeof IndexRoute - '/demo/api/names': typeof DemoApiNamesRoute - '/demo/start/api-request': typeof DemoStartApiRequestRoute - '/demo/start/server-funcs': typeof DemoStartServerFuncsRoute - '/demo/start/ssr/data-only': typeof DemoStartSsrDataOnlyRoute - '/demo/start/ssr/full-ssr': typeof DemoStartSsrFullSsrRoute - '/demo/start/ssr/spa-mode': typeof DemoStartSsrSpaModeRoute - '/demo/start/ssr/': typeof DemoStartSsrIndexRoute + __root__: typeof rootRouteImport; + '/': typeof IndexRoute; + '/demo/api/names': typeof DemoApiNamesRoute; + '/demo/start/api-request': typeof DemoStartApiRequestRoute; + '/demo/start/server-funcs': typeof DemoStartServerFuncsRoute; + '/demo/start/ssr/data-only': typeof DemoStartSsrDataOnlyRoute; + '/demo/start/ssr/full-ssr': typeof DemoStartSsrFullSsrRoute; + '/demo/start/ssr/spa-mode': typeof DemoStartSsrSpaModeRoute; + '/demo/start/ssr/': typeof DemoStartSsrIndexRoute; } export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: - | '/' - | '/demo/api/names' - | '/demo/start/api-request' - | '/demo/start/server-funcs' - | '/demo/start/ssr/data-only' - | '/demo/start/ssr/full-ssr' - | '/demo/start/ssr/spa-mode' - | '/demo/start/ssr/' - fileRoutesByTo: FileRoutesByTo - to: - | '/' - | '/demo/api/names' - | '/demo/start/api-request' - | '/demo/start/server-funcs' - | '/demo/start/ssr/data-only' - | '/demo/start/ssr/full-ssr' - | '/demo/start/ssr/spa-mode' - | '/demo/start/ssr' - id: - | '__root__' - | '/' - | '/demo/api/names' - | '/demo/start/api-request' - | '/demo/start/server-funcs' - | '/demo/start/ssr/data-only' - | '/demo/start/ssr/full-ssr' - | '/demo/start/ssr/spa-mode' - | '/demo/start/ssr/' - fileRoutesById: FileRoutesById + fileRoutesByFullPath: FileRoutesByFullPath; + fullPaths: + | '/' + | '/demo/api/names' + | '/demo/start/api-request' + | '/demo/start/server-funcs' + | '/demo/start/ssr/data-only' + | '/demo/start/ssr/full-ssr' + | '/demo/start/ssr/spa-mode' + | '/demo/start/ssr/'; + fileRoutesByTo: FileRoutesByTo; + to: + | '/' + | '/demo/api/names' + | '/demo/start/api-request' + | '/demo/start/server-funcs' + | '/demo/start/ssr/data-only' + | '/demo/start/ssr/full-ssr' + | '/demo/start/ssr/spa-mode' + | '/demo/start/ssr'; + id: + | '__root__' + | '/' + | '/demo/api/names' + | '/demo/start/api-request' + | '/demo/start/server-funcs' + | '/demo/start/ssr/data-only' + | '/demo/start/ssr/full-ssr' + | '/demo/start/ssr/spa-mode' + | '/demo/start/ssr/'; + fileRoutesById: FileRoutesById; } export interface RootRouteChildren { - IndexRoute: typeof IndexRoute - DemoApiNamesRoute: typeof DemoApiNamesRoute - DemoStartApiRequestRoute: typeof DemoStartApiRequestRoute - DemoStartServerFuncsRoute: typeof DemoStartServerFuncsRoute - DemoStartSsrDataOnlyRoute: typeof DemoStartSsrDataOnlyRoute - DemoStartSsrFullSsrRoute: typeof DemoStartSsrFullSsrRoute - DemoStartSsrSpaModeRoute: typeof DemoStartSsrSpaModeRoute - DemoStartSsrIndexRoute: typeof DemoStartSsrIndexRoute + IndexRoute: typeof IndexRoute; + DemoApiNamesRoute: typeof DemoApiNamesRoute; + DemoStartApiRequestRoute: typeof DemoStartApiRequestRoute; + DemoStartServerFuncsRoute: typeof DemoStartServerFuncsRoute; + DemoStartSsrDataOnlyRoute: typeof DemoStartSsrDataOnlyRoute; + DemoStartSsrFullSsrRoute: typeof DemoStartSsrFullSsrRoute; + DemoStartSsrSpaModeRoute: typeof DemoStartSsrSpaModeRoute; + DemoStartSsrIndexRoute: typeof DemoStartSsrIndexRoute; } declare module '@tanstack/react-router' { - interface FileRoutesByPath { - '/': { - id: '/' - path: '/' - fullPath: '/' - preLoaderRoute: typeof IndexRouteImport - parentRoute: typeof rootRouteImport - } - '/demo/start/server-funcs': { - id: '/demo/start/server-funcs' - path: '/demo/start/server-funcs' - fullPath: '/demo/start/server-funcs' - preLoaderRoute: typeof DemoStartServerFuncsRouteImport - parentRoute: typeof rootRouteImport - } - '/demo/start/api-request': { - id: '/demo/start/api-request' - path: '/demo/start/api-request' - fullPath: '/demo/start/api-request' - preLoaderRoute: typeof DemoStartApiRequestRouteImport - parentRoute: typeof rootRouteImport - } - '/demo/api/names': { - id: '/demo/api/names' - path: '/demo/api/names' - fullPath: '/demo/api/names' - preLoaderRoute: typeof DemoApiNamesRouteImport - parentRoute: typeof rootRouteImport - } - '/demo/start/ssr/': { - id: '/demo/start/ssr/' - path: '/demo/start/ssr' - fullPath: '/demo/start/ssr/' - preLoaderRoute: typeof DemoStartSsrIndexRouteImport - parentRoute: typeof rootRouteImport - } - '/demo/start/ssr/spa-mode': { - id: '/demo/start/ssr/spa-mode' - path: '/demo/start/ssr/spa-mode' - fullPath: '/demo/start/ssr/spa-mode' - preLoaderRoute: typeof DemoStartSsrSpaModeRouteImport - parentRoute: typeof rootRouteImport - } - '/demo/start/ssr/full-ssr': { - id: '/demo/start/ssr/full-ssr' - path: '/demo/start/ssr/full-ssr' - fullPath: '/demo/start/ssr/full-ssr' - preLoaderRoute: typeof DemoStartSsrFullSsrRouteImport - parentRoute: typeof rootRouteImport - } - '/demo/start/ssr/data-only': { - id: '/demo/start/ssr/data-only' - path: '/demo/start/ssr/data-only' - fullPath: '/demo/start/ssr/data-only' - preLoaderRoute: typeof DemoStartSsrDataOnlyRouteImport - parentRoute: typeof rootRouteImport - } - } + interface FileRoutesByPath { + '/': { + id: '/'; + path: '/'; + fullPath: '/'; + preLoaderRoute: typeof IndexRouteImport; + parentRoute: typeof rootRouteImport; + }; + '/demo/start/server-funcs': { + id: '/demo/start/server-funcs'; + path: '/demo/start/server-funcs'; + fullPath: '/demo/start/server-funcs'; + preLoaderRoute: typeof DemoStartServerFuncsRouteImport; + parentRoute: typeof rootRouteImport; + }; + '/demo/start/api-request': { + id: '/demo/start/api-request'; + path: '/demo/start/api-request'; + fullPath: '/demo/start/api-request'; + preLoaderRoute: typeof DemoStartApiRequestRouteImport; + parentRoute: typeof rootRouteImport; + }; + '/demo/api/names': { + id: '/demo/api/names'; + path: '/demo/api/names'; + fullPath: '/demo/api/names'; + preLoaderRoute: typeof DemoApiNamesRouteImport; + parentRoute: typeof rootRouteImport; + }; + '/demo/start/ssr/': { + id: '/demo/start/ssr/'; + path: '/demo/start/ssr'; + fullPath: '/demo/start/ssr/'; + preLoaderRoute: typeof DemoStartSsrIndexRouteImport; + parentRoute: typeof rootRouteImport; + }; + '/demo/start/ssr/spa-mode': { + id: '/demo/start/ssr/spa-mode'; + path: '/demo/start/ssr/spa-mode'; + fullPath: '/demo/start/ssr/spa-mode'; + preLoaderRoute: typeof DemoStartSsrSpaModeRouteImport; + parentRoute: typeof rootRouteImport; + }; + '/demo/start/ssr/full-ssr': { + id: '/demo/start/ssr/full-ssr'; + path: '/demo/start/ssr/full-ssr'; + fullPath: '/demo/start/ssr/full-ssr'; + preLoaderRoute: typeof DemoStartSsrFullSsrRouteImport; + parentRoute: typeof rootRouteImport; + }; + '/demo/start/ssr/data-only': { + id: '/demo/start/ssr/data-only'; + path: '/demo/start/ssr/data-only'; + fullPath: '/demo/start/ssr/data-only'; + preLoaderRoute: typeof DemoStartSsrDataOnlyRouteImport; + parentRoute: typeof rootRouteImport; + }; + } } const rootRouteChildren: RootRouteChildren = { - IndexRoute: IndexRoute, - DemoApiNamesRoute: DemoApiNamesRoute, - DemoStartApiRequestRoute: DemoStartApiRequestRoute, - DemoStartServerFuncsRoute: DemoStartServerFuncsRoute, - DemoStartSsrDataOnlyRoute: DemoStartSsrDataOnlyRoute, - DemoStartSsrFullSsrRoute: DemoStartSsrFullSsrRoute, - DemoStartSsrSpaModeRoute: DemoStartSsrSpaModeRoute, - DemoStartSsrIndexRoute: DemoStartSsrIndexRoute, -} + IndexRoute: IndexRoute, + DemoApiNamesRoute: DemoApiNamesRoute, + DemoStartApiRequestRoute: DemoStartApiRequestRoute, + DemoStartServerFuncsRoute: DemoStartServerFuncsRoute, + DemoStartSsrDataOnlyRoute: DemoStartSsrDataOnlyRoute, + DemoStartSsrFullSsrRoute: DemoStartSsrFullSsrRoute, + DemoStartSsrSpaModeRoute: DemoStartSsrSpaModeRoute, + DemoStartSsrIndexRoute: DemoStartSsrIndexRoute, +}; export const routeTree = rootRouteImport - ._addFileChildren(rootRouteChildren) - ._addFileTypes() + ._addFileChildren(rootRouteChildren) + ._addFileTypes(); + +import type { createStart } from '@tanstack/react-start'; +import type { getRouter } from './router.tsx'; -import type { getRouter } from './router.tsx' -import type { createStart } from '@tanstack/react-start' declare module '@tanstack/react-start' { - interface Register { - ssr: true - router: Awaited> - } + interface Register { + ssr: true; + router: Awaited>; + } } diff --git a/src/router.tsx b/src/router.tsx index 5c70836..ef44808 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -1,17 +1,17 @@ -import { createRouter } from '@tanstack/react-router' +import { createRouter } from '@tanstack/react-router'; // Import the generated route tree -import { routeTree } from './routeTree.gen' +import { routeTree } from './routeTree.gen'; // Create a new router instance export const getRouter = () => { - const router = createRouter({ - routeTree, - context: {}, + const router = createRouter({ + routeTree, + context: {}, - scrollRestoration: true, - defaultPreloadStaleTime: 0, - }) + scrollRestoration: true, + defaultPreloadStaleTime: 0, + }); - return router -} + return router; +}; diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index b4e94a5..43bff2d 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -1,58 +1,58 @@ -import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router' -import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools' -import { TanStackDevtools } from '@tanstack/react-devtools' +import { TanStackDevtools } from '@tanstack/react-devtools'; +import { createRootRoute, HeadContent, Scripts } from '@tanstack/react-router'; +import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; -import Header from '../components/Header' +import Header from '../components/Header'; -import appCss from '../styles.css?url' +import appCss from '../styles.css?url'; export const Route = createRootRoute({ - head: () => ({ - meta: [ - { - charSet: 'utf-8', - }, - { - name: 'viewport', - content: 'width=device-width, initial-scale=1', - }, - { - title: 'TanStack Start Starter', - }, - ], - links: [ - { - rel: 'stylesheet', - href: appCss, - }, - ], - }), + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + { + title: 'TanStack Start Starter', + }, + ], + links: [ + { + rel: 'stylesheet', + href: appCss, + }, + ], + }), - shellComponent: RootDocument, -}) + shellComponent: RootDocument, +}); function RootDocument({ children }: { children: React.ReactNode }) { - return ( - - - - - -
- {children} - , - }, - ]} - /> - - - - ) + return ( + + + + + +
+ {children} + , + }, + ]} + /> + + + + ); } diff --git a/src/routes/api/health.ts b/src/routes/api/health.ts index 39ab648..cd44a86 100644 --- a/src/routes/api/health.ts +++ b/src/routes/api/health.ts @@ -1,20 +1,20 @@ -import { createAPIFileRoute } from "@tanstack/start/api"; -import { prisma } from "@/lib/server/db"; +import { createAPIFileRoute } from '@tanstack/start/api'; +import { prisma } from '@/lib/server/db'; -export const Route = createAPIFileRoute("/api/health")({ - GET: async () => { - let dbStatus = "disconnected"; - try { - await prisma.$queryRaw`SELECT 1`; - dbStatus = "connected"; - } catch { - dbStatus = "error"; - } +export const Route = createAPIFileRoute('/api/health')({ + GET: async () => { + let dbStatus = 'disconnected'; + try { + await prisma.$queryRaw`SELECT 1`; + dbStatus = 'connected'; + } catch { + dbStatus = 'error'; + } - return Response.json({ - status: "ok", - timestamp: new Date().toISOString(), - database: dbStatus, - }); - }, + return Response.json({ + status: 'ok', + timestamp: new Date().toISOString(), + database: dbStatus, + }); + }, }); diff --git a/src/routes/demo/api.names.ts b/src/routes/demo/api.names.ts index a1e4a35..120a5c6 100644 --- a/src/routes/demo/api.names.ts +++ b/src/routes/demo/api.names.ts @@ -1,10 +1,10 @@ -import { createFileRoute } from '@tanstack/react-router' -import { json } from '@tanstack/react-start' +import { createFileRoute } from '@tanstack/react-router'; +import { json } from '@tanstack/react-start'; export const Route = createFileRoute('/demo/api/names')({ - server: { - handlers: { - GET: () => json(['Alice', 'Bob', 'Charlie']), - }, - }, -}) + server: { + handlers: { + GET: () => json(['Alice', 'Bob', 'Charlie']), + }, + }, +}); diff --git a/src/routes/demo/start.api-request.tsx b/src/routes/demo/start.api-request.tsx index e61b95c..10942c8 100644 --- a/src/routes/demo/start.api-request.tsx +++ b/src/routes/demo/start.api-request.tsx @@ -1,33 +1,34 @@ -import { useEffect, useState } from 'react' - -import { createFileRoute } from '@tanstack/react-router' -import './start.css' +import { createFileRoute } from '@tanstack/react-router'; +import { useEffect, useState } from 'react'; +import './start.css'; function getNames() { - return fetch('/demo/api/names').then((res) => res.json() as Promise) + return fetch('/demo/api/names').then( + (res) => res.json() as Promise, + ); } export const Route = createFileRoute('/demo/start/api-request')({ - component: Home, -}) + component: Home, +}); function Home() { - const [names, setNames] = useState>([]) + const [names, setNames] = useState>([]); - useEffect(() => { - getNames().then(setNames) - }, []) + useEffect(() => { + getNames().then(setNames); + }, []); - return ( -
-
-

Start API Request Demo - Names List

-
    - {names.map((name) => ( -
  • {name}
  • - ))} -
-
-
- ) + return ( +
+
+

Start API Request Demo - Names List

+
    + {names.map((name) => ( +
  • {name}
  • + ))} +
+
+
+ ); } diff --git a/src/routes/demo/start.server-funcs.tsx b/src/routes/demo/start.server-funcs.tsx index 7e30a98..c741928 100644 --- a/src/routes/demo/start.server-funcs.tsx +++ b/src/routes/demo/start.server-funcs.tsx @@ -1,8 +1,8 @@ -import fs from 'node:fs' -import { useCallback, useState } from 'react' -import { createFileRoute, useRouter } from '@tanstack/react-router' -import { createServerFn } from '@tanstack/react-start' -import './start.css' +import fs from 'node:fs'; +import { createFileRoute, useRouter } from '@tanstack/react-router'; +import { createServerFn } from '@tanstack/react-start'; +import { useCallback, useState } from 'react'; +import './start.css'; /* const loggingMiddleware = createMiddleware().server( @@ -16,77 +16,77 @@ const loggedServerFunction = createServerFn({ method: "GET" }).middleware([ ]); */ -const TODOS_FILE = 'todos.json' +const TODOS_FILE = 'todos.json'; async function readTodos() { - return JSON.parse( - await fs.promises.readFile(TODOS_FILE, 'utf-8').catch(() => - JSON.stringify( - [ - { id: 1, name: 'Get groceries' }, - { id: 2, name: 'Buy a new phone' }, - ], - null, - 2, - ), - ), - ) + return JSON.parse( + await fs.promises.readFile(TODOS_FILE, 'utf-8').catch(() => + JSON.stringify( + [ + { id: 1, name: 'Get groceries' }, + { id: 2, name: 'Buy a new phone' }, + ], + null, + 2, + ), + ), + ); } const getTodos = createServerFn({ - method: 'GET', -}).handler(async () => await readTodos()) + method: 'GET', +}).handler(async () => await readTodos()); const addTodo = createServerFn({ method: 'POST' }) - .inputValidator((d: string) => d) - .handler(async ({ data }) => { - const todos = await readTodos() - todos.push({ id: todos.length + 1, name: data }) - await fs.promises.writeFile(TODOS_FILE, JSON.stringify(todos, null, 2)) - return todos - }) + .inputValidator((d: string) => d) + .handler(async ({ data }) => { + const todos = await readTodos(); + todos.push({ id: todos.length + 1, name: data }); + await fs.promises.writeFile(TODOS_FILE, JSON.stringify(todos, null, 2)); + return todos; + }); export const Route = createFileRoute('/demo/start/server-funcs')({ - component: Home, - loader: async () => await getTodos(), -}) + component: Home, + loader: async () => await getTodos(), +}); function Home() { - const router = useRouter() - let todos = Route.useLoaderData() + const router = useRouter(); + let todos = Route.useLoaderData(); - const [todo, setTodo] = useState('') + const [todo, setTodo] = useState(''); - const submitTodo = useCallback(async () => { - todos = await addTodo({ data: todo }) - setTodo('') - router.invalidate() - }, [addTodo, todo]) + const submitTodo = useCallback(async () => { + todos = await addTodo({ data: todo }); + setTodo(''); + router.invalidate(); + }, [addTodo, todo]); - return ( -
-

Start Server Functions - Todo Example

-
    - {todos?.map((t) => ( -
  • {t.name}
  • - ))} -
-
- setTodo(e.target.value)} - onKeyDown={(e) => { - if (e.key === 'Enter') { - submitTodo() - } - }} - placeholder="Enter a new todo..." - /> - -
-
- ) + return ( +
+

Start Server Functions - Todo Example

+
    + {todos?.map((t) => ( +
  • {t.name}
  • + ))} +
+
+ setTodo(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + submitTodo(); + } + }} + placeholder="Enter a new todo..." + /> + +
+
+ ); } diff --git a/src/routes/demo/start.ssr.data-only.tsx b/src/routes/demo/start.ssr.data-only.tsx index 84ec99e..d4089d9 100644 --- a/src/routes/demo/start.ssr.data-only.tsx +++ b/src/routes/demo/start.ssr.data-only.tsx @@ -1,25 +1,25 @@ -import { createFileRoute } from '@tanstack/react-router' -import { getPunkSongs } from '@/data/demo.punk-songs' +import { createFileRoute } from '@tanstack/react-router'; +import { getPunkSongs } from '@/data/demo.punk-songs'; export const Route = createFileRoute('/demo/start/ssr/data-only')({ - ssr: 'data-only', - component: RouteComponent, - loader: async () => await getPunkSongs(), -}) + ssr: 'data-only', + component: RouteComponent, + loader: async () => await getPunkSongs(), +}); function RouteComponent() { - const punkSongs = Route.useLoaderData() + const punkSongs = Route.useLoaderData(); - return ( -
-

Data Only SSR - Punk Songs

-
    - {punkSongs.map((song) => ( -
  • - {song.name} - {song.artist} -
  • - ))} -
-
- ) + return ( +
+

Data Only SSR - Punk Songs

+
    + {punkSongs.map((song) => ( +
  • + {song.name} - {song.artist} +
  • + ))} +
+
+ ); } diff --git a/src/routes/demo/start.ssr.full-ssr.tsx b/src/routes/demo/start.ssr.full-ssr.tsx index 84bd3be..c50fcd1 100644 --- a/src/routes/demo/start.ssr.full-ssr.tsx +++ b/src/routes/demo/start.ssr.full-ssr.tsx @@ -1,24 +1,24 @@ -import { createFileRoute } from '@tanstack/react-router' -import { getPunkSongs } from '@/data/demo.punk-songs' +import { createFileRoute } from '@tanstack/react-router'; +import { getPunkSongs } from '@/data/demo.punk-songs'; export const Route = createFileRoute('/demo/start/ssr/full-ssr')({ - component: RouteComponent, - loader: async () => await getPunkSongs(), -}) + component: RouteComponent, + loader: async () => await getPunkSongs(), +}); function RouteComponent() { - const punkSongs = Route.useLoaderData() + const punkSongs = Route.useLoaderData(); - return ( -
-

Full SSR - Punk Songs

-
    - {punkSongs.map((song) => ( -
  • - {song.name} - {song.artist} -
  • - ))} -
-
- ) + return ( +
+

Full SSR - Punk Songs

+
    + {punkSongs.map((song) => ( +
  • + {song.name} - {song.artist} +
  • + ))} +
+
+ ); } diff --git a/src/routes/demo/start.ssr.index.tsx b/src/routes/demo/start.ssr.index.tsx index 80e2cfd..41cde72 100644 --- a/src/routes/demo/start.ssr.index.tsx +++ b/src/routes/demo/start.ssr.index.tsx @@ -1,24 +1,24 @@ -import { createFileRoute, Link } from '@tanstack/react-router' +import { createFileRoute, Link } from '@tanstack/react-router'; export const Route = createFileRoute('/demo/start/ssr/')({ - component: RouteComponent, -}) + component: RouteComponent, +}); function RouteComponent() { - return ( -
-

SSR Demos

-
    -
  • - SPA Mode -
  • -
  • - Full SSR -
  • -
  • - Data Only -
  • -
-
- ) + return ( +
+

SSR Demos

+
    +
  • + SPA Mode +
  • +
  • + Full SSR +
  • +
  • + Data Only +
  • +
+
+ ); } diff --git a/src/routes/demo/start.ssr.spa-mode.tsx b/src/routes/demo/start.ssr.spa-mode.tsx index d09434b..a81e8fd 100644 --- a/src/routes/demo/start.ssr.spa-mode.tsx +++ b/src/routes/demo/start.ssr.spa-mode.tsx @@ -1,31 +1,31 @@ -import { useEffect, useState } from 'react' -import { createFileRoute } from '@tanstack/react-router' -import { getPunkSongs } from '@/data/demo.punk-songs' +import { createFileRoute } from '@tanstack/react-router'; +import { useEffect, useState } from 'react'; +import { getPunkSongs } from '@/data/demo.punk-songs'; export const Route = createFileRoute('/demo/start/ssr/spa-mode')({ - ssr: false, - component: RouteComponent, -}) + ssr: false, + component: RouteComponent, +}); function RouteComponent() { - const [punkSongs, setPunkSongs] = useState< - Awaited> - >([]) + const [punkSongs, setPunkSongs] = useState< + Awaited> + >([]); - useEffect(() => { - getPunkSongs().then(setPunkSongs) - }, []) + useEffect(() => { + getPunkSongs().then(setPunkSongs); + }, []); - return ( -
-

SPA Mode - Punk Songs

-
    - {punkSongs.map((song) => ( -
  • - {song.name} - {song.artist} -
  • - ))} -
-
- ) + return ( +
+

SPA Mode - Punk Songs

+
    + {punkSongs.map((song) => ( +
  • + {song.name} - {song.artist} +
  • + ))} +
+
+ ); } diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 20aae92..24122e0 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -1,37 +1,37 @@ -import { createFileRoute } from '@tanstack/react-router' -import '../App.css' +import { createFileRoute } from '@tanstack/react-router'; +import '../App.css'; -export const Route = createFileRoute('/')({ component: App }) +export const Route = createFileRoute('/')({ component: App }); function App() { - return ( -
-
- TanStack Logo -

- Edit src/routes/index.tsx and save to reload. -

- - Learn React - - - Learn TanStack - -
-
- ) + return ( +
+
+ TanStack Logo +

+ Edit src/routes/index.tsx and save to reload. +

+ + Learn React + + + Learn TanStack + +
+
+ ); }