Initialize HemHub project foundation
This commit is contained in:
13
frontend/index.html
Normal file
13
frontend/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="sv">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>HemHub</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
27
frontend/package.json
Normal file
27
frontend/package.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "hemhub-frontend",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "19.2.8",
|
||||
"react-dom": "19.2.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "7.0.0",
|
||||
"@testing-library/react": "16.3.2",
|
||||
"@types/react": "19.2.17",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@vitejs/plugin-react": "6.0.4",
|
||||
"jsdom": "29.1.1",
|
||||
"typescript": "7.0.2",
|
||||
"vite": "8.1.5",
|
||||
"vitest": "4.1.10"
|
||||
},
|
||||
"packageManager": "pnpm@11.17.0"
|
||||
}
|
||||
1567
frontend/pnpm-lock.yaml
generated
Normal file
1567
frontend/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
frontend/src/App.test.tsx
Normal file
21
frontend/src/App.test.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { afterEach, expect, test, vi } from 'vitest'
|
||||
import App from './App'
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
test('visar sidans rubrik', () => {
|
||||
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||
new Response(JSON.stringify({ status: 'UP' }), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
}),
|
||||
)
|
||||
|
||||
render(<App />)
|
||||
|
||||
expect(screen.getByRole('heading', { name: 'HemHub' })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
48
frontend/src/App.tsx
Normal file
48
frontend/src/App.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
type HealthResponse = {
|
||||
status: string
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [backendStatus, setBackendStatus] = useState<string | null>(null)
|
||||
const [hasError, setHasError] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const loadHealth = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/health')
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Backend svarade med status ${response.status}`)
|
||||
}
|
||||
|
||||
const health = (await response.json()) as HealthResponse
|
||||
setBackendStatus(health.status)
|
||||
} catch {
|
||||
setHasError(true)
|
||||
}
|
||||
}
|
||||
|
||||
void loadHealth()
|
||||
}, [])
|
||||
|
||||
let statusMessage = 'Kontrollerar backend…'
|
||||
|
||||
if (hasError) {
|
||||
statusMessage = 'Backend kunde inte nås'
|
||||
} else if (backendStatus) {
|
||||
statusMessage = `Backend: ${backendStatus}`
|
||||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1>HemHub</h1>
|
||||
<p>Frontend har startat.</p>
|
||||
<p aria-live="polite">{statusMessage}</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
|
||||
11
frontend/src/main.tsx
Normal file
11
frontend/src/main.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import App from './App'
|
||||
import './styles.css'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
|
||||
23
frontend/src/styles.css
Normal file
23
frontend/src/styles.css
Normal file
@ -0,0 +1,23 @@
|
||||
:root {
|
||||
font-family: system-ui, sans-serif;
|
||||
color: #1f2937;
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 40rem;
|
||||
margin: 6rem auto;
|
||||
padding: 2rem;
|
||||
border-radius: 0.75rem;
|
||||
background: white;
|
||||
box-shadow: 0 0.25rem 1rem rgb(0 0 0 / 8%);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
2
frontend/src/test/setup.ts
Normal file
2
frontend/src/test/setup.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import '@testing-library/jest-dom/vitest'
|
||||
|
||||
1
frontend/src/vite-env.d.ts
vendored
Normal file
1
frontend/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
22
frontend/tsconfig.app.json
Normal file
22
frontend/tsconfig.app.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
"types": ["vitest/globals", "@testing-library/jest-dom"]
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
8
frontend/tsconfig.json
Normal file
8
frontend/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
|
||||
12
frontend/tsconfig.node.json
Normal file
12
frontend/tsconfig.node.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
|
||||
16
frontend/vite.config.ts
Normal file
16
frontend/vite.config.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 5173,
|
||||
proxy: {
|
||||
'/api': 'http://localhost:8080',
|
||||
},
|
||||
},
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
setupFiles: './src/test/setup.ts',
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user