diff --git a/docs/project-structure.md b/docs/project-structure.md index e13eb28..cc89566 100644 --- a/docs/project-structure.md +++ b/docs/project-structure.md @@ -42,23 +42,18 @@ Next.js 15 App Router structure: ### Reusable Components (`src/components/`) #### shadcn/ui Components (`src/components/ui/`) +Only the primitives the app actually renders are vendored in. Add others with +the shadcn CLI when a screen needs them, rather than keeping unused ones around. + - `alert.jsx` - Alert notifications -- `avatar.jsx` - User avatars - `badge.jsx` - Badge components - `button.jsx` - Button variants - `card.jsx` - Card layouts - `dialog.jsx` - Modal dialogs -- `form.jsx` - Form components - `input.jsx` - Input fields - `label.jsx` - Form labels -- `popover.jsx` - Popover components -- `progress.jsx` - Progress indicators -- `separator.jsx` - Visual separators -- `sheet.jsx` - Side sheets - `skeleton.jsx` - Loading skeletons -- `table.jsx` - Data tables - `tabs.jsx` - Tab navigation -- `tooltip.jsx` - Tooltips ### Utility Libraries (`src/lib/`) - `utils.js` - Utility functions including `cn()` for class name merging diff --git a/docs/tech-stack.md b/docs/tech-stack.md index e260ba0..370844c 100644 --- a/docs/tech-stack.md +++ b/docs/tech-stack.md @@ -35,10 +35,10 @@ - **class-variance-authority**: Component variant management - **tailwind-merge + clsx**: Dynamic class name handling -## Form Handling & Validation -- **react-hook-form**: Form state management -- **@hookform/resolvers**: Form validation resolvers -- **zod**: Schema validation +## Testing +- **Vitest**: Test runner for the logic in `src/lib/` +- **In-memory Upstash fake**: Default backing store, no service required +- **SRH + Redis (Docker)**: Optional lane running the same tests against real Redis ## Development & Analytics - **ESLint**: Code linting with Next.js configuration diff --git a/public/file.svg b/public/file.svg deleted file mode 100644 index 004145c..0000000 --- a/public/file.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg deleted file mode 100644 index 567f17b..0000000 --- a/public/globe.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index 7705396..0000000 --- a/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/window.svg b/public/window.svg deleted file mode 100644 index b2b2a44..0000000 --- a/public/window.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/components/GameClient.js b/src/app/components/GameClient.js index f0d3a80..5ae8c95 100644 --- a/src/app/components/GameClient.js +++ b/src/app/components/GameClient.js @@ -21,8 +21,7 @@ import { cityNames, formatDistance, getUsername, - getResultMessage, - getAccumulatedScoreMessage + getResultMessage } from '../../lib/game'; export default function GameClient() { diff --git a/src/components/ui/avatar.jsx b/src/components/ui/avatar.jsx deleted file mode 100644 index 417ebdf..0000000 --- a/src/components/ui/avatar.jsx +++ /dev/null @@ -1,47 +0,0 @@ -"use client" - -import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" - -import { cn } from "@/lib/utils" - -function Avatar({ - className, - ...props -}) { - return ( - - ); -} - -function AvatarImage({ - className, - ...props -}) { - return ( - - ); -} - -function AvatarFallback({ - className, - ...props -}) { - return ( - - ); -} - -export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/components/ui/form.jsx b/src/components/ui/form.jsx deleted file mode 100644 index 728ea87..0000000 --- a/src/components/ui/form.jsx +++ /dev/null @@ -1,144 +0,0 @@ -"use client"; -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { Controller, FormProvider, useFormContext, useFormState } from "react-hook-form"; - -import { cn } from "@/lib/utils" -import { Label } from "@/components/ui/label" - -const Form = FormProvider - -const FormFieldContext = React.createContext({}) - -const FormField = ( - { - ...props - } -) => { - return ( - - - - ); -} - -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext) - const itemContext = React.useContext(FormItemContext) - const { getFieldState } = useFormContext() - const formState = useFormState({ name: fieldContext.name }) - const fieldState = getFieldState(fieldContext.name, formState) - - if (!fieldContext) { - throw new Error("useFormField should be used within ") - } - - const { id } = itemContext - - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - } -} - -const FormItemContext = React.createContext({}) - -function FormItem({ - className, - ...props -}) { - const id = React.useId() - - return ( - -
- - ); -} - -function FormLabel({ - className, - ...props -}) { - const { error, formItemId } = useFormField() - - return ( -