diff --git a/.env.example b/.env.example index 09d7e54..01cc93f 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,9 @@ PORT=3000 HOST=127.0.0.1 ORIGIN=http://localhost:3000 +# Branding +APP_NAME=B4L Budget + # Database DATABASE_URL=postgresql://budget_app:password@localhost:5432/buildfor_life_budget diff --git a/.gitea/workflows/validate.yml b/.gitea/workflows/validate.yml new file mode 100644 index 0000000..18a6754 --- /dev/null +++ b/.gitea/workflows/validate.yml @@ -0,0 +1,26 @@ +name: Validate + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Run validation (svelte-check + build) + run: npm run validate diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..18a6754 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,26 @@ +name: Validate + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Run validation (svelte-check + build) + run: npm run validate diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 0000000..d1dde59 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,2 @@ +echo "Running validation before push (svelte-check + build)..." +npm run validate diff --git a/package-lock.json b/package-lock.json index a53c647..ce23a97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,12 @@ "@node-rs/argon2": "^2.0.2", "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", + "@pdf-lib/fontkit": "^1.1.1", "chart.js": "^4.4.7", "date-fns": "^4.1.0", "drizzle-orm": "^0.38.4", "papaparse": "^5.5.2", + "pdf-lib": "^1.17.1", "pg": "^8.13.1", "zod": "^3.24.2" }, @@ -26,6 +28,7 @@ "@types/papaparse": "^5.3.15", "@types/pg": "^8.11.11", "drizzle-kit": "^0.30.5", + "husky": "^9.1.7", "svelte": "^5.19.0", "svelte-check": "^4.1.4", "tailwindcss": "^4.1.3", @@ -1297,6 +1300,33 @@ "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", "license": "MIT" }, + "node_modules/@pdf-lib/fontkit": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/fontkit/-/fontkit-1.1.1.tgz", + "integrity": "sha512-KjMd7grNapIWS/Dm0gvfHEilSyAmeLvrEGVcqLGi0VYebuqqzTbgF29efCx7tvx+IEbG3zQciRSWl3GkUSvjZg==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/@pdf-lib/standard-fonts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", + "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/@pdf-lib/upng": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.10" + } + }, "node_modules/@petamoriken/float16": { "version": "3.9.3", "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.3.tgz", @@ -2721,6 +2751,22 @@ "node": ">= 0.4" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -3108,6 +3154,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, "node_modules/papaparse": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.3.tgz", @@ -3121,6 +3173,24 @@ "dev": true, "license": "MIT" }, + "node_modules/pdf-lib": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", + "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==", + "license": "MIT", + "dependencies": { + "@pdf-lib/standard-fonts": "^1.0.0", + "@pdf-lib/upng": "^1.0.1", + "pako": "^1.0.11", + "tslib": "^1.11.1" + } + }, + "node_modules/pdf-lib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/pg": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz", diff --git a/package.json b/package.json index 95c4b54..0de8f4e 100644 --- a/package.json +++ b/package.json @@ -7,20 +7,24 @@ "dev": "vite dev", "build": "vite build", "preview": "vite preview", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --threshold warning", + "validate": "npm run check && npm run build", "db:generate": "drizzle-kit generate", "db:migrate": "drizzle-kit migrate", "db:push": "drizzle-kit push", - "db:studio": "drizzle-kit studio" + "db:studio": "drizzle-kit studio", + "prepare": "husky" }, "dependencies": { "@node-rs/argon2": "^2.0.2", "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", + "@pdf-lib/fontkit": "^1.1.1", "chart.js": "^4.4.7", "date-fns": "^4.1.0", "drizzle-orm": "^0.38.4", "papaparse": "^5.5.2", + "pdf-lib": "^1.17.1", "pg": "^8.13.1", "zod": "^3.24.2" }, @@ -29,9 +33,10 @@ "@sveltejs/kit": "^2.15.2", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@tailwindcss/vite": "^4.1.3", - "@types/pg": "^8.11.11", "@types/papaparse": "^5.3.15", + "@types/pg": "^8.11.11", "drizzle-kit": "^0.30.5", + "husky": "^9.1.7", "svelte": "^5.19.0", "svelte-check": "^4.1.4", "tailwindcss": "^4.1.3", diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte index c977fbc..d9db9bf 100644 --- a/src/lib/components/layout/Sidebar.svelte +++ b/src/lib/components/layout/Sidebar.svelte @@ -3,12 +3,13 @@ interface Props { user: { id: string; email: string; displayName: string | null; isSystemAdmin: boolean }; - companies: Array<{ companyId: string; companyName: string; role: CompanyRole }>; + companies: Array<{ companyId: string; companyName: string; roles: CompanyRole[] }>; + appName: string; open: boolean; onToggle: () => void; } - let { user, companies, open, onToggle }: Props = $props(); + let { user, companies, appName, open, onToggle }: Props = $props();