UNPKG

create-y3-app

Version:
566 lines (514 loc) 17.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.reactRouterStructure = void 0; const docker_1 = require("../config/docker"); exports.reactRouterStructure = { src: { 'index.ts': '// Barrel file for exports\n', 'App.tsx': `import { RouterProvider } from 'react-router-dom'; import { router } from './routes'; function App() { return <RouterProvider router={router} />; } export default App;`, 'index.css': `@import "tailwindcss"; @import "tw-animate-css";`, 'main.tsx': `import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App.tsx'; import './index.css'; ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <App /> </React.StrictMode>, ); `, 'vite-env.d.ts': '/// <reference types="vite/client" />\n', assets: { fonts: {}, icons: {}, images: {}, }, components: { ui: { 'Button.tsx': `import { cn } from '@/lib/utils'; import { cva, type VariantProps } from 'class-variance-authority'; import { forwardRef } from 'react'; const buttonVariants = cva( 'inline-flex items-center justify-center 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', { 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-9 px-4 py-2', sm: 'h-8 rounded-md px-3 text-xs', lg: 'h-10 rounded-md px-8', icon: 'h-9 w-9', }, }, defaultVariants: { variant: 'default', size: 'default', }, } ); export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {} const Button = forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, ...props }, ref) => { return ( <button className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> ); } ); Button.displayName = 'Button'; export { Button, buttonVariants };`, }, layouts: { 'RootLayout.tsx': `import { Outlet } from 'react-router-dom'; import { Navbar } from '../navigation/Navbar'; import { Footer } from '../navigation/Footer'; export function RootLayout() { return ( <div className="flex min-h-screen flex-col"> <Navbar /> <main className="flex-1"> <Outlet /> </main> <Footer /> </div> ); }`, 'AuthLayout.tsx': `import { Outlet, Navigate } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; export function AuthLayout() { const { isAuthenticated } = useAuth(); // Redirect to login if not authenticated if (!isAuthenticated) { return <Navigate to="/login" replace />; } return <Outlet />; }`, }, navigation: { 'Navbar.tsx': `import { Link } from 'react-router-dom'; import { Button } from '../ui/Button'; import { useAuth } from '@/hooks/useAuth'; export function Navbar() { const { isAuthenticated, logout } = useAuth(); return ( <header className="border-b"> <div className="container mx-auto flex h-16 items-center justify-between px-4"> <Link to="/" className="text-xl font-bold"> AppName </Link> <nav className="flex items-center gap-6"> <Link to="/" className="text-sm font-medium hover:text-primary"> Home </Link> <Link to="/about" className="text-sm font-medium hover:text-primary"> About </Link> <Link to="/dashboard" className="text-sm font-medium hover:text-primary"> Dashboard </Link> {isAuthenticated ? ( <Button onClick={logout} variant="outline"> Logout </Button> ) : ( <div className="flex items-center gap-2"> <Link to="/login"> <Button variant="outline">Login</Button> </Link> <Link to="/register"> <Button>Sign Up</Button> </Link> </div> )} </nav> </div> </header> ); }`, 'Footer.tsx': `export function Footer() { return ( <footer className="border-t py-6"> <div className="container mx-auto px-4 text-center text-sm text-muted-foreground"> © {new Date().getFullYear()} Your Company. All rights reserved. </div> </footer> ); }`, }, }, hooks: { 'useAuth.ts': `import { useState, useEffect, createContext, useContext } from 'react'; interface User { id: string; name: string; email: string; } interface AuthContextType { user: User | null; isAuthenticated: boolean; isLoading: boolean; login: (email: string, password: string) => Promise<void>; register: (name: string, email: string, password: string) => Promise<void>; logout: () => void; } const AuthContext = createContext<AuthContextType | null>(null); export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState<User | null>(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { // Check for existing session const checkAuth = async () => { try { // Example: fetch user data from API or localStorage const storedUser = localStorage.getItem('user'); if (storedUser) { setUser(JSON.parse(storedUser)); } } catch (error) { console.error('Authentication error:', error); } finally { setIsLoading(false); } }; checkAuth(); }, []); const login = async (email: string, password: string) => { setIsLoading(true); try { // Mock login - replace with actual API call const mockUser = { id: '1', name: 'Test User', email }; localStorage.setItem('user', JSON.stringify(mockUser)); setUser(mockUser); } catch (error) { console.error('Login error:', error); throw error; } finally { setIsLoading(false); } }; const register = async (name: string, email: string, password: string) => { setIsLoading(true); try { // Mock registration - replace with actual API call const mockUser = { id: '1', name, email }; localStorage.setItem('user', JSON.stringify(mockUser)); setUser(mockUser); } catch (error) { console.error('Registration error:', error); throw error; } finally { setIsLoading(false); } }; const logout = () => { localStorage.removeItem('user'); setUser(null); }; return ( <AuthContext.Provider value={{ user, isAuthenticated: !!user, isLoading, login, register, logout, }} > {children} </AuthContext.Provider> ); } export function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }`, 'index.ts': '// Barrel file for hooks\nexport * from "./useAuth";\n', }, lib: { 'utils.ts': `import { clsx, type ClassValue } from 'clsx'; import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } export function delay(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); }`, }, pages: { 'HomePage.tsx': `export function HomePage() { return ( <div className="container mx-auto py-12 px-4"> <h1 className="text-4xl font-bold mb-6">Welcome to the App</h1> <p className="text-lg text-muted-foreground"> This is a React application with TypeScript and React Router. </p> </div> ); }`, 'AboutPage.tsx': `export function AboutPage() { return ( <div className="container mx-auto py-12 px-4"> <h1 className="text-4xl font-bold mb-6">About</h1> <p className="text-lg text-muted-foreground"> Learn more about our application and mission. </p> </div> ); }`, 'DashboardPage.tsx': `import { useAuth } from '@/hooks/useAuth'; export function DashboardPage() { const { user } = useAuth(); return ( <div className="container mx-auto py-12 px-4"> <h1 className="text-4xl font-bold mb-6">Dashboard</h1> <p className="text-lg mb-4">Welcome back, {user?.name}!</p> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {/* Dashboard widgets would go here */} <div className="rounded-lg border p-6"> <h2 className="text-xl font-semibold mb-2">Analytics</h2> <p>Your analytics data goes here.</p> </div> <div className="rounded-lg border p-6"> <h2 className="text-xl font-semibold mb-2">Recent Activity</h2> <p>Your recent activity goes here.</p> </div> <div className="rounded-lg border p-6"> <h2 className="text-xl font-semibold mb-2">Tasks</h2> <p>Your upcoming tasks go here.</p> </div> </div> </div> ); }`, auth: { 'LoginPage.tsx': `import { useState } from 'react'; import { useNavigate, Link } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; import { Button } from '@/components/ui/Button'; export function LoginPage() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const { login, isLoading } = useAuth(); const navigate = useNavigate(); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(''); try { await login(email, password); navigate('/dashboard'); } catch (err) { setError('Invalid email or password'); } }; return ( <div className="flex min-h-[calc(100vh-4rem)] items-center justify-center p-4"> <div className="w-full max-w-md rounded-lg border p-8"> <h1 className="text-2xl font-bold text-center mb-6">Login</h1> {error && ( <div className="bg-destructive/10 text-destructive rounded-md p-3 mb-4"> {error} </div> )} <form onSubmit={handleSubmit} className="space-y-4"> <div> <label htmlFor="email" className="block text-sm font-medium mb-1"> Email </label> <input id="email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="w-full rounded-md border p-2 text-sm" required /> </div> <div> <label htmlFor="password" className="block text-sm font-medium mb-1"> Password </label> <input id="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} className="w-full rounded-md border p-2 text-sm" required /> </div> <Button type="submit" className="w-full" disabled={isLoading}> {isLoading ? 'Logging in...' : 'Login'} </Button> </form> <p className="text-center mt-4 text-sm"> Don't have an account?{' '} <Link to="/register" className="text-primary hover:underline"> Sign up </Link> </p> </div> </div> ); }`, 'RegisterPage.tsx': `import { useState } from 'react'; import { useNavigate, Link } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; import { Button } from '@/components/ui/Button'; export function RegisterPage() { const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const { register, isLoading } = useAuth(); const navigate = useNavigate(); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(''); try { await register(name, email, password); navigate('/dashboard'); } catch (err) { setError('Registration failed'); } }; return ( <div className="flex min-h-[calc(100vh-4rem)] items-center justify-center p-4"> <div className="w-full max-w-md rounded-lg border p-8"> <h1 className="text-2xl font-bold text-center mb-6">Create an Account</h1> {error && ( <div className="bg-destructive/10 text-destructive rounded-md p-3 mb-4"> {error} </div> )} <form onSubmit={handleSubmit} className="space-y-4"> <div> <label htmlFor="name" className="block text-sm font-medium mb-1"> Name </label> <input id="name" type="text" value={name} onChange={(e) => setName(e.target.value)} className="w-full rounded-md border p-2 text-sm" required /> </div> <div> <label htmlFor="email" className="block text-sm font-medium mb-1"> Email </label> <input id="email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="w-full rounded-md border p-2 text-sm" required /> </div> <div> <label htmlFor="password" className="block text-sm font-medium mb-1"> Password </label> <input id="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} className="w-full rounded-md border p-2 text-sm" required /> </div> <Button type="submit" className="w-full" disabled={isLoading}> {isLoading ? 'Creating account...' : 'Sign Up'} </Button> </form> <p className="text-center mt-4 text-sm"> Already have an account?{' '} <Link to="/login" className="text-primary hover:underline"> Login </Link> </p> </div> </div> ); }`, }, 'NotFoundPage.tsx': `import { Link } from 'react-router-dom'; import { Button } from '@/components/ui/Button'; export function NotFoundPage() { return ( <div className="flex min-h-[calc(100vh-8rem)] flex-col items-center justify-center p-4 text-center"> <h1 className="text-6xl font-bold mb-4">404</h1> <p className="text-xl mb-8">Page not found</p> <Link to="/"> <Button>Go Home</Button> </Link> </div> ); }`, }, routes: { 'index.ts': `import { createBrowserRouter } from 'react-router-dom'; import { RootLayout } from '@/components/layouts/RootLayout'; import { AuthLayout } from '@/components/layouts/AuthLayout'; import { HomePage } from '@/pages/HomePage'; import { AboutPage } from '@/pages/AboutPage'; import { DashboardPage } from '@/pages/DashboardPage'; import { LoginPage } from '@/pages/auth/LoginPage'; import { RegisterPage } from '@/pages/auth/RegisterPage'; import { NotFoundPage } from '@/pages/NotFoundPage'; export const router = createBrowserRouter([ { path: '/', element: <RootLayout />, children: [ { index: true, element: <HomePage /> }, { path: 'about', element: <AboutPage /> }, { path: '/', element: <AuthLayout />, children: [ { path: 'dashboard', element: <DashboardPage /> }, ], }, { path: 'login', element: <LoginPage /> }, { path: 'register', element: <RegisterPage /> }, { path: '*', element: <NotFoundPage /> }, ], }, ]);`, }, context: { 'AuthContext.tsx': `// This content has been moved to hooks/useAuth.ts`, }, }, ...docker_1.dockerStructure, };