Skip to content
This repository was archived by the owner on Jan 28, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.itestra.eep.dtos.FileDetailsDTO;
import com.itestra.eep.models.Event;
import com.itestra.eep.models.FileEntity;
import com.itestra.eep.models.Participation;
import org.mapstruct.*;

import java.time.LocalDateTime;
Expand All @@ -28,20 +27,12 @@ public interface EventMapper {
List<EventDetailsDTO> toDetailsDto(List<Event> events);

@Mappings({
@Mapping(source = "participations", target = "participantCount", qualifiedByName = "countConfirmed"),
@Mapping(source = "date", target = "status", qualifiedByName = "status")
})
EventDetailsDTO toDetailsDto(Event event);

FileDetailsDTO toFileDetailsDto(FileEntity file);

@Named("countConfirmed")
default int map(List<Participation> participations) {
return participations.stream().filter(Participation::isConfirmed)
.mapToInt(p -> p.getGuestCount() + 1)
.sum();
}

@Named("status")
default String status(LocalDateTime eventDate) {
return eventDate.isAfter(LocalDateTime.now()) ? "upcoming" : "completed";
Expand Down
4 changes: 2 additions & 2 deletions backend/src/main/java/com/itestra/eep/models/Employee.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class Employee {
private UUID id;

@MapsId
@OneToOne(fetch = FetchType.LAZY, optional = false)
@OneToOne(fetch = FetchType.LAZY, optional = false, orphanRemoval = true)
@JoinColumn(name = "profile_id", nullable = false)
private Profile profile;

Expand All @@ -35,7 +35,7 @@ public class Employee {
@Column(name = "employment_type")
private EmploymentType employmentType;

@OneToMany(mappedBy = "employee")
@OneToMany(mappedBy = "employee", orphanRemoval = true)
private List<Participation> participations = new LinkedList<>();

@ManyToMany
Expand Down
13 changes: 13 additions & 0 deletions backend/src/main/java/com/itestra/eep/models/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,18 @@ public class Event {
@OneToOne(mappedBy = "event", orphanRemoval = true)
private Schematics schematics;

@Transient
public int getParticipantCount() {
return getParticipantCount(null);
}

@Transient
public int getParticipantCount(Participation excludeParticipation) {
return participations.stream()
.filter(p -> excludeParticipation == null || !p.getId().equals(excludeParticipation.getId()))
.mapToInt(p -> p.getGuestCount() + 1)
.sum();
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ public Event create(EventCreateDTO dto) {
public Event update(UUID id, EventUpdateDTO dto) {
Event event = eventRepository.findById(id).orElseThrow(EventNotFoundException::new);
eventMapper.updateEventFromDto(dto, event);

if (event.getCapacity() < participationRepository.sumGuestCounts(event, null)) {
if (dto.getCapacity() != null && event.getParticipantCount(null) > dto.getCapacity()) {
throw new EventCapacityExceededException();
}

return eventRepository.save(event);
}

Expand Down Expand Up @@ -107,9 +105,7 @@ public void deleteParticipant(UUID participationId) {

private void validateCapacity(Event event, int guestCount, Participation excludeParticipation) {

Integer total = participationRepository.sumGuestCounts(event, excludeParticipation == null ? null : excludeParticipation.getId());

int currentTotal = total != null ? total : 0;
int currentTotal = event.getParticipantCount(excludeParticipation);

int newTotal = currentTotal + guestCount + 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class SchematicsController {
private final SchematicsMapper schematicsMapper;

@GetMapping("/{id}")
@PreAuthorize("hasAnyAuthority('ADMIN', 'EMPLOYEE', 'VISITOR')")
@PreAuthorize("hasAnyAuthority('ADMIN', 'EMPLOYEE')")
public ResponseEntity<SchematicsCreateDTO> getSchematics(@PathVariable UUID id) {
Schematics schematics = schematicsService.findById(id);
return new ResponseEntity<>(schematicsMapper.toSchematicsCreateDTO(schematics), HttpStatus.OK);
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { RouterProvider } from "react-router-dom";
import { ConfigProvider } from "antd";
import { AuthProvider } from "./contexts/AuthContext";
import { router } from "./routes/routes";
import { Toaster } from "react-hot-toast";
import {RouterProvider} from "react-router-dom";
import {ConfigProvider} from "antd";
import {AuthProvider} from "./contexts/AuthContext";
import {router} from "./routes/routes";
import {Toaster} from "react-hot-toast";

function App() {
return (
Expand Down
60 changes: 27 additions & 33 deletions frontend/src/components/AppContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { Avatar, Dropdown, Layout, Menu } from "antd";
import { Outlet, useLocation, useNavigate } from "react-router-dom";
import {
CalendarOutlined,
DashboardOutlined,
LogoutOutlined,
TeamOutlined,
UserOutlined,
} from "@ant-design/icons";
import { useAuth } from "../contexts/AuthContext";
import {Avatar, Dropdown, Layout, Menu} from "antd";
import {Outlet, useLocation, useNavigate} from "react-router-dom";
import {CalendarOutlined, DashboardOutlined, LogoutOutlined, TeamOutlined, UserOutlined,} from "@ant-design/icons";
import {useAuth} from "../contexts/AuthContext";
import useApiService from "../services/apiService.ts";
import { useState } from "react";
import {useState} from "react";
import itestraEventLogo from "../assets/itestra_event_logo.png";

const { Sider, Content, Footer } = Layout;
Expand Down Expand Up @@ -70,27 +64,27 @@ export const AppContainer = () => {
return (
<Layout className="min-h-screen">
<Sider
theme="dark"
className="fixed h-full z-10"
breakpoint="lg"
collapsedWidth="0"
onCollapse={value => setCollapsed(value)}
onBreakpoint={broken => setCollapsed(broken)}
theme="dark"
className="fixed h-full z-10"
breakpoint="lg"
collapsedWidth="0"
onCollapse={value => setCollapsed(value)}
onBreakpoint={broken => setCollapsed(broken)}
>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: 100,
marginTop: 16,
marginBottom: 4,
}}
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: 100,
marginTop: 16,
marginBottom: 4,
}}
>
<img
src={itestraEventLogo}
alt="itestra event planning logo"
style={{ height: "64px" }}
style={{height: "64px"}}
/>
</div>
<Menu
Expand All @@ -102,8 +96,8 @@ export const AppContainer = () => {
/>
{/* User profile at the bottom */}
<div
style={{ position: "absolute", bottom: 0, width: "100%", padding: "24px 0" }}
className="flex flex-col items-center"
style={{position: "absolute", bottom: 0, width: "100%", padding: "24px 0"}}
className="flex flex-col items-center"
>
<Dropdown
menu={{
Expand All @@ -120,17 +114,17 @@ export const AppContainer = () => {
</div>
</Sider>
<Layout
className="flex flex-col min-h-screen"
style={{
marginLeft: collapsed ? 0 : 200,
}}
className="flex flex-col min-h-screen"
style={{
marginLeft: collapsed ? 0 : 200,
}}
>
<Content className="bg-gray-50 flex-1 overflow-auto">
<div className="p-6">
<Outlet />
</div>
</Content>
<Footer className="text-center border-t border-gray-200" style={{ background: "#e6f4ff" }}>
<Footer className="text-center border-t border-gray-200" style={{background: "#e6f4ff"}}>
Event Exchange Platform ©{new Date().getFullYear()}
</Footer>
</Layout>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Breadcrumb as AntBreadcrumb } from "antd";
import { Link } from "react-router-dom";
import {Breadcrumb as AntBreadcrumb} from "antd";
import {Link} from "react-router-dom";

export interface BreadcrumbItem {
path: string;
Expand Down
14 changes: 7 additions & 7 deletions frontend/src/components/ProtectedRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Navigate, useLocation } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
import { Spin } from "antd";
import {Navigate, useLocation} from "react-router-dom";
import {useAuth} from "../contexts/AuthContext";
import {Spin} from "antd";

interface ProtectedRouteProps {
children: React.ReactNode;
Expand All @@ -14,10 +14,10 @@ export function ProtectedRoute({ children }: ProtectedRouteProps) {
return (
<div
style={{
height: "100vh",
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<Spin size="large" />
Expand Down
Loading