completely re-initialize Vite/React configuration to dummy

This commit is contained in:
2024-11-10 14:02:47 -06:00
parent 01081ee834
commit 69c83edd3a
19 changed files with 961 additions and 1371 deletions

30
frontend/.gitignore vendored
View File

@@ -1,6 +1,24 @@
.eslintcache
.pnpm-debug.log
node_modules/
coverage/
dist/
tsconfig.tsbuildinfo
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -4,10 +4,10 @@
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.cjs",
"css": "src/App.css",
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "zinc",
"cssVariables": false,
"cssVariables": true,
"prefix": ""
},
"aliases": {

28
frontend/eslint.config.js Normal file
View File

@@ -0,0 +1,28 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
)

View File

@@ -1,16 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#fff" />
<title>App</title>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root" class="min-w-full min-h-screen"></div>
<script src="/src/index.tsx" type="module"></script>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -1,14 +1,20 @@
{
"name": "linkpulse",
"private": true,
"version": "0.3.0",
"author": "Xevion <xevion@xevion.dev>",
"author": {
"name": "Xevion",
"url": "https://xevion.dev",
"email": "xevion@xevion.dev"
},
"type": "module",
"engines": {
"node": ">=22.0.0",
"pnpm": ">=9.0.0"
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@radix-ui/react-slot": "^1.1.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.456.0",
@@ -18,46 +24,21 @@
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@swc/core": "^1.6.5",
"@eslint/js": "^9.13.0",
"@types/node": "^22.9.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.19",
"eslint": "^9",
"npm-run-all2": "^6.2.0",
"postcss": "^8.4.38",
"prettier": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.6.5",
"tailwindcss": "^3.4.4",
"ts-node": "^10.9.2",
"typescript": "^5.5.2",
"vite": "^5.3.1",
"vitest": "^1.6.0"
},
"scripts": {
"preinstall": "command -v git >/dev/null 2>&1 && git config core.hooksPath git-hooks || true",
"build": "vite build",
"dev:update-deps": "rm -rf pnpm-lock.yaml node_modules/ **/node_modules && pnpm install",
"dev": "vite dev",
"format": "prettier --write .",
"lint:format": "prettier --cache --check .",
"lint": "eslint --cache .",
"test": "npm-run-all --parallel tsc:check vitest:run lint lint:format",
"tsc:check": "tsc",
"vitest:run": "vitest run"
},
"browserslist": [
">0.2%",
"not dead",
"not op_mini all"
],
"pnpm": {
"updateConfig": {
"ignoreDependencies": [
"eslint"
]
}
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.11.0",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.14",
"typescript": "~5.6.2",
"typescript-eslint": "^8.11.0",
"vite": "^5.4.10",
"vitest": "^2.1.4"
}
}

1670
frontend/pnpm-lock.yaml generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
module.exports = {
export default {
plugins: {
autoprefixer: {},
tailwindcss: {},
autoprefixer: {},
},
};
}

View File

@@ -1,26 +1,42 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--background-color: #fff;
--text-color: #111;
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: dark) {
:root {
--background-color: rgb(20, 20, 20);
--text-color: rgb(230, 230, 230);
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
body {
background-color: var(--background-color);
color: var(--text-color);
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
@layer base {
:root {
--radius: 0.5rem;
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}

View File

@@ -1,91 +1,33 @@
import { useEffect, useState } from 'react';
import { useState } from "react";
import "./App.css";
const backendUrl = import.meta.env.PROD
? '/api'
: `http://${import.meta.env.VITE_BACKEND_TARGET}/api`;
const Code = (props: JSX.IntrinsicElements['code']) => (
<code
className="border-1 2py-1 mx-1 rounded border border-pink-500 bg-neutral-100 px-1 font-mono font-light text-pink-500 dark:border-pink-400 dark:bg-neutral-700 dark:text-pink-400"
{...props}
/>
);
type SeenIP = {
last_seen: string;
ip: string;
count: number;
};
export default function App() {
const [seenIps, setSeenIps] = useState<SeenIP[]>([]);
const [error, setError] = useState<string | null>(null);
const refreshData = async () => {
try {
const response = await fetch(`${backendUrl}/ips`);
if (!response.ok) {
throw new Error(`Error: ${response.statusText}`);
}
const data = await response.json();
setSeenIps(data.ips);
setError(null); // Clear any previous errors
console.log('Data fetched:', data);
} catch (error) {
console.error('Error fetching data:', error);
setError(error.message);
}
};
// Refresh data on component mount and every 30 seconds
useEffect(() => {
refreshData();
const interval = setInterval(
() => {
refreshData();
},
(import.meta.env.DEV ? 3 : 30) * 1000,
);
return () => clearInterval(interval);
}, []);
function App() {
const [count, setCount] = useState(0);
return (
<div className="min-h-full min-w-full">
<div className="mx-auto my-8 mt-10 w-8/12 max-w-md rounded border border-gray-200 p-4 shadow-md dark:border-neutral-600 dark:bg-neutral-800 dark:shadow-none">
<h1 className="mb-4 text-3xl">LinkPulse</h1>
{error && (
<div className="mb-4 rounded border border-red-500 bg-red-100 p-2 text-red-700 dark:border-red-800/50 dark:bg-red-950/50 dark:text-red-400">
{error}
</div>
)}
<div className="relative overflow-x-auto">
<table className="w-full text-left text-sm text-gray-500 rtl:text-right dark:text-gray-300">
<tbody>
{error == null
? seenIps.map((ip) => (
<tr
key={ip.ip}
className="border-b bg-white last:border-0 dark:border-neutral-700 dark:bg-neutral-800"
>
<td className="py-4">
<Code>{ip.ip}</Code>
</td>
<td className="py-4">
{ip.count} time{ip.count > 1 ? 's' : ''}
</td>
<td className="py-4">{ip.last_seen}</td>
</tr>
))
: null}
</tbody>
</table>
</div>
<>
<div>
<a href="https://vite.dev" target="_blank">
<img className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
);
}
export default App;

137
frontend/src/index.css Normal file
View File

@@ -0,0 +1,137 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 10% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

View File

@@ -1,10 +0,0 @@
import App from './App.tsx';
import './App.css';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
);

10
frontend/src/main.tsx Normal file
View File

@@ -0,0 +1,10 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)

1
frontend/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -1,20 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}', './*.html'],
darkMode: ['media', 'class'],
mode: 'jit',
theme: {
extend: {
fontFamily: {
inter: ['Inter', 'sans-serif']
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
},
colors: {}
}
},
plugins: [require("tailwindcss-animate")]
};

View File

@@ -0,0 +1,57 @@
/** @type {import('tailwindcss').Config} */
export default {
darkMode: ["class"],
content: ["./index.html", "./src/**/*.{ts,tsx,js,jsx}"],
theme: {
extend: {
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
},
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))'
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))'
},
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))'
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))'
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))'
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))'
},
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
chart: {
'1': 'hsl(var(--chart-1))',
'2': 'hsl(var(--chart-2))',
'3': 'hsl(var(--chart-3))',
'4': 'hsl(var(--chart-4))',
'5': 'hsl(var(--chart-5))'
}
}
}
},
plugins: [require("tailwindcss-animate")],
};

View File

@@ -0,0 +1,30 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src"]
}

View File

@@ -1,37 +1,13 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"allowJs": true,
"allowImportingTsExtensions": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"incremental": true,
"isolatedModules": true,
"jsx": "preserve",
"lib": ["dom", "dom.iterable", "esnext"],
"module": "nodenext",
"moduleResolution": "nodenext",
"noEmit": true,
"noImplicitOverride": true,
"noUnusedLocals": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "es2017",
"types": ["vite/client"],
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules"],
"include": ["**/*.ts", "**/*.tsx"],
"ts-node": {
"transpileOnly": true,
"transpiler": "ts-node/transpilers/swc",
"files": true,
"compilerOptions": {
"module": "esnext",
"isolatedModules": false
}
}
}

View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["vite.config.ts"]
}

View File

@@ -1,12 +1,13 @@
import path from 'path';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
import path from 'path'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
"@": path.resolve(__dirname, "./src"),
},
},
});
})