From 8a13eec2271df066fd4e41fd79ac1771cf348393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dyl=C4=85g?= Date: Mon, 25 May 2026 14:57:10 +0200 Subject: [PATCH 1/6] =?UTF-8?q?refactor=20komponentu=20do=20tworzenia=20pr?= =?UTF-8?q?ojekt=C3=B3w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 7 + .../dto/project/ProjectCreationRequest.java | 5 +- .../components/CreateProjectForm.view.tsx | 288 ++++++------ .../components/StepBasicInformation.view.tsx | 94 ++-- .../components/StepMilestoneAndRisk.tsx | 418 +++++++++--------- .../project/components/UserAutocomplete.tsx | 174 ++++---- .../src/features/project/project.schema.ts | 9 +- 7 files changed, 494 insertions(+), 501 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..81f5cda7 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(Get-ChildItem -Path \"c:\\\\Users\\\\jandy\\\\OneDrive\\\\Pulpit\\\\6 sem\\\\IO\\\\IO-Project\" -Directory)" + ] + } +} diff --git a/backend/project-manager/src/main/java/pl/edu/agh/project_manager/controller/dto/project/ProjectCreationRequest.java b/backend/project-manager/src/main/java/pl/edu/agh/project_manager/controller/dto/project/ProjectCreationRequest.java index aab2b214..fd6b01c0 100644 --- a/backend/project-manager/src/main/java/pl/edu/agh/project_manager/controller/dto/project/ProjectCreationRequest.java +++ b/backend/project-manager/src/main/java/pl/edu/agh/project_manager/controller/dto/project/ProjectCreationRequest.java @@ -2,7 +2,6 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import pl.edu.agh.project_manager.controller.dto.milestone.MilestoneRequest; import pl.edu.agh.project_manager.controller.dto.project.projectrisk.ProjectRiskRequest; @@ -27,10 +26,8 @@ public record ProjectCreationRequest( UUID projectGroupId, - @NotEmpty(message = "Lista sponsorów nie może być pusta") List sponsors, - @NotEmpty(message = "Lista członków komitetu sterującego nie może być pusta") List committee, @Valid @@ -41,6 +38,8 @@ public record ProjectCreationRequest( ) { public ProjectCreationRequest { if (risks == null || risks.isEmpty()) risks = List.of(); + if (sponsors == null) sponsors = List.of(); + if (committee == null) committee = List.of(); } public ProjectCreationCommand toCommand(UUID creatorId) { diff --git a/frontend/src/features/project/components/CreateProjectForm.view.tsx b/frontend/src/features/project/components/CreateProjectForm.view.tsx index dbd46c50..6b154af6 100644 --- a/frontend/src/features/project/components/CreateProjectForm.view.tsx +++ b/frontend/src/features/project/components/CreateProjectForm.view.tsx @@ -1,164 +1,150 @@ import { useFieldArray, useFormContext } from "react-hook-form"; import type { ProjectCreationRequest } from "../project.types.ts"; -import { useState, useCallback } from "react"; import type { SimpleUserResponse } from "@/features/user-management"; import { UserAutocomplete } from "./UserAutocomplete.tsx"; import { StepBasicInformation } from "./StepBasicInformation.view.tsx"; import { StepMilestonesAndRisks } from "./StepMilestoneAndRisk.tsx"; import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Separator } from "@/components/ui/separator"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; interface CreateProjectViewProps { - onSubmitProject: () => Promise; - isPending: boolean; - groups: { id: string; name: string }[]; - foundSponsors: SimpleUserResponse[]; - foundCommittee: SimpleUserResponse[]; - onSponsorSearch: (query: string) => void; - onCommitteeSearch: (query: string) => void; - message?: string; + onSubmitProject: () => Promise; + isPending: boolean; + groups: { id: string; name: string }[]; + foundSponsors: SimpleUserResponse[]; + foundCommittee: SimpleUserResponse[]; + onSponsorSearch: (query: string) => void; + onCommitteeSearch: (query: string) => void; } export const CreateProjectView = ({ - onSubmitProject, - isPending, - groups, - foundSponsors, - foundCommittee, - onSponsorSearch, - onCommitteeSearch, - message - }: CreateProjectViewProps) => { - const { - register, - control, - formState: { errors, isValid }, - clearErrors, - watch, - setValue, - getValues, - } = useFormContext(); - - const milestones = watch("milestones"); - - const { - fields: riskFields, - append: appendRisk, - remove: removeRisk, - } = useFieldArray({ - control, - name: "risks", - }); - - const { - fields: milestonesFields, - append: appendMilestone, - remove: removeMilestone, - } = useFieldArray({ - control, - name: "milestones", - }); - - const [usersById, setUsersById] = useState>({}); - - const rememberUser = useCallback((user: SimpleUserResponse) => { - setUsersById((prev) => ({ ...prev, [user.id]: user })); - }, []); - - return ( -
-

Utwórz Nowy Projekt

- - {message && ( -
- {message} -
- )} - -
{ e.preventDefault(); onSubmitProject(); }}> - -
- - -
-
- - - {errors.startDate?.message &&

{errors.startDate.message as string}

} -
-
- - - {errors.endDate?.message &&

{errors.endDate.message as string}

} -
-
-
- -
-

Uczestnicy Główni

- -
- - {errors.sponsors?.message &&

{errors.sponsors.message}

} -
- -
- - {errors.committee?.message &&

{errors.committee.message}

} -
-
- -
- -
- -
- + onSubmitProject, + isPending, + groups, + foundSponsors, + foundCommittee, + onSponsorSearch, + onCommitteeSearch, +}: CreateProjectViewProps) => { + const { + register, + control, + formState: { errors, isValid }, + watch, + setValue, + } = useFormContext(); + + const milestones = watch("milestones"); + + const { + fields: riskFields, + append: appendRisk, + remove: removeRisk, + } = useFieldArray({ control, name: "risks" }); + + const { + fields: milestonesFields, + append: appendMilestone, + remove: removeMilestone, + } = useFieldArray({ control, name: "milestones" }); + + return ( +
+ + + Utwórz Nowy Projekt + + + { + e.preventDefault(); + onSubmitProject(); + }} + > + + +
+
+ + + {errors.startDate?.message && ( +

{errors.startDate.message as string}

+ )} +
+
+ + + {errors.endDate?.message && ( +

{errors.endDate.message as string}

+ )} +
+
+ + + +
+

Uczestnicy Główni

+ + +
+ + + +
+ +
+ +
+ +
+ +
+
- -
- ); -}; \ No newline at end of file + ); +}; diff --git a/frontend/src/features/project/components/StepBasicInformation.view.tsx b/frontend/src/features/project/components/StepBasicInformation.view.tsx index e2f8fdd7..1dfe528c 100644 --- a/frontend/src/features/project/components/StepBasicInformation.view.tsx +++ b/frontend/src/features/project/components/StepBasicInformation.view.tsx @@ -3,8 +3,9 @@ import type { FieldErrors, UseFormRegister } from "react-hook-form"; import type { ProjectCreationRequest } from "../project.types"; import { ChevronDownIcon, CheckIcon } from "lucide-react"; import { cn } from "@/lib/utils"; - -// Import Twoich komponentów DropdownMenu +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Label } from "@/components/ui/label"; import { DropdownMenu, DropdownMenuContent, @@ -18,59 +19,44 @@ interface StepBasicInformationViewProps { groups: { id: string; name: string }[]; } -export const StepBasicInformation = ({ - register, - errors, - groups +export const StepBasicInformation = ({ + register, + errors, + groups, }: StepBasicInformationViewProps) => { const { control, setValue } = useFormContext(); return (
- {/* --- NAZWA PROJEKTU --- */} -
- - + + {errors.title && ( - {errors.title.message} +

{errors.title.message}

)}
- {/* --- OPIS PROJEKTU --- */} -
- -