feat(frontend): bootstrap React + Vite + Tailwind + Router + Layout
This commit is contained in:
3107
package-lock.json
generated
3107
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
packages/frontend/index.html
Normal file
12
packages/frontend/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="nl" class="h-full">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Flashcards</title>
|
||||||
|
</head>
|
||||||
|
<body class="h-full bg-slate-50 text-slate-900 dark:bg-slate-950 dark:text-slate-100">
|
||||||
|
<div id="root" class="h-full"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
37
packages/frontend/package.json
Normal file
37
packages/frontend/package.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "@flashcard/frontend",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc --noEmit && vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"test": "vitest run"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@flashcard/shared": "*",
|
||||||
|
"canvas-confetti": "^1.9.0",
|
||||||
|
"framer-motion": "^11.0.0",
|
||||||
|
"react": "^18.3.0",
|
||||||
|
"react-dom": "^18.3.0",
|
||||||
|
"react-router-dom": "^6.26.0",
|
||||||
|
"zustand": "^4.5.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@testing-library/jest-dom": "^6.5.0",
|
||||||
|
"@testing-library/react": "^16.0.0",
|
||||||
|
"@types/canvas-confetti": "^1.6.0",
|
||||||
|
"@types/react": "^18.3.0",
|
||||||
|
"@types/react-dom": "^18.3.0",
|
||||||
|
"@vitejs/plugin-react": "^4.3.0",
|
||||||
|
"autoprefixer": "^10.4.0",
|
||||||
|
"jsdom": "^25.0.0",
|
||||||
|
"postcss": "^8.4.0",
|
||||||
|
"tailwindcss": "^3.4.0",
|
||||||
|
"typescript": "^5.5.0",
|
||||||
|
"vite": "^7.0.0",
|
||||||
|
"vitest": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
packages/frontend/postcss.config.js
Normal file
1
packages/frontend/postcss.config.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export default { plugins: { tailwindcss: {}, autoprefixer: {} } };
|
||||||
16
packages/frontend/src/components/Layout.tsx
Normal file
16
packages/frontend/src/components/Layout.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
|
export function Layout() {
|
||||||
|
return (
|
||||||
|
<div className="flex h-full flex-col">
|
||||||
|
<header className="border-b border-slate-200 bg-white px-6 py-3 dark:border-slate-800 dark:bg-slate-900">
|
||||||
|
<nav className="flex gap-4 text-sm">
|
||||||
|
<Link to="/" className="font-semibold">Flashcards</Link>
|
||||||
|
<Link to="/admin">Admin</Link>
|
||||||
|
<Link to="/stats">Stats</Link>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main className="flex-1 overflow-auto"><Outlet /></main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
12
packages/frontend/src/main.tsx
Normal file
12
packages/frontend/src/main.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import { RouterProvider } from 'react-router-dom';
|
||||||
|
import { router } from './router.js';
|
||||||
|
import './styles.css';
|
||||||
|
|
||||||
|
const root = createRoot(document.getElementById('root')!);
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<RouterProvider router={router} />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
14
packages/frontend/src/router.tsx
Normal file
14
packages/frontend/src/router.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { createBrowserRouter, Navigate } from 'react-router-dom';
|
||||||
|
import { Layout } from './components/Layout.js';
|
||||||
|
|
||||||
|
export const router = createBrowserRouter([
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
element: <Layout />,
|
||||||
|
children: [
|
||||||
|
{ index: true, element: <div className="p-6">Dashboard placeholder</div> },
|
||||||
|
{ path: 'admin', element: <div className="p-6">Admin placeholder</div> },
|
||||||
|
{ path: '*', element: <Navigate to="/" replace /> },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
7
packages/frontend/src/styles.css
Normal file
7
packages/frontend/src/styles.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
html, body, #root { height: 100%; }
|
||||||
|
.card-perspective { perspective: 1000px; }
|
||||||
|
.card-face { backface-visibility: hidden; }
|
||||||
1
packages/frontend/src/test-setup.ts
Normal file
1
packages/frontend/src/test-setup.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import '@testing-library/jest-dom/vitest';
|
||||||
17
packages/frontend/tailwind.config.ts
Normal file
17
packages/frontend/tailwind.config.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import type { Config } from 'tailwindcss';
|
||||||
|
export default {
|
||||||
|
content: ['./index.html', './src/**/*.{ts,tsx}'],
|
||||||
|
darkMode: 'class',
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
animation: { 'flip': 'flip 0.4s ease-out forwards' },
|
||||||
|
keyframes: {
|
||||||
|
flip: {
|
||||||
|
'0%': { transform: 'rotateY(0)' },
|
||||||
|
'100%': { transform: 'rotateY(180deg)' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
} satisfies Config;
|
||||||
9
packages/frontend/tsconfig.json
Normal file
9
packages/frontend/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
|
"moduleResolution": "Bundler"
|
||||||
|
},
|
||||||
|
"include": ["src/**/*", "index.html"]
|
||||||
|
}
|
||||||
11
packages/frontend/vite.config.ts
Normal file
11
packages/frontend/vite.config.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
proxy: { '/api': 'http://localhost:3000' },
|
||||||
|
},
|
||||||
|
test: { environment: 'jsdom', setupFiles: ['./src/test-setup.ts'] },
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user