Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5,804 changes: 0 additions & 5,804 deletions frontend/package-lock.json

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@hookform/resolvers": "^4.1.0",
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-alert-dialog": "^1.1.6",
"@radix-ui/react-avatar": "^1.1.3",
Expand All @@ -23,6 +24,7 @@
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.1.8",
"axios": "^1.7.9",
"class-variance-authority": "^0.7.1",
Expand All @@ -36,11 +38,13 @@
"react-day-picker": "^8.10.1",
"react-dom": "^18.3.1",
"react-hot-toast": "^2.4.1",
"react-icons": "^5.4.0",
"react-router-dom": "^6.22.2",
"recharts": "^2.15.1",
"sonner": "^1.7.4",
"tailwind-merge": "^3.0.1",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"zod": "^3.24.2"
},
"devDependencies": {
"@eslint/js": "^9.9.1",
Expand Down
46 changes: 4 additions & 42 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { AuthProvider } from "./hooks/UseAuth";
import { AppRoutes } from "./routes/Index";
import { Toaster } from "@/components/ui/sonner";
import Navbar from "./components/Navbar";
import RequireAuth from "./components/RequireAuth";
Expand All @@ -14,47 +15,8 @@ function App() {
return (
<AuthProvider>
<BrowserRouter>
<div className="min-h-screen bg-gray-50">
<Navbar />
<main className="container mx-auto px-4 py-8">
<Routes>
<Route path="/signin" element={<SignIn />} />
<Route
path="/"
element={
<RequireAuth>
<Home />
</RequireAuth>
}
/>
<Route
path="/dashboard"
element={
<RequireAuth>
<Dashboard />
</RequireAuth>
}
/>
<Route
path="/polls/:id"
element={
<RequireAuth>
<PollDetails />
</RequireAuth>
}
/>
<Route
path="/create-poll"
element={
<RequireAuth requireAdmin>
<CreatePoll />
</RequireAuth>
}
/>
</Routes>
</main>
<Toaster position="top-right" />
</div>
<AppRoutes />
<Toaster position="top-right" />
</BrowserRouter>
</AuthProvider>
);
Expand Down
15 changes: 4 additions & 11 deletions frontend/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import { Link } from "react-router-dom";
import { Vote } from "lucide-react";
import { NavUser } from "@/components/NavUser";
import { Vote, LogOut, LogIn } from "lucide-react";
import { useAuth } from "@/hooks/UseAuth";
import { Button } from "./ui/button";

export default function Navbar() {
const user = {
firstName: "John",
lastName: "Doe",
avatar: "https://randomuser.me/api/portraits",
email: "John@bsospace.com",
id: "1",
createdAt: new Date(),
updatedAt: new Date(),
};
const { user } = useAuth();
const appName = import.meta.env.VITE_APP_NAME;

return (
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/RequireAuth.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Navigate, useLocation } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
import { useAuth } from "@/hooks/UseAuth";
import { SkeletonCard } from "./Skeleton";

interface RequireAuthProps {
Expand All @@ -11,18 +11,18 @@ export default function RequireAuth({
children,
requireAdmin = false,
}: RequireAuthProps) {
const { user, isAdmin, loading } = useAuth();
const { user, isLoading, isAuthenticated } = useAuth();
const location = useLocation();

if (loading) {
if (isLoading) {
return <SkeletonCard />;
}

if (!user) {
return <Navigate to="/signin" state={{ from: location }} replace />;
return <Navigate to="/login" state={{ from: location }} replace />;
}

if (requireAdmin && !isAdmin) {
if (requireAdmin && !isAuthenticated) {
return <Navigate to="/" replace />;
}

Expand Down
38 changes: 38 additions & 0 deletions frontend/src/components/animata/card/flip-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FC, ReactNode } from "react";
import { cn } from "@/lib/Utils";

interface FlipCardProps extends React.HTMLAttributes<HTMLDivElement> {
flip?: boolean; // ควบคุมการ Flip
frontContent: ReactNode;
backContent: ReactNode;
}

const FlipCard: FC<FlipCardProps> = ({ flip = false, frontContent, backContent, className, ...props }) => {
return (
<div className={cn("group h-96 w-72 [perspective:1000px]", className)} {...props}>
<div
className={cn(
"relative h-full rounded-2xl transition-all duration-500 [transform-style:preserve-3d]",
flip ? "[transform:rotateY(180deg)]" : ""
)}
>
{/* Front - Google Auth */}
<div className="absolute h-full w-full rounded-2xl bg-white shadow-lg flex flex-col items-center justify-center [backface-visibility:hidden]">
{frontContent}
</div>

{/* Back - Guest Auth */}
<div
className={cn(
"absolute h-full w-full rounded-2xl bg-gray-900 text-white shadow-lg flex flex-col items-center justify-center [backface-visibility:hidden]",
"[transform:rotateY(180deg)]"
)}
>
{backContent}
</div>
</div>
</div>
);
};

export default FlipCard;
15 changes: 15 additions & 0 deletions frontend/src/components/layouts/AuthLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ReactNode } from "react";

interface AuthLayoutProps {
children: ReactNode;
}

export function AuthLayout({ children }: AuthLayoutProps) {
return (
<div className="h-screen flex items-center justify-center bg-gray-100 shadow-md">
<div className="w-full max-w-md p-6 rounded-lg">
{children}
</div>
</div>
);
}
15 changes: 15 additions & 0 deletions frontend/src/components/layouts/PageLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Navbar from "@/components/Navbar";

interface PageLayoutProps {
children: React.ReactNode;
}
export function PageLayout({ children }: PageLayoutProps) {
// const [breadcrumbs] = useBreadcrumb();

return (
<>
<Navbar />
<div className="container mx-auto px-4 py-8">{children}</div>
</>
);
}
2 changes: 1 addition & 1 deletion frontend/src/components/ui/alert-dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react"
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"
import { buttonVariants } from "@/components/ui/button"

const AlertDialog = AlertDialogPrimitive.Root
Expand Down
59 changes: 59 additions & 0 deletions frontend/src/components/ui/alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/Utils"

const alertVariants = cva(
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
{
variants: {
variant: {
default: "bg-background text-foreground",
destructive:
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
},
},
defaultVariants: {
variant: "default",
},
}
)

const Alert = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
>(({ className, variant, ...props }, ref) => (
<div
ref={ref}
role="alert"
className={cn(alertVariants({ variant }), className)}
{...props}
/>
))
Alert.displayName = "Alert"

const AlertTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h5
ref={ref}
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
{...props}
/>
))
AlertTitle.displayName = "AlertTitle"

const AlertDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("text-sm [&_p]:leading-relaxed", className)}
{...props}
/>
))
AlertDescription.displayName = "AlertDescription"

export { Alert, AlertTitle, AlertDescription }
2 changes: 1 addition & 1 deletion frontend/src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

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-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react"
import { ChevronLeft, ChevronRight } from "lucide-react"
import { DayPicker } from "react-day-picker"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"
import { buttonVariants } from "@/components/ui/button"

export type CalendarProps = React.ComponentProps<typeof DayPicker>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from "react"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const Card = React.forwardRef<
HTMLDivElement,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/chart.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react"
import * as RechartsPrimitive from "recharts"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

// Format: { THEME_NAME: CSS_SELECTOR }
const THEMES = { light: "", dark: ".dark" } as const
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/datetime-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react";
import { CalendarIcon } from "@radix-ui/react-icons";
import { format } from "date-fns";

import { cn } from "@/lib/utils";
import { cn } from "@/lib/Utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/dropdown-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import { Check, ChevronRight, Circle } from "lucide-react"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const DropdownMenu = DropdownMenuPrimitive.Root

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from "react"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/popover.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const Popover = PopoverPrimitive.Root

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/progress.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/scroll-area.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ui/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react"
import * as SelectPrimitive from "@radix-ui/react-select"
import { Check, ChevronDown, ChevronUp } from "lucide-react"

import { cn } from "@/lib/utils"
import { cn } from "@/lib/Utils"

const Select = SelectPrimitive.Root

Expand Down
Loading