Skip to content

Commit 6bbabec

Browse files
authored
Merge pull request #82 from cevi/dev
Updated node version from 15 to 24
2 parents 2384cf0 + 7254f68 commit 6bbabec

70 files changed

Lines changed: 3243 additions & 13838 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
{
22
"permissions": {
33
"allow": [
4+
"Bash(where:*)",
5+
"Bash(npx yarn:*)",
6+
"Bash(yarn install:*)",
7+
"Bash(npx vite build:*)",
8+
"Bash(yarn audit:*)"
49
"Bash(npm ls:*)",
510
"Bash(node --version:*)",
611
"Bash(npm:*)"

.env.example

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
REACT_APP_FIREBASE_API_KEY=
2-
REACT_APP_FIREBASE_AUTH_DOMAIN=
3-
REACT_APP_FIREBASE_PROJECT_ID=
4-
REACT_APP_FIREBASE_STORAGE_BUCKET=
5-
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=
6-
REACT_APP_FIREBASE_APP_ID=
7-
REACT_APP_SENTRY_DNS=
8-
REACT_APP_AUTH0_DOMAIN=
9-
REACT_APP_AUTH0_CLIENT_ID=
10-
REACT_APP_DEV_ENV=true
1+
VITE_FIREBASE_API_KEY=
2+
VITE_FIREBASE_AUTH_DOMAIN=
3+
VITE_FIREBASE_PROJECT_ID=
4+
VITE_FIREBASE_STORAGE_BUCKET=
5+
VITE_FIREBASE_MESSAGING_SENDER_ID=
6+
VITE_FIREBASE_APP_ID=
7+
VITE_SENTRY_DNS=
8+
VITE_AUTH0_DOMAIN=
9+
VITE_AUTH0_CLIENT_ID=
10+
VITE_DEV_ENV=true

.github/workflows/deployDev.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,22 @@ on:
88
jobs:
99
build_docker_container:
1010
runs-on: ubuntu-latest
11-
environment:
11+
environment:
1212
name: dev
1313
url: https://dev-onlinemat.cevi.tools
1414
steps:
1515

16-
# Checkout the source code
1716
- name: 🛎️ Checkout
18-
uses: actions/checkout@v2
19-
20-
# Restores the cache if it exists.
21-
- name: ⛏ Restore docker image from cache
22-
uses: satackey/action-docker-layer-caching@v0.0.11
23-
continue-on-error: true
17+
uses: actions/checkout@v4
2418

2519
- name: 🔐 Login to private Registry (registry.cevi.tools)
26-
uses: docker/login-action@v2
20+
uses: docker/login-action@v3
2721
with:
2822
registry: registry.cevi.tools
2923
username: ${{ secrets.DOCKERHUB_USERNAME }}
3024
password: ${{ secrets.DOCKERHUB_TOKEN }}
3125

32-
- name: Load .evn file from secrets
26+
- name: Load .env file from secrets
3327
run: echo "${{ secrets.ENV_FILE }}" > .env
3428

3529
- name: Set gitInfo file

.github/workflows/deployMaster.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,22 @@ on:
88
jobs:
99
build_docker_container:
1010
runs-on: ubuntu-latest
11-
environment:
11+
environment:
1212
name: production
1313
url: https://mat.cevi.tools
1414
steps:
1515

16-
# Checkout the source code
1716
- name: 🛎️ Checkout
18-
uses: actions/checkout@v2
19-
20-
# Restores the cache if it exists.
21-
- name: ⛏ Restore docker image from cache
22-
uses: satackey/action-docker-layer-caching@v0.0.11
23-
continue-on-error: true
17+
uses: actions/checkout@v4
2418

2519
- name: 🔐 Login to private Registry (registry.cevi.tools)
26-
uses: docker/login-action@v2
20+
uses: docker/login-action@v3
2721
with:
2822
registry: registry.cevi.tools
2923
username: ${{ secrets.DOCKERHUB_USERNAME }}
3024
password: ${{ secrets.DOCKERHUB_TOKEN }}
3125

32-
- name: Load .evn file from secrets
26+
- name: Load .env file from secrets
3327
run: echo "${{ secrets.ENV_FILE }}" > .env
3428

3529
- name: Set gitInfo file

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
24

CLAUDE.md

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,65 @@ Onlinemat is a material/equipment lending management system for Cevi (Swiss yout
99
## Development Commands
1010

1111
```bash
12-
# Prerequisites: Node.js 15.14.0 via nvm, yarn installed globally
13-
nvm use 15.14.0
12+
# Prerequisites: Node.js 24 LTS via nvm, yarn installed globally
13+
nvm use 24
1414

1515
# Install dependencies
1616
yarn
1717

1818
# Start dev server (http://localhost:3000)
19-
yarn start
19+
yarn dev
2020

2121
# Production build
2222
yarn build
2323

24+
# Preview production build
25+
yarn preview
26+
2427
# Run tests
2528
yarn test
26-
27-
# Serve production build locally
28-
yarn serve
2929
```
3030

31-
A `.env` file is required (copy `.env.example` and fill in secrets). Environment variables configure Firebase, Auth0, and Sentry.
31+
A `.env` file is required (copy `.env.example` and fill in secrets). Environment variables use the `VITE_` prefix (e.g. `VITE_FIREBASE_API_KEY`).
3232

3333
## Tech Stack
3434

35-
- **React 17** with TypeScript, bootstrapped with Create React App (react-scripts 4.0.3)
36-
- **Ant Design (antd)** for UI components
37-
- **Firebase** (Firestore) as the backend/database — all domain data flows through real-time Firestore listeners (`onSnapshot`)
38-
- **Auth0** for authentication, which issues a custom Firebase token for Firestore access
35+
- **React 18** with TypeScript 5, built with **Vite**
36+
- **Ant Design (antd) 5** for UI components (CSS-in-JS, no global CSS import)
37+
- **Firebase 10** (modular API) as the backend — all domain data flows through real-time Firestore listeners (`onSnapshot`)
38+
- **Auth0** (`@auth0/auth0-react` v2) for authentication, which issues a custom Firebase token for Firestore access
3939
- **Redux** (with redux-actions/redux-thunk) — used only for user authentication state, not for domain data
4040
- **CASL** for attribute-based access control (permissions)
41+
- **dayjs** for date handling (with `de-ch` locale, `isSameOrBefore` and `localizedFormat` plugins)
4142
- **react-cookie** for cart persistence
42-
- **Sentry** for error tracking
43+
- **Sentry** v8 for error tracking
4344
- **SCSS modules** for styling
4445

4546
## Architecture
4647

4748
### Import Paths
4849

49-
`tsconfig.json` sets `baseUrl: "src"`, so imports are absolute from `src/` (e.g., `import { ability } from "config/casl/ability"`).
50+
`tsconfig.json` sets `baseUrl: "src"`, so imports are absolute from `src/` (e.g., `import { ability } from "config/casl/ability"`). Vite resolves these via `vite-tsconfig-paths`.
5051

5152
### Authentication Flow
5253

53-
Auth0 handles user login → issues a custom Firebase token (stored at `user["https://mat.cevi.tools/firebase_token"]`) → `App.tsx` calls `auth().signInWithCustomToken(token)` → Firebase auth state change triggers a Firestore listener on the user document → Redux store and CASL ability rules are updated.
54+
Auth0 handles user login → issues a custom Firebase token (stored at `user["https://mat.cevi.tools/firebase_token"]`) → `App.tsx` calls `signInWithCustomToken(auth, token)` → Firebase auth state change triggers a Firestore listener on the user document → Redux store and CASL ability rules are updated.
5455

5556
### Data Flow Pattern
5657

5758
Domain data (materials, orders, categories, etc.) does NOT go through Redux. Instead, `AbteilungDetails` component sets up real-time Firestore `onSnapshot` listeners and distributes data via React Contexts:
5859
- `AbteilungenContext` (from `NavigationMenu`) — list of all departments
5960
- `MembersContext`, `CategorysContext`, `MaterialsContext`, `StandorteContext`, `MembersUserDataContext` (from `AbteilungDetails`) — per-department data
6061

62+
### Firebase Modular API
63+
64+
All Firebase calls use the modular (tree-shakeable) API:
65+
```ts
66+
import { collection, doc, onSnapshot, updateDoc, deleteDoc } from 'firebase/firestore'
67+
import { db } from 'config/firebase/firebase'
68+
```
69+
Collection path constants are in `src/config/firebase/collections.ts`.
70+
6171
### Permission Model (CASL)
6272

6373
Two-tier access control defined in `util/UserPermission.ts`:
@@ -66,22 +76,12 @@ Two-tier access control defined in `util/UserPermission.ts`:
6676

6777
Roles (from most to least privileged): `admin``matchef` (material chief) → `member``guest``pending`
6878

69-
Components use `<Can I='action' this={{ __caslSubjectType__: 'Type', abteilungId }}>` to conditionally render based on permissions. Domain types include a `__caslSubjectType__` field for CASL subject detection.
70-
71-
### Firestore Collections
72-
73-
Collection paths are defined as constants in `src/config/firebase/collections.ts`. Top-level collections are `abteilungen` and `users`. Sub-collections under each abteilung: `materials`, `categories`, `members`, `orders`, `standorte`.
79+
Components use `<Can I='action' this={{ __caslSubjectType__: 'Type', abteilungId }}>` to conditionally render based on permissions.
7480

7581
### Routing
7682

7783
Routes are defined in `src/routes.tsx` as `AppRoute` objects with metadata (icon, access flags: `public`, `private`, `staffOnly`, `showInMenue`). `NavigationMenu` filters visible routes based on auth state. Private routes use `ProtectedRoute` wrapper with Auth0's `withAuthenticationRequired`.
7884

79-
Key routes: `/abteilungen/:abteilungSlugOrId/:tab/:orderId` — the abteilung detail page is the main working area, with tabs for materials, members, groups, orders, settings, standorte, and categories.
80-
81-
### Business Logic
82-
83-
Utility modules in `src/util/` contain Firestore CRUD operations and business logic (e.g., `MaterialUtil.ts` handles material CRUD, keyword generation for search, availability calculations, batch import via Firestore transactions).
84-
8585
### Deployment
8686

87-
Auto-deployed via GitHub Actions on push to `master`. Builds a Docker container (Node 15 build stage → nginx serving stage) pushed to `registry.cevi.tools`.
87+
Auto-deployed via GitHub Actions on push to `master`. Builds a Docker container (Node 24 build stage → nginx serving stage) pushed to `registry.cevi.tools`.

Dockerfile

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,18 @@
1-
FROM node:15-alpine3.13 AS builder
2-
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
3-
RUN apk add --no-cache libc6-compat
4-
RUN apk update && apk add --no-cache git
1+
FROM node:24-alpine AS builder
2+
RUN apk add --no-cache libc6-compat git
53

6-
# Create app directory
74
WORKDIR /usr/src/app
85

9-
COPY package*.json ./
10-
COPY *.lock ./
6+
COPY package*.json yarn.lock ./
7+
RUN yarn install --frozen-lockfile
118

12-
RUN yarn install --frozen-lockfile --ignore-engines
13-
14-
# Bundle app source
159
COPY . .
16-
17-
# load environment variables from .env
18-
RUN set -a && . .env && set +a
19-
2010
RUN yarn run build
2111

22-
# Stage 2: Serve app with nginx server
23-
# Use official nginx image as the base image
24-
FROM nginx:1.23.2-alpine
12+
FROM nginx:1.27-alpine
2513

26-
# copy the nginx configuration file to the container
2714
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
28-
29-
# copy the /public folder from the builder stage
3015
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
3116

3217
EXPOSE 3000
33-
CMD ["nginx", "-g", "daemon off;"]
18+
CMD ["nginx", "-g", "daemon off;"]

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,17 @@
55
### First installation
66

77
1. Install [node.js version management](https://github.com/coreybutler/nvm-windows)
8-
2. Execute `nvm install 15.14.0`
9-
3. Execute `nvm use 15.14.0`
8+
2. Execute `nvm install 24`
9+
3. Execute `nvm use 24`
1010
4. Execute `npm i yarn -g` --> Installs yarn globally.
1111
5. Execute `yarn` --> Installs all dependencies.
1212

1313
### Start the application
1414

15-
1. Execute: `yarn start` --> Runs the app in the development mode.
15+
1. Execute: `yarn dev` --> Runs the app in the development mode.
1616
2. Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
1717

18-
The page will reload if you make edits.
19-
You will also see any lint errors in the console.
18+
The page will reload if you make edits.
2019

2120
Happy Coding!
2221

@@ -25,6 +24,7 @@ Happy Coding!
2524
**The Application won't start**
2625
Don't forget to create the `.env` file with all the keys and values in it.
2726
For that just copy the `.env.example` file, rename it to `.env`, and add the missing secrets.
27+
Note: environment variables use the `VITE_` prefix (e.g. `VITE_FIREBASE_API_KEY`).
2828
To get the `.env` values for the dev instance, please contact onlinemat@cevi.tools
2929

3030
**Where is the backend?**

index.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<link rel="icon" href="/favicon/favicon.ico" />
7+
<link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
8+
<link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
9+
<link rel="apple-touch-icon" sizes="72x72" href="/favicon/favicon/apple-icon-72x72.png">
10+
<link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
11+
<link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
12+
<link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
13+
<link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
14+
<link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
15+
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
16+
<link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png">
17+
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
18+
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
19+
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
20+
<link rel="manifest" href="/favicon/manifest.json">
21+
<meta name="msapplication-TileColor" content="#ffffff">
22+
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
23+
<meta name="theme-color" content="#ffffff">
24+
<meta name="viewport" content="width=device-width, initial-scale=1" />
25+
<meta name="description" content="Onlinemat - Material Management" />
26+
<title>Onlinemat</title>
27+
</head>
28+
29+
<body>
30+
<noscript>You need to enable JavaScript to run this app.</noscript>
31+
<div id="root"></div>
32+
<script type="module" src="/src/index.tsx"></script>
33+
</body>
34+
35+
</html>

0 commit comments

Comments
 (0)