Skip to content

Commit

Permalink
feat: finish temp auth logic that will be replaced later (#35)
Browse files Browse the repository at this point in the history
* feat: install libs and add shadcn components

* feat: finish login and register pages

* feat: finish temp auth logic that will be replaced later

* fix: decrease login and register components width
  • Loading branch information
alikehel authored Oct 5, 2024
1 parent b97b570 commit 4886b90
Show file tree
Hide file tree
Showing 19 changed files with 1,271 additions and 55 deletions.
4 changes: 4 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
"preview": "vite preview"
},
"dependencies": {
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@tanstack/react-form": "^0.33.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/react-query": "^5.56.2",
"@tanstack/react-router": "^1.58.9",
"@tanstack/zod-form-adapter": "^0.33.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"gql.tada": "^1.8.9",
Expand Down
15 changes: 9 additions & 6 deletions apps/web/src/app-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ThemeProvider } from "@/providers/theme-provider";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
// import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import * as React from "react";
import { AuthProvider } from "./providers/auth-provider";
import { ResponsiveProvider } from "./providers/responsive-provider";

type AppProviderProps = {
Expand All @@ -30,12 +31,14 @@ export const AppProvider = ({ children }: AppProviderProps) => {
<QueryClientProvider client={queryClient}>
<ResponsiveProvider>
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
{env.DEV && (
<React.Suspense fallback={null}>
<ReactQueryDevtoolsProduction />
</React.Suspense>
)}
{children}
<AuthProvider>
{env.DEV && (
<React.Suspense fallback={null}>
<ReactQueryDevtoolsProduction />
</React.Suspense>
)}
{children}
</AuthProvider>
</ThemeProvider>
</ResponsiveProvider>
</QueryClientProvider>
Expand Down
7 changes: 6 additions & 1 deletion apps/web/src/app-router.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Link, RouterProvider, createRouter } from "@tanstack/react-router";

// Import the generated route tree
import { useAuth } from "@/providers/auth-provider";
import { routeTree } from "@/routeTree.gen";

// Create a new router instance
Expand All @@ -24,6 +25,9 @@ const router = createRouter({
</Link>
</div>
),
context: {
auth: undefined!, // This will be set after we wrap the app in an AuthProvider
},
});

// Register the router instance for type safety
Expand All @@ -34,5 +38,6 @@ declare module "@tanstack/react-router" {
}

export const AppRouter = () => {
return <RouterProvider router={router} />;
const auth = useAuth();
return <RouterProvider router={router} context={{ auth }} />;
};
57 changes: 57 additions & 0 deletions apps/web/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Slot } from "@radix-ui/react-slot";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";

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

const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button";
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
},
);
Button.displayName = "Button";

export { Button, buttonVariants };
86 changes: 86 additions & 0 deletions apps/web/src/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as React from "react";

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

const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className,
)}
{...props}
/>
));
Card.displayName = "Card";

const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
));
CardHeader.displayName = "CardHeader";

const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
"font-semibold text-2xl leading-none tracking-tight",
className,
)}
{...props}
/>
));
CardTitle.displayName = "CardTitle";

const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
));
CardDescription.displayName = "CardDescription";

const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
));
CardContent.displayName = "CardContent";

const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
));
CardFooter.displayName = "CardFooter";

export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
};
25 changes: 25 additions & 0 deletions apps/web/src/components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from "react";

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

export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:font-medium file:text-foreground file:text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
{...props}
/>
);
},
);
Input.displayName = "Input";

export { Input };
24 changes: 24 additions & 0 deletions apps/web/src/components/ui/label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as LabelPrimitive from "@radix-ui/react-label";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";

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

const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);

const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
));
Label.displayName = LabelPrimitive.Root.displayName;

export { Label };
63 changes: 63 additions & 0 deletions apps/web/src/providers/auth-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as React from "react";

// import { sleep } from "./utils";

export interface AuthContext {
isAuthenticated: boolean;
login: (email: string) => Promise<void>;
logout: () => Promise<void>;
user: string | null;
}

const AuthContext = React.createContext<AuthContext | null>(null);

const key = "tanstack.auth.user";

function getStoredUser() {
return localStorage.getItem(key);
}

function setStoredUser(user: string | null) {
if (user) {
localStorage.setItem(key, user);
} else {
localStorage.removeItem(key);
}
}

export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = React.useState<string | null>(getStoredUser());
const isAuthenticated = !!user;

const logout = React.useCallback(async () => {
// await sleep(250);

setStoredUser(null);
setUser(null);
}, []);

const login = React.useCallback(async (email: string) => {
// await sleep(500);

setStoredUser(email);
setUser(email);
}, []);

React.useEffect(() => {
setUser(getStoredUser());
}, []);

return (
<AuthContext.Provider value={{ isAuthenticated, user, login, logout }}>
{children}
</AuthContext.Provider>
);
}

export function useAuth() {
const context = React.useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}
Loading

0 comments on commit 4886b90

Please sign in to comment.