Compare commits

..
8 Commits
Author SHA1 Message Date
theis.gaedigk cc2c3d7f54 Merge pull request 'Refactor1' (#18) from refactor1 into dev
Reviewed-on: #18
2026-10-26 20:16:56 +01:00
theis.gaedigk 8b89f31178 change version number 2026-10-26 20:16:33 +01:00
theis.gaedigk c7933dfa3b add backend versioning 2026-10-26 20:15:06 +01:00
theis.gaedigk c1bb628f22 fix npm bug 2026-10-26 20:07:40 +01:00
theis.gaedigk 941f9105d6 change compose config 2026-10-26 19:56:49 +01:00
theis.gaedigk 0070b0e7a0 change folder name 2026-10-26 19:41:34 +01:00
theis.gaedigk 63d3e2db07 change config of services 2026-10-26 19:35:40 +01:00
theis.gaedigk 9c17b2a495 major changes to docker and npm config 2026-10-26 16:29:17 +01:00
99 changed files with 3343 additions and 9046 deletions
+14
View File
@@ -0,0 +1,14 @@
**/node_modules
**/dist
**/dist-ssr
.git
.idea
.vscode
**/.env
**/.env.*
**/.DS_Store
**/*.log
docs
pics
icon
no-as-a-service
+10
View File
@@ -0,0 +1,10 @@
DB_PASSWORD=
BACKEND_URL=
MAIL_HOST=
MAIL_PORT=
MAIL_USER=
MAIL_PASSWORD=
MAIL_SENDEES_CONTACT=
MAIL_SENDEES=
NAAS_URL=
SECRET_KEY=
+3 -1
View File
@@ -11,6 +11,8 @@ dist/
build/
out/
docker-compose.override.yml
# Environment variables
.env
.env.local
@@ -119,6 +121,6 @@ ToDo.txt
next-env.d.ts
# psd files from footage
footage/*.psd
pics/*.psd
icon/
+7
View File
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": false,
"trailingComma": "all",
"printWidth": 80,
"tabWidth": 2
}
+78
View File
@@ -0,0 +1,78 @@
# Docker
## Prerequisites
You have created an empty `docker-compose.override.yml` file in the root directory of this repository.
## Docker Network
If you want to run the stack in a docker network, you need to change the `BACKEND_HOST` variable in the root `.env` file
to `stockhome-backend`. To add a docker network, create a `docker-compose.override.yml` file in the root directory of
this repository with the following content:
```yaml
services:
admin-frontend:
networks:
- proxynet
backend:
networks:
- proxynet
usr-frontend:
networks:
- proxynet
no-as-a-service:
networks:
- proxynet
mysql:
networks:
- proxynet
networks:
proxynet:
external: true
```
To start off I recommend to set the `BACKEND_HOST` variable to `localhost` and start the stack without a docker network.
After you have started the stack and everything is working, you can add a docker network.
## Ports
### Change Exposed Ports
If you want to change the exposed ports, you can do this in the `docker-compose.yml` file like so:
```yaml
services:
mysql:
ports:
- "3306:3306"
backend:
ports:
- "8004:8004"
usr-frontend:
ports:
- "80:80"
```
### Remove Exposed Ports
If you want to remove the exposed ports, you can do this in the `docker-compose.override.yml` file like so:
```yaml
services:
mysql:
ports: !override [ ]
backend:
ports: !override [ ]
usr-frontend:
ports: !override [ ]
```
-19
View File
@@ -1,19 +0,0 @@
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine AS runner
WORKDIR /usr/share/nginx/html
COPY --from=builder /app/dist .
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+18 -15
View File
@@ -19,14 +19,18 @@ A small full‑stack system to log in, view available items, reserve them for a
## Contents
- Frontend: [frontend/](frontend)
- Vite/Tailwind config: [frontend/vite.config.ts](frontend/vite.config.ts), [frontend/tailwind.config.js](frontend/tailwind.config.js)
- Vite/Tailwind
config: [frontend/vite.config.ts](frontend/vite.config.ts), [frontend/tailwind.config.js](frontend/tailwind.config.js)
- App entry: [frontend/src/main.tsx](frontend/src/main.tsx), [frontend/src/App.tsx](frontend/src/App.tsx)
- UI: [frontend/src/layout/Layout.tsx](frontend/src/layout/Layout.tsx), [frontend/src/components](frontend/src/components)
- Data/utilities: [frontend/src/utils/fetchData.ts](frontend/src/utils/fetchData.ts), [frontend/src/utils/userHandler.ts](frontend/src/utils/userHandler.ts), [frontend/src/utils/toastify.ts](frontend/src/utils/toastify.ts)
-
UI: [frontend/src/layout/Layout.tsx](frontend/src/layout/Layout.tsx), [frontend/src/components](frontend/src/components)
-
Data/utilities: [frontend/src/utils/fetchData.ts](frontend/src/utils/fetchData.ts), [frontend/src/utils/userHandler.ts](frontend/src/utils/userHandler.ts), [frontend/src/utils/toastify.ts](frontend/src/utils/toastify.ts)
- Backend: [backend/](backend)
- Server: [backend/server.js](backend/server.js)
- Routes: [backend/routes/api.js](backend/routes/api.js), [backend/routes/apiV2.js](backend/routes/apiV2.js)
- DB + services: [backend/services/database.js](backend/services/database.js), [backend/services/tokenService.js](backend/services/tokenService.js)
- DB +
services: [backend/services/database.js](backend/services/database.js), [backend/services/tokenService.js](backend/services/tokenService.js)
- Schema/seed: [backend/scheme.sql](backend/scheme.sql)
- Docs: [docs/](docs)
- API docs (see below): [docs/backend_API_docs/README.md](docs/backend_API_docs/README.md)
@@ -41,7 +45,8 @@ A small full‑stack system to log in, view available items, reserve them for a
Key frontend utilities:
- [`utils.fetchData.fetchAllData`](frontend/src/utils/fetchData.ts): loads items, loans, and user loans after login.
- [`utils.fetchData.getBorrowableItems`](frontend/src/utils/fetchData.ts): fetches borrowable items for the selected time range.
- [`utils.fetchData.getBorrowableItems`](frontend/src/utils/fetchData.ts): fetches borrowable items for the selected
time range.
- [`utils.userHandler.createLoan`](frontend/src/utils/userHandler.ts): creates a new loan for selected items.
- [`utils.userHandler.handleDeleteLoan`](frontend/src/utils/userHandler.ts): deletes a loan and syncs local state.
- [`utils.toastify.myToast`](frontend/src/utils/toastify.ts): toast notifications.
@@ -54,20 +59,18 @@ UI flow (main screens):
## Development
- Scripts: see [frontend/package.json](frontend/package.json) and [backend/package.json](backend/package.json)
- Frontend: `npm run dev`, `npm run build`, `npm run preview`, `npm run lint`
- Backend: `npm start`
- Linting: ESLint configured via [frontend/eslint.config.js](frontend/eslint.config.js)
- TypeScript configs: [frontend/tsconfig.app.json](frontend/tsconfig.app.json), [frontend/tsconfig.node.json](frontend/tsconfig.node.json)
- The NAAS (no-as-a-service) and the mysql database are running in a docker container
- `frontend`, `backend` and `admin` are both in a vite dev server and can be started by `npm run dev` in the root
directory.
## Configuration notes
- Vite/Tailwind integration via [frontend/vite.config.ts](frontend/vite.config.ts) and `@tailwindcss/vite`; CSS entry uses `@import "tailwindcss"` in [frontend/src/index.css](frontend/src/index.css).
- Vite/Tailwind integration via [frontend/vite.config.ts](frontend/vite.config.ts) and `@tailwindcss/vite`; CSS entry
uses `@import "tailwindcss"` in [frontend/src/index.css](frontend/src/index.css).
- Toasts wired in [frontend/src/main.tsx](frontend/src/main.tsx) with `react-toastify`.
- Local state is stored in `localStorage` keys: `allItems`, `allLoans`, `userLoans`, `borrowableItems`. Cross‑component updates are signaled via window events from [`utils.fetchData`](frontend/src/utils/fetchData.ts).
- Local state is stored in `localStorage` keys: `allItems`, `allLoans`, `userLoans`, `borrowableItems`. Cross‑component
updates are signaled via window events from [`utils.fetchData`](frontend/src/utils/fetchData.ts).
## API documentation
Refer to the dedicated API docs:
`docs/backend_API_docs/README.md`
Refer to the dedicated [API-Docs](docs/backend_API_docs/README.md)
+13 -6
View File
@@ -1,19 +1,26 @@
FROM node:18 as builder
# Build context is the repo root (npm workspaces share one root package-lock.json)
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY frontend/package.json frontend/
COPY admin/package.json admin/
COPY backend/package.json backend/
RUN npm ci -w admin
COPY . .
RUN npm run build
ARG VITE_BACKEND_URL
ENV VITE_BACKEND_URL=$VITE_BACKEND_URL
COPY admin/ admin/
RUN npm run build -w admin
FROM nginx:alpine AS runner
WORKDIR /usr/share/nginx/html
COPY --from=builder /app/dist .
COPY --from=builder /app/admin/dist .
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY admin/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+1 -1
View File
@@ -14,7 +14,7 @@ server {
}
location /backend/ {
proxy_pass http://borrow_system-backend_v2:8004/;
proxy_pass http://borrow-system_backend:8004/;
}
location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
-6066
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "admin",
"private": true,
"version": "v1.3.2 (dev)",
"version": "1.3.2-dev",
"type": "module",
"scripts": {
"dev": "vite",
+28
View File
@@ -0,0 +1,28 @@
# Build context is the repo root (npm workspaces share one root package-lock.json)
FROM node:20-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY package.json package-lock.json ./
COPY frontend/package.json frontend/
COPY admin/package.json admin/
COPY backend/package.json backend/
RUN npm ci -w backend --omit=dev
COPY backend/ backend/
# Generate info.json from the workspace package.json versions, without the "-dev" suffix
RUN node -e ' \
const fs = require("fs"); \
const v = (p) => "v" + JSON.parse(fs.readFileSync(p + "/package.json")).version.replace(/-dev$/, ""); \
fs.writeFileSync("backend/info.json", JSON.stringify({ \
"backend-info": { version: v("backend") }, \
"frontend-info": { version: v("frontend") }, \
"admin-panel-info": { version: v("admin") } \
}, null, 4)); \
'
WORKDIR /app/backend
EXPOSE 8004
CMD ["npm", "start"]
@@ -1,10 +1,11 @@
{
"name": "backendv2",
"version": "v2.1.1 (dev)",
"name": "backend",
"version": "2.1.1-dev",
"private": true,
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
"dev": "node --watch server.js",
"start": "NODE_ENV=production node server.js"
},
"keywords": [],
"author": "",
@@ -18,6 +19,6 @@
"express-rate-limit": "^8.4.1",
"jose": "^6.0.12",
"mysql2": "^3.14.3",
"nodemailer": "^8.0.6"
"nodemailer": "^10.2.1"
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import info from "./info.json" assert { type: "json" };
import info from "./info.json" with { type: "json" };
import { authenticate } from "./services/authentication.js";
import { rateLimit } from "express-rate-limit";
-12
View File
@@ -1,12 +0,0 @@
FROM node:20-alpine
ENV NODE_ENV=production
WORKDIR /backend
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8004
CMD ["npm", "start"]
-1141
View File
File diff suppressed because it is too large Load Diff
-29
View File
@@ -1,29 +0,0 @@
# Changelog for upcoming version: vX.X
Introduction
## New features
-
## Improvements
-
## Fixed bugs
-
---
## New version numbers
**Backend:** vX.X
**Frontend:** vX.X
**Admin panel:** vX.X
---
-[Theis](https://portfolio-theis.de)
+56
View File
@@ -0,0 +1,56 @@
services:
# usr-frontend_v2:
# container_name: borrow_system-usr-frontend
# build: ./FrontendV2
# ports:
# - "8001:80"
# restart: always
# admin-frontend:
# container_name: borrow_system-admin-frontend
# build: ./admin
# ports:
# - "8003:80"
# restart: always
# backend_v2:
# container_name: borrow_system-backend_v2
# build: ./backend
# ports:
# - "8004:8004"
# environment:
# NODE_ENV: production
# DB_HOST: mysql_v2
# DB_USER: root
# DB_PASSWORD: ${DB_PASSWORD_V2}
# DB_NAME: borrow_system_new
# depends_on:
# - mysql_v2
# restart: always
mysql:
container_name: borrow-system_mysql
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD_V2}
MYSQL_DATABASE: borrow_system_new
TZ: Europe/Berlin
volumes:
- mysql-v2-data:/var/lib/mysql
- ./mysql-timezone.cnf:/etc/mysql/conf.d/timezone.cnf:ro
ports:
- "3310:3306"
no-as-a-service:
container_name: borrow-system_naas
ports:
- "3000:3000"
build:
context: ./no-as-a-service
dockerfile: Dockerfile
restart: always
volumes:
mysql-data:
mysql-v2-data:
+43 -35
View File
@@ -1,51 +1,59 @@
services:
# usr-frontend_v2:
# container_name: borrow_system-usr-frontend
# build: ./FrontendV2
# ports:
# - "8001:80"
# restart: always
# admin-frontend:
# container_name: borrow_system-admin-frontend
# build: ./admin
# ports:
# - "8003:80"
# restart: always
backend_v2:
container_name: borrow_system-backend_v2
build: ./backendV2
ports:
- "8004:8004"
environment:
NODE_ENV: production
DB_HOST: mysql_v2
DB_USER: root
DB_PASSWORD: ${DB_PASSWORD_V2}
DB_NAME: borrow_system_new
depends_on:
- mysql_v2
usr-frontend:
container_name: borrow-system_usr-frontend
build:
context: .
dockerfile: frontend/Dockerfile
args:
VITE_BACKEND_URL: ${BACKEND_URL}
restart: always
mysql_v2:
container_name: borrow_system-mysql-v2
admin-frontend:
container_name: borrow-system_admin-frontend
build:
context: .
dockerfile: admin/Dockerfile
args:
VITE_BACKEND_URL: ${BACKEND_URL}
restart: always
backend:
container_name: borrow-system_backend
build:
context: .
dockerfile: backend/Dockerfile
environment:
NODE_ENV: production
DB_HOST: borrow-system_mysql
DB_USER: root
DB_PASSWORD: ${DB_PASSWORD}
DB_NAME: borrow_system_new
MAIL_HOST: ${MAIL_HOST}
MAIL_PORT: ${MAIL_PORT}
MAIL_USER: ${MAIL_USER}
MAIL_PASSWORD: ${MAIL_PASSWORD}
MAIL_SENDEES_CONTACT: ${MAIL_SENDEES_CONTACT}
MAIL_SENDEES: ${MAIL_SENDEES}
NAAS_URL: ${NAAS_URL}
SECRET_KEY: ${SECRET_KEY}
depends_on:
- mysql
restart: always
mysql:
container_name: borrow-system_mysql
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD_V2}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: borrow_system_new
TZ: Europe/Berlin
volumes:
- mysql-v2-data:/var/lib/mysql
- ./mysql-timezone.cnf:/etc/mysql/conf.d/timezone.cnf:ro
ports:
- "3310:3306"
no-as-a-service:
container_name: borrow_system-naas
ports:
- "3000:3000"
container_name: borrow-system_naas
build:
context: ./no-as-a-service
dockerfile: Dockerfile
+26
View File
@@ -0,0 +1,26 @@
# Build context is the repo root (npm workspaces share one root package-lock.json)
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
COPY frontend/package.json frontend/
COPY admin/package.json admin/
COPY backend/package.json backend/
RUN npm ci -w frontend
ARG VITE_BACKEND_URL
ENV VITE_BACKEND_URL=$VITE_BACKEND_URL
COPY frontend/ frontend/
RUN npm run build -w frontend
FROM nginx:alpine AS runner
WORKDIR /usr/share/nginx/html
COPY --from=builder /app/frontend/dist .
COPY frontend/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
@@ -14,7 +14,7 @@ server {
}
location /backend/ {
proxy_pass http://borrow_system-backend_v2:8004/;
proxy_pass http://borrow-system_backend:8004/;
}
location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
@@ -1,7 +1,7 @@
{
"name": "admin",
"name": "frontend",
"private": true,
"version": "v2.1.2 (dev)",
"version": "2.1.2-dev",
"type": "module",
"scripts": {
"dev": "vite",
@@ -45,6 +45,7 @@
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0",
"prettier": "^3.9.10",
"typescript": "~5.8.3",
"typescript-eslint": "^8.39.0",
"vite": "^7.1.0",

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -14,5 +14,5 @@ createRoot(document.getElementById("root")!).render(
<Provider>
<App />
</Provider>
</StrictMode>
</StrictMode>,
);
+2
View File
@@ -0,0 +1,2 @@
[mysqld]
default-time-zone = Europe/Berlin
File diff suppressed because it is too large Load Diff
+35
View File
@@ -0,0 +1,35 @@
{
"name": "borrow-system",
"version": "2.3.0",
"private": true,
"workspaces": [
"backend",
"frontend",
"admin"
],
"description": "",
"main": "index.js",
"directories": {
"doc": "docs"
},
"devDependencies": {
"concurrently": "^10.0.6",
"prettier": "^3.9.6"
},
"scripts": {
"dev:docker": "docker compose -f docker-compose.dev.yml up -d",
"dev": "npm run dev:docker && concurrently --kill-others \"npm:dev:frontend\" \"npm:dev:backend\" \"npm:dev:admin\"",
"dev:frontend": "npm run dev -w frontend",
"dev:backend": "npm run dev -w backend",
"dev:admin": "npm run dev -w admin",
"dev:stop": "docker compose -f docker-compose.dev.yml down"
},
"repository": {
"type": "git",
"url": "https://git.the1s.de/theis.gaedigk/borrow-system.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Before

Width:  |  Height:  |  Size: 428 KiB

After

Width:  |  Height:  |  Size: 428 KiB

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 416 KiB