Skip to content

Commit f9bf6ed

Browse files
committed
Merge branch 'develop' into #4037-JasperPinkus-credits
2 parents 775478f + d89a5f4 commit f9bf6ed

98 files changed

Lines changed: 2872 additions & 1293 deletions

File tree

Some content is hidden

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

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,5 @@ eb-deploy/
7070

7171
# Claude Code Files
7272
CLAUDE.md
73-
.playwright-mcp/
73+
.playwright-mcp/
74+
docs/

Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build stage - compile TypeScript
2-
FROM node:20 AS builder
2+
FROM node:25 AS builder
33
WORKDIR /app
44

55
COPY package.json tsconfig.build.json ./
@@ -11,11 +11,11 @@ RUN cd src/backend && npx prisma generate
1111
RUN yarn build:shared
1212
RUN yarn build:backend
1313

14-
FROM node:20-slim
14+
FROM platformatic/node-caged:25-slim
1515
WORKDIR /app
1616

1717
# Install OpenSSL for Prisma (slim image needs this)
18-
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
18+
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/* && npm install -g yarn
1919

2020
COPY package.json ./
2121

devContainerization/Dockerfile.backend.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:20
1+
FROM node:25
22

33
COPY package.json tsconfig.build.json ./
44
COPY ./src/backend/package.json ./src/backend/tsconfig.json src/backend/

devContainerization/Dockerfile.frontend.dev

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:20-alpine
1+
FROM node:25-alpine
22

33
COPY package.json tsconfig.build.json ./
44
COPY ./src/frontend/package.json ./src/frontend/tsconfig.json src/frontend/
@@ -11,4 +11,4 @@ COPY ./src/frontend src/frontend
1111
COPY ./src/shared src/shared
1212

1313
EXPOSE 3000
14-
CMD [ "yarn", "workspace", "frontend", "vite", "--force", "--host" ]
14+
CMD [ "yarn", "workspace", "frontend", "vite", "--force", "--host" ]

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
"@babel/preset-typescript": "^7.18.6",
8787
"@types/canvas-confetti": "^1.9.0",
8888
"@types/jest": "^29.5.14",
89-
"@types/node": "20.0.0",
89+
"@types/node": "^25.0.0",
9090
"@typescript-eslint/eslint-plugin": "8.20.0",
9191
"@typescript-eslint/parser": "8.20.0",
9292
"concurrently": "^9.1.0",

src/backend/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# TO BE RUN FROM DOCKER COMPOSE. DO NOT RUN MANUALLY AS CONTEXT IS NOT SET CORRECTLY
2-
FROM node:20
2+
FROM platformatic/node-caged:25-slim
3+
RUN npm install -g yarn
34

45
WORKDIR /base
56

src/backend/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import partsRouter from './src/routes/parts.routes.js';
2727
import financeRouter from './src/routes/finance.routes.js';
2828
import calendarRouter from './src/routes/calendar.routes.js';
2929
import prospectiveSponsorRouter from './src/routes/prospective-sponsor.routes.js';
30+
import attendanceRouter from './src/routes/attendance.routes.js';
3031

3132
const app = express();
3233

@@ -112,6 +113,7 @@ app.use('/parts', partsRouter);
112113
app.use('/finance', financeRouter);
113114
app.use('/calendar', calendarRouter);
114115
app.use('/prospective-sponsors', prospectiveSponsorRouter);
116+
app.use('/attendance', attendanceRouter);
115117
app.use('/', (_req, res) => {
116118
res.status(200).json('Welcome to FinishLine');
117119
});

src/backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"devDependencies": {
4040
"@types/express-jwt": "^6.0.4",
4141
"@types/jsonwebtoken": "^8.5.9",
42-
"@types/node": "^20.0.0",
42+
"@types/node": "^25.0.0",
4343
"@types/supertest": "^2.0.12",
4444
"nodemon": "^2.0.16",
4545
"supertest": "^6.2.4",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { NextFunction, Request, Response } from 'express';
2+
import AttendanceService from '../services/attendance.services.js';
3+
4+
export default class AttendanceController {
5+
static async takeAttendance(req: Request, res: Response, next: NextFunction) {
6+
try {
7+
const { teamId, message } = req.body;
8+
const attendance = await AttendanceService.takeAttendance(req.currentUser, teamId, message, req.organization);
9+
res.status(200).json(attendance);
10+
} catch (error: unknown) {
11+
next(error);
12+
}
13+
}
14+
15+
static async getAllAttendances(req: Request, res: Response, next: NextFunction) {
16+
try {
17+
const attendances = await AttendanceService.getAllAttendances(req.organization);
18+
res.status(200).json(attendances);
19+
} catch (error: unknown) {
20+
next(error);
21+
}
22+
}
23+
24+
static async getOngoingAttendance(req: Request, res: Response, next: NextFunction) {
25+
try {
26+
const { teamId } = req.params as Record<string, string>;
27+
const attendance = await AttendanceService.getOngoingAttendance(teamId, req.organization);
28+
res.status(200).json(attendance);
29+
} catch (error: unknown) {
30+
next(error);
31+
}
32+
}
33+
34+
static async closeOngoingAttendance(req: Request, res: Response, next: NextFunction) {
35+
try {
36+
const { teamId } = req.params as Record<string, string>;
37+
await AttendanceService.closeOngoingAttendance(teamId, req.currentUser, req.organization);
38+
res.status(200).json({ message: 'Attendance closed successfully' });
39+
} catch (error: unknown) {
40+
next(error);
41+
}
42+
}
43+
44+
static async checkChannel(req: Request, res: Response, next: NextFunction) {
45+
try {
46+
const { teamId } = req.params as Record<string, string>;
47+
const result = await AttendanceService.checkTeamChannel(teamId, req.organization);
48+
res.status(200).json(result);
49+
} catch (error: unknown) {
50+
next(error);
51+
}
52+
}
53+
}

src/backend/src/controllers/organizations.controllers.ts

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,6 @@ export default class OrganizationsController {
2222
}
2323
}
2424

25-
static async setImages(req: Request, res: Response, next: NextFunction) {
26-
try {
27-
const { applyInterestImage = [], exploreAsGuestImage = [] } = req.files as {
28-
applyInterestImage?: Express.Multer.File[];
29-
exploreAsGuestImage?: Express.Multer.File[];
30-
};
31-
32-
const applyInterestFile = applyInterestImage[0] || null;
33-
const exploreAsGuestFile = exploreAsGuestImage[0] || null;
34-
35-
const newImages = await OrganizationsService.setImages(
36-
applyInterestFile,
37-
exploreAsGuestFile,
38-
req.currentUser,
39-
req.organization
40-
);
41-
42-
res.status(200).json(newImages);
43-
} catch (error: unknown) {
44-
next(error);
45-
}
46-
}
4725
static async getAllUsefulLinks(req: Request, res: Response, next: NextFunction) {
4826
try {
4927
const links = await OrganizationsService.getAllUsefulLinks(req.organization.organizationId);
@@ -97,15 +75,6 @@ export default class OrganizationsController {
9775
}
9876
}
9977

100-
static async getOrganizationImages(req: Request, res: Response, next: NextFunction) {
101-
try {
102-
const images = await OrganizationsService.getOrganizationImages(req.organization.organizationId);
103-
res.status(200).json(images);
104-
} catch (error: unknown) {
105-
next(error);
106-
}
107-
}
108-
10978
static async setOrganizationFeaturedProjects(req: Request, res: Response, next: NextFunction) {
11079
try {
11180
const { projectIds } = req.body;
@@ -142,6 +111,20 @@ export default class OrganizationsController {
142111
}
143112
}
144113

114+
static async setPlatformLogoImage(req: Request, res: Response, next: NextFunction) {
115+
try {
116+
if (!req.file) {
117+
throw new HttpException(400, 'Invalid or undefined image data');
118+
}
119+
120+
const updatedOrg = await OrganizationsService.setPlatformLogoImage(req.file, req.currentUser, req.organization);
121+
122+
res.status(200).json(updatedOrg);
123+
} catch (error: unknown) {
124+
next(error);
125+
}
126+
}
127+
145128
static async setNewMemberImage(req: Request, res: Response, next: NextFunction) {
146129
try {
147130
if (!req.file) {
@@ -181,6 +164,20 @@ export default class OrganizationsController {
181164
}
182165
}
183166

167+
static async setPlatformDescription(req: Request, res: Response, next: NextFunction) {
168+
try {
169+
const updatedOrg = await OrganizationsService.setPlatformDescription(
170+
req.body.platformDescription,
171+
req.currentUser,
172+
req.organization
173+
);
174+
175+
res.status(200).json(updatedOrg);
176+
} catch (error: unknown) {
177+
next(error);
178+
}
179+
}
180+
184181
static async getOrganizationFeaturedProjects(req: Request, res: Response, next: NextFunction) {
185182
try {
186183
const featuredProjects = await OrganizationsService.getOrganizationFeaturedProjects(req.organization.organizationId);

0 commit comments

Comments
 (0)