Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a545772
feat: implement TimePicker component for improved time selection in r…
Nov 14, 2025
fd43cba
Made fixes on comment and gatekeeper appliance access
Jan 9, 2026
14ed188
Refactored frontend to monochromatic desgin
justnyx Mar 18, 2026
e2f55ac
Refactored calendar design
justnyx Mar 18, 2026
6c9cc3b
refactored calendar for mobile view
justnyx Mar 18, 2026
05f4375
feat: add sanction management features including SanctionRecord model…
Mar 18, 2026
86934c2
Added gatekeeper priority
Mar 20, 2026
2cdacb7
Fixed bug: calendar card shift
Mar 20, 2026
0f42f30
Remove SANCTIONED status from ReservationStatus enum and related logi…
Mar 22, 2026
8ab6e2b
feat: add OpenedWeek model and enhance Settings with new attributes f…
Mar 22, 2026
1a8ce55
Merge origin/main and resolve conflicts
Mar 22, 2026
459f9c2
Add missing sonner dependency for frontend
Mar 22, 2026
0ab44ce
Refactor: remove ReservationConfig and SanctionTier models, along wit…
Mar 23, 2026
49c3f85
Build error fix
Mar 23, 2026
4d1a9d7
Merge remote-tracking branch 'origin/frontend_refactor' into feature/…
Mar 23, 2026
9052054
Enhance reservation management: include gatekeeper details in reserva…
Mar 23, 2026
e3a4587
Enhance reservation functionality: add optional gatekeeper ID to find…
Mar 23, 2026
d9855e9
ESLint fixes
Mar 24, 2026
81cff6f
Enhance sanction records functionality: add reservationId to sanction…
Mar 26, 2026
c620671
Added missing migration file and fixed ESLint errors/warnings
Mar 26, 2026
fe6a1c4
feat: enhance authorization and settings management
Jun 18, 2026
9e29f53
fix: address CodeRabbit/Copilot PR review findings
Jun 19, 2026
8d59ac6
refactor: replace string literals with ReservationStatus enum in comm…
Jun 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
env: {
node: true,
},
ignorePatterns: ['.eslintrc.js', '.prettierrc.js'],
ignorePatterns: ['.eslintrc.js', '.prettierrc.js', 'apps/frontend/next-env.d.ts'],
rules: {
'prettier/prettier': 'error',
'simple-import-sort/imports': 'error',
Expand Down
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
.idea
dist
.next
.next
next-env.d.ts
11 changes: 11 additions & 0 deletions apps/backend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: 'src',
testRegex: '.*\\.spec\\.ts$',
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
},
collectCoverageFrom: ['**/*.{ts,js}'],
coverageDirectory: '../coverage',
testEnvironment: 'node',
};
7 changes: 6 additions & 1 deletion apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main"
"start:prod": "node dist/main",
"test:backend": "jest"
},
"dependencies": {
"@kir-dev/passport-authsch": "^2.2.2",
Expand All @@ -37,11 +38,15 @@
"devDependencies": {
"@nestjs/cli": "^10.3.2",
"@nestjs/schematics": "^10.1.1",
"@nestjs/testing": "^11.1.17",
"@types/express": "^4.17.21",
"@types/jest": "^30.0.0",
"@types/node": "^20.12.7",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.7.1",
"jest": "^30.3.0",
"source-map-support": "^0.5.21",
"ts-jest": "^29.4.6",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "4.2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- AlterEnum
ALTER TYPE "ReservationStatus" ADD VALUE 'SANCTIONED';

-- AlterTable
ALTER TABLE "Period" ADD COLUMN "isOpen" BOOLEAN NOT NULL DEFAULT false;

-- AlterTable
ALTER TABLE "User" ADD COLUMN "sanctionPoints" INTEGER NOT NULL DEFAULT 0;

-- CreateTable
CREATE TABLE "Settings" (
"id" SERIAL NOT NULL,
"maxHoursPerWeek" DOUBLE PRECISION NOT NULL DEFAULT 8.0,
"maxHoursPerDay" DOUBLE PRECISION NOT NULL DEFAULT 4.0,
"minReservationMinutes" INTEGER NOT NULL DEFAULT 30,
"maxReservationMinutes" INTEGER NOT NULL DEFAULT 180,
"sanctionHourPenaltyPerPoint" DOUBLE PRECISION NOT NULL DEFAULT 1.0,

CONSTRAINT "Settings_pkey" PRIMARY KEY ("id")
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Reservation" ADD COLUMN "needToBeLetIn" BOOLEAN NOT NULL DEFAULT false;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Warnings:

- You are about to drop the column `sanctionPoints` on the `User` table. All the data in the column will be lost.

*/
-- AlterTable
ALTER TABLE "User" DROP COLUMN "sanctionPoints";

-- CreateTable
CREATE TABLE "SanctionRecord" (
"id" SERIAL NOT NULL,
"userId" INTEGER,
"bandId" INTEGER,
"points" INTEGER NOT NULL,
"reason" TEXT NOT NULL,
"awardedBy" INTEGER NOT NULL,
"awardedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

CONSTRAINT "SanctionRecord_pkey" PRIMARY KEY ("id")
);

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_bandId_fkey" FOREIGN KEY ("bandId") REFERENCES "Band"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_awardedBy_fkey" FOREIGN KEY ("awardedBy") REFERENCES "ClubMembership"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- CreateEnum
CREATE TYPE "GateKeeperPriority" AS ENUM ('PRIMARY', 'SECONDARY');

-- AlterTable
ALTER TABLE "Reservation" ADD COLUMN "gateKeeperPriority" "GateKeeperPriority";
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Warnings:

- The values [SANCTIONED] on the enum `ReservationStatus` will be removed. If these variants are still used in the database, this will fail.

*/
-- AlterEnum
BEGIN;
CREATE TYPE "ReservationStatus_new" AS ENUM ('NORMAL', 'OVERTIME', 'ADMINMADE');
ALTER TABLE "Reservation" ALTER COLUMN "status" TYPE "ReservationStatus_new" USING ("status"::text::"ReservationStatus_new");
ALTER TYPE "ReservationStatus" RENAME TO "ReservationStatus_old";
ALTER TYPE "ReservationStatus_new" RENAME TO "ReservationStatus";
DROP TYPE "ReservationStatus_old";
COMMIT;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- AlterTable
ALTER TABLE "Settings" ADD COLUMN "banSanctionPointThreshold" INTEGER NOT NULL DEFAULT 5,
ADD COLUMN "maxTotalHoursPerWeek" DOUBLE PRECISION NOT NULL DEFAULT 12.0,
ADD COLUMN "sanctionTotalHourPenaltyPerPoint" DOUBLE PRECISION NOT NULL DEFAULT 2.0;

-- CreateTable
CREATE TABLE "OpenedWeek" (
"id" SERIAL NOT NULL,
"monday" TIMESTAMP(3) NOT NULL,
"isOpen" BOOLEAN NOT NULL DEFAULT false,

CONSTRAINT "OpenedWeek_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "OpenedWeek_monday_key" ON "OpenedWeek"("monday");
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
Warnings:

- You are about to drop the `ReservationConfig` table. If the table is not empty, all the data it contains will be lost.
- You are about to drop the `SanctionTier` table. If the table is not empty, all the data it contains will be lost.

*/
-- DropForeignKey
ALTER TABLE "SanctionTier" DROP CONSTRAINT "SanctionTier_configId_fkey";

-- DropTable
DROP TABLE "ReservationConfig";

-- DropTable
DROP TABLE "SanctionTier";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "SanctionRecord" ADD COLUMN "reservationId" INTEGER;

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_reservationId_fkey" FOREIGN KEY ("reservationId") REFERENCES "Reservation"("id") ON DELETE SET NULL ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ALTER TABLE "Settings" ALTER COLUMN "maxHoursPerWeek" SET DEFAULT 6.0;
ALTER TABLE "Settings" ALTER COLUMN "maxHoursPerDay" SET DEFAULT 3.0;

UPDATE "Settings"
SET "maxHoursPerWeek" = 6.0
WHERE "maxHoursPerWeek" = 8.0;

UPDATE "Settings"
SET "maxHoursPerDay" = 3.0
WHERE "maxHoursPerDay" = 4.0;
102 changes: 64 additions & 38 deletions apps/backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,26 @@ enum BandMembershipStatus {
ACCEPTED
}

enum GateKeeperPriority {
PRIMARY
SECONDARY
}

model User {
id Int @id @default(autoincrement())
email String @unique
phone String? @unique
role Role @default(USER)
authSchId String? @unique
id Int @id @default(autoincrement())
email String @unique
phone String? @unique
role Role @default(USER)
authSchId String? @unique
fullName String
clubMembershipUpdatedAt DateTime?
bandMemberships BandMembership[]
clubMembership ClubMembership?
DormResidency DormResidency?
Post Post[]
profilePicture ProfilePicture?
reservations Reservation[] @relation("Reservations")
reservations Reservation[] @relation("Reservations")
sanctionRecords SanctionRecord[] @relation("UserSanctions")
}

model ProfilePicture {
Expand Down Expand Up @@ -70,17 +76,19 @@ model ClubMembership {
isGateKeeper Boolean
user User @relation(fields: [userId], references: [id])
gateKeepingRecords Reservation[] @relation("GateKeeping")
sanctionsAwarded SanctionRecord[] @relation("GateKeeperSanctions")
}

model Band {
id Int @id @default(autoincrement())
name String
email String?
webPage String?
description String?
genres String[]
members BandMembership[]
reservations Reservation[]
id Int @id @default(autoincrement())
name String
email String?
webPage String?
description String?
genres String[]
members BandMembership[]
reservations Reservation[]
sanctionRecords SanctionRecord[] @relation("BandSanctions")
}

model BandMembership {
Expand All @@ -95,16 +103,19 @@ model BandMembership {
}

model Reservation {
id Int @id @default(autoincrement())
id Int @id @default(autoincrement())
userId Int?
bandId Int?
startTime DateTime
endTime DateTime
gateKeeperId Int?
status ReservationStatus
band Band? @relation(fields: [bandId], references: [id])
gateKeeper ClubMembership? @relation("GateKeeping", fields: [gateKeeperId], references: [id])
user User? @relation("Reservations", fields: [userId], references: [id])
gateKeeperId Int?
gateKeeperPriority GateKeeperPriority?
status ReservationStatus
needToBeLetIn Boolean @default(false)
band Band? @relation(fields: [bandId], references: [id])
gateKeeper ClubMembership? @relation("GateKeeping", fields: [gateKeeperId], references: [id])
user User? @relation("Reservations", fields: [userId], references: [id])
sanctionRecords SanctionRecord[]
}

model Comment {
Expand All @@ -119,6 +130,7 @@ model Period {
id Int @id @default(autoincrement())
startDate DateTime
endDate DateTime
isOpen Boolean @default(false)
}

model Post {
Expand All @@ -131,22 +143,36 @@ model Post {
User User @relation(fields: [authorId], references: [id])
}

model ReservationConfig {
id Int @id @default(autoincrement())
userDailyHours Float @default(4)
userWeeklyHours Float @default(8)
bandDailyHours Float @default(6)
bandWeeklyHours Float @default(12)
sanctionTiers SanctionTier[]
}

model SanctionTier {
id Int @id @default(autoincrement())
configId Int
config ReservationConfig @relation(fields: [configId], references: [id])
minPoints Int
userDailyHours Float
userWeeklyHours Float
bandDailyHours Float
bandWeeklyHours Float
model Settings {
id Int @id @default(autoincrement())
maxHoursPerWeek Float @default(6.0)
maxHoursPerDay Float @default(3.0)
minReservationMinutes Int @default(30)
maxReservationMinutes Int @default(180)
sanctionHourPenaltyPerPoint Float @default(1.0)
maxTotalHoursPerWeek Float @default(12.0)
sanctionTotalHourPenaltyPerPoint Float @default(2.0)
banSanctionPointThreshold Int @default(5)
}

model OpenedWeek {
id Int @id @default(autoincrement())
monday DateTime @unique
isOpen Boolean @default(false)
}

model SanctionRecord {
id Int @id @default(autoincrement())
userId Int?
bandId Int?
reservationId Int?
points Int
reason String
awardedBy Int
awardedAt DateTime @default(now())

user User? @relation("UserSanctions", fields: [userId], references: [id])
band Band? @relation("BandSanctions", fields: [bandId], references: [id])
reservation Reservation? @relation(fields: [reservationId], references: [id])
gateKeeper ClubMembership @relation("GateKeeperSanctions", fields: [awardedBy], references: [id])
}
34 changes: 0 additions & 34 deletions apps/backend/src/admin/admin.controller.ts

This file was deleted.

10 changes: 0 additions & 10 deletions apps/backend/src/admin/admin.module.ts

This file was deleted.

Loading