diff --git a/kabinizer-back-end/kabinizer-api/Controllers/DrawController.cs b/kabinizer-back-end/kabinizer-api/Controllers/DrawController.cs index 7f54a1f..a91355b 100644 --- a/kabinizer-back-end/kabinizer-api/Controllers/DrawController.cs +++ b/kabinizer-back-end/kabinizer-api/Controllers/DrawController.cs @@ -43,16 +43,35 @@ public async Task> GetDraw([Required] Guid drawId) } [HttpPost] - public async Task> CreateDraw([Required] CreateDrawDto draw) + public async Task> CreateDraw([Required] CreateDrawDto draw) { var createdDraw = await drawService.CreateDraw(draw); - return CreatedAtAction(nameof(GetDraws), new { drawId = createdDraw.Id }, createdDraw); + return Ok(ReadDrawDto.FromEntity(createdDraw)); } - [HttpDelete("{drawId:guid}")] + + + + [HttpPut] + + public IActionResult UpdateDraw([Required] UpdateDrawDto draw) + { + try + { + drawService.UpdateDraw(draw); + return new NoContentResult(); + } + catch (Exception) + { + return new NotFoundResult(); + } + } + + [HttpDelete] public async Task DeleteDraw([Required] Guid drawId) { await drawService.DeleteDraw(drawId); return NoContent(); } + } \ No newline at end of file diff --git a/kabinizer-back-end/kabinizer-api/Dtos/Draw/ReadDrawDto.cs b/kabinizer-back-end/kabinizer-api/Dtos/Draw/ReadDrawDto.cs new file mode 100644 index 0000000..913af40 --- /dev/null +++ b/kabinizer-back-end/kabinizer-api/Dtos/Draw/ReadDrawDto.cs @@ -0,0 +1,31 @@ +using kabinizer_data.Entities; + +namespace kabinizer_api.Dtos.Draw; + +public class ReadDrawDto +{ + public DateTime DeadlineStart { get; set; } + public DateTime DeadlineEnd { get; set; } + public required string Title { get; set; } + public required List DrawPeriods { get; set; } + public bool IsSpecial { get; set; } + + internal static object? FromEntity(DrawEntity createdDraw) + + { + return new ReadDrawDto + { + DeadlineStart = createdDraw.DeadlineStart, + DeadlineEnd = createdDraw.DeadlineEnd, + Title = createdDraw.Title, + DrawPeriods = createdDraw.Periods.Select(p => new DrawPeriod + { + Start = p.PeriodStart, + End = p.PeriodEnd, + Title = p.Title + }).ToList(), + IsSpecial = createdDraw.IsSpecial + }; + } + +} diff --git a/kabinizer-back-end/kabinizer-api/Dtos/Draw/UpdateDrawDto.cs b/kabinizer-back-end/kabinizer-api/Dtos/Draw/UpdateDrawDto.cs new file mode 100644 index 0000000..7d2b534 --- /dev/null +++ b/kabinizer-back-end/kabinizer-api/Dtos/Draw/UpdateDrawDto.cs @@ -0,0 +1,12 @@ +namespace kabinizer_api.Dtos.Draw; + +public class UpdateDrawDto +{ + public required string Id { get; set; } + public DateTime Start { get; set; } + public DateTime End { get; set; } + public required string Title { get; set; } + public bool IsSpecial { get; set; } + + public List? Periods { get; set; } +} diff --git a/kabinizer-back-end/kabinizer-api/Dtos/Draw/UpdatePeriod.cs b/kabinizer-back-end/kabinizer-api/Dtos/Draw/UpdatePeriod.cs new file mode 100644 index 0000000..3d1263f --- /dev/null +++ b/kabinizer-back-end/kabinizer-api/Dtos/Draw/UpdatePeriod.cs @@ -0,0 +1,11 @@ +namespace kabinizer_api.Dtos.Draw; + +public class UpdatePeriod { + + public required string Id { get; set; } + public DateTime PeriodStart { get; set; } + public DateTime PeriodEnd { get; set; } + public required string Title { get; set; } + + public required string DrawId { get; set; } +} \ No newline at end of file diff --git a/kabinizer-back-end/kabinizer-api/Services/Draw/DrawService.cs b/kabinizer-back-end/kabinizer-api/Services/Draw/DrawService.cs index 973b6a0..65ecf8c 100644 --- a/kabinizer-back-end/kabinizer-api/Services/Draw/DrawService.cs +++ b/kabinizer-back-end/kabinizer-api/Services/Draw/DrawService.cs @@ -40,9 +40,17 @@ public async Task GetDraw(Guid drawId) /** * Update a draw */ - public Task UpdateDraw(Guid drawId) + public void UpdateDraw(UpdateDrawDto draw) { - throw new NotImplementedException(); + var drawToUpdate = entityContext.Draws.Include(d => d.Periods).FirstOrDefault(d => d.Id == Guid.Parse(draw.Id)) + ?? throw new Exception("Draw not found"); + + drawToUpdate.DeadlineStart = draw.Start; + drawToUpdate.DeadlineEnd = draw.End; + drawToUpdate.Title = draw.Title; + drawToUpdate.IsSpecial = draw.IsSpecial; + drawToUpdate.Periods = periodService.UpdatePeriods(drawToUpdate.Id, draw.Periods); + entityContext.SaveChanges(); } /** @@ -102,4 +110,4 @@ public async Task DeleteDraw(Guid drawId) .ToListAsync(); return draws.Select(Model.Draw.FromObject); } -} \ No newline at end of file +} diff --git a/kabinizer-back-end/kabinizer-api/Services/Period/PeriodService.cs b/kabinizer-back-end/kabinizer-api/Services/Period/PeriodService.cs index 85e9bcf..2e27a25 100644 --- a/kabinizer-back-end/kabinizer-api/Services/Period/PeriodService.cs +++ b/kabinizer-back-end/kabinizer-api/Services/Period/PeriodService.cs @@ -24,6 +24,25 @@ public List CreatePeriods(Guid drawId, List drawPeriod return periodEntities; } + internal List? UpdatePeriods(Guid id, List? periods) + { + ArgumentNullException.ThrowIfNull(periods); + + List periodEntities = new(); + foreach (UpdatePeriod updatePeriod in periods) { + PeriodEntity periodEntity = new() + { + PeriodStart = updatePeriod.PeriodStart, + PeriodEnd = updatePeriod.PeriodEnd, + Title = updatePeriod.Title, + DrawId = Guid.Parse(updatePeriod.DrawId) + }; + periodEntities.Add(periodEntity); + } + return periodEntities; + } + + private PeriodEntity CreateSinglePeriod(DrawPeriod drawPeriod, Guid drawId) { if (drawPeriod.Title?.Trim().Length == 0) @@ -80,4 +99,4 @@ public async Task> GetPastPeriods() => await entityContext.Periods.Where(p => p.PeriodEnd < DateTime.Now).ToListAsync(); public async Task> GetAllPeriods() => await entityContext.Periods.ToListAsync(); -} \ No newline at end of file +} diff --git a/kabinizer-back-end/kabinizer-data/Entities/DrawEntity.cs b/kabinizer-back-end/kabinizer-data/Entities/DrawEntity.cs index ca6eaa8..b81f761 100644 --- a/kabinizer-back-end/kabinizer-data/Entities/DrawEntity.cs +++ b/kabinizer-back-end/kabinizer-data/Entities/DrawEntity.cs @@ -1,10 +1,12 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; namespace kabinizer_data.Entities; [Table("Draw")] public class DrawEntity { + [Key] public Guid Id { get; set; } public DateTime DeadlineStart { get; set; } public DateTime DeadlineEnd { get; set; } diff --git a/kabinizer-front-end/api/index.ts b/kabinizer-front-end/api/index.ts index 19eb320..01fec60 100644 --- a/kabinizer-front-end/api/index.ts +++ b/kabinizer-front-end/api/index.ts @@ -7,16 +7,15 @@ export { CancelablePromise, CancelError } from "./core/CancelablePromise"; export { OpenAPI } from "./core/OpenAPI"; export type { OpenAPIConfig } from "./core/OpenAPI"; -export type { BookingRequestDto } from "./models/BookingRequestDto"; +export type { BookingRequest } from "./models/BookingRequest"; export type { CreateBookingRequestDto } from "./models/CreateBookingRequestDto"; export type { CreateDrawDto } from "./models/CreateDrawDto"; export type { Draw } from "./models/Draw"; -export type { DrawEntity } from "./models/DrawEntity"; export type { DrawPeriod } from "./models/DrawPeriod"; export type { Period } from "./models/Period"; -export type { PeriodEntity } from "./models/PeriodEntity"; -export type { ProblemDetails } from "./models/ProblemDetails"; -export type { ReadPeriodDto } from "./models/ReadPeriodDto"; +export type { UpdateDrawDto } from "./models/UpdateDrawDto"; +export type { UpdatePeriod } from "./models/UpdatePeriod"; +export type { User } from "./models/User"; export { BookingRequestService } from "./services/BookingRequestService"; export { DrawService } from "./services/DrawService"; diff --git a/kabinizer-front-end/api/models/BookingRequest.ts b/kabinizer-front-end/api/models/BookingRequest.ts new file mode 100644 index 0000000..d8d33a4 --- /dev/null +++ b/kabinizer-front-end/api/models/BookingRequest.ts @@ -0,0 +1,13 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { Period } from "./Period"; +import type { User } from "./User"; + +export type BookingRequest = { + bookingRequestId?: string; + period?: Period; + user?: User; +}; diff --git a/kabinizer-front-end/api/models/BookingRequestDto.ts b/kabinizer-front-end/api/models/BookingRequestDto.ts deleted file mode 100644 index c47cca3..0000000 --- a/kabinizer-front-end/api/models/BookingRequestDto.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -export type BookingRequestDto = { - id?: string; - userId?: string; - periodId?: string; - createdDate?: string; - createdBy?: string; - updatedDate?: string | null; - updatedBy?: string | null; -}; diff --git a/kabinizer-front-end/api/models/DrawEntity.ts b/kabinizer-front-end/api/models/DrawEntity.ts deleted file mode 100644 index 09f91f6..0000000 --- a/kabinizer-front-end/api/models/DrawEntity.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -import type { PeriodEntity } from './PeriodEntity'; - -export type DrawEntity = { - id?: string; - deadlineStart?: string; - deadlineEnd?: string; - title?: string | null; - isSpecial?: boolean; - periods?: Array | null; -}; - diff --git a/kabinizer-front-end/api/models/PeriodEntity.ts b/kabinizer-front-end/api/models/PeriodEntity.ts deleted file mode 100644 index 46bda62..0000000 --- a/kabinizer-front-end/api/models/PeriodEntity.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -import type { DrawEntity } from './DrawEntity'; - -export type PeriodEntity = { - id?: string; - periodStart?: string; - periodEnd?: string; - title?: string | null; - drawId?: string; - draw?: DrawEntity; -}; - diff --git a/kabinizer-front-end/api/models/ReadPeriodDto.ts b/kabinizer-front-end/api/models/ReadPeriodDto.ts deleted file mode 100644 index f29a950..0000000 --- a/kabinizer-front-end/api/models/ReadPeriodDto.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -export type ReadPeriodDto = { - id?: string; - startDate?: string; - endDate?: string; - title?: string | null; -}; - diff --git a/kabinizer-front-end/api/models/UpdateDrawDto.ts b/kabinizer-front-end/api/models/UpdateDrawDto.ts new file mode 100644 index 0000000..ae6598b --- /dev/null +++ b/kabinizer-front-end/api/models/UpdateDrawDto.ts @@ -0,0 +1,14 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { UpdatePeriod } from "./UpdatePeriod"; + +export type UpdateDrawDto = { + id?: string | null; + end?: string; + title?: string | null; + isSpecial?: boolean; + periods?: Array | null; +}; diff --git a/kabinizer-front-end/api/models/UpdatePeriod.ts b/kabinizer-front-end/api/models/UpdatePeriod.ts new file mode 100644 index 0000000..06b8471 --- /dev/null +++ b/kabinizer-front-end/api/models/UpdatePeriod.ts @@ -0,0 +1,12 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type UpdatePeriod = { + id?: string | null; + periodStart?: string; + periodEnd?: string; + title?: string | null; + drawId?: string | null; +}; diff --git a/kabinizer-front-end/api/models/ProblemDetails.ts b/kabinizer-front-end/api/models/User.ts similarity index 67% rename from kabinizer-front-end/api/models/ProblemDetails.ts rename to kabinizer-front-end/api/models/User.ts index d120301..60f8c3a 100644 --- a/kabinizer-front-end/api/models/ProblemDetails.ts +++ b/kabinizer-front-end/api/models/User.ts @@ -3,4 +3,7 @@ /* tslint:disable */ /* eslint-disable */ -export type ProblemDetails = Record; +export type User = { + id?: string; + name?: string | null; +}; diff --git a/kabinizer-front-end/api/services/BookingRequestService.ts b/kabinizer-front-end/api/services/BookingRequestService.ts index f7ce1ff..6afd577 100644 --- a/kabinizer-front-end/api/services/BookingRequestService.ts +++ b/kabinizer-front-end/api/services/BookingRequestService.ts @@ -2,7 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { BookingRequestDto } from "../models/BookingRequestDto"; +import type { BookingRequest } from "../models/BookingRequest"; import type { CreateBookingRequestDto } from "../models/CreateBookingRequestDto"; import type { CancelablePromise } from "../core/CancelablePromise"; @@ -11,116 +11,47 @@ import { request as __request } from "../core/request"; export class BookingRequestService { /** - * @param id - * @returns BookingRequestDto Success + * @returns BookingRequest Success * @throws ApiError */ - public static getApiBookingRequest( - id: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: "GET", - url: "/api/BookingRequest/{id}", - path: { - id: id, - }, - errors: { - 404: `Not Found`, - }, - }); - } - - /** - * @returns BookingRequestDto Success - * @throws ApiError - */ - public static getApiBookingRequest1(): CancelablePromise< - Array + public static getApiBookingRequest(): CancelablePromise< + Array > { return __request(OpenAPI, { method: "GET", url: "/api/BookingRequest", - errors: { - 404: `Not Found`, - }, }); } /** * @param requestBody - * @returns BookingRequestDto Success + * @returns any Success * @throws ApiError */ public static postApiBookingRequest( requestBody: Array, - ): CancelablePromise { + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/BookingRequest", body: requestBody, mediaType: "application/json", - errors: { - 400: `Bad Request`, - }, }); } /** * @param requestBody - * @returns string Success + * @returns boolean Success * @throws ApiError */ public static deleteApiBookingRequest( requestBody: Array, - ): CancelablePromise { + ): CancelablePromise { return __request(OpenAPI, { method: "DELETE", url: "/api/BookingRequest", body: requestBody, mediaType: "application/json", - errors: { - 400: `Bad Request`, - }, - }); - } - - /** - * @param userId - * @returns BookingRequestDto Success - * @throws ApiError - */ - public static getApiBookingRequestUser( - userId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/BookingRequest/user/{userId}", - path: { - userId: userId, - }, - errors: { - 404: `Not Found`, - }, - }); - } - - /** - * @param periodId - * @returns BookingRequestDto Success - * @throws ApiError - */ - public static getApiBookingRequestPeriod( - periodId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/BookingRequest/period/{periodId}", - path: { - periodId: periodId, - }, - errors: { - 404: `Not Found`, - }, }); } diff --git a/kabinizer-front-end/api/services/DrawService.ts b/kabinizer-front-end/api/services/DrawService.ts index c0a8d15..8dc3882 100644 --- a/kabinizer-front-end/api/services/DrawService.ts +++ b/kabinizer-front-end/api/services/DrawService.ts @@ -4,7 +4,7 @@ /* eslint-disable */ import type { CreateDrawDto } from "../models/CreateDrawDto"; import type { Draw } from "../models/Draw"; -import type { DrawEntity } from "../models/DrawEntity"; +import type { UpdateDrawDto } from "../models/UpdateDrawDto"; import type { CancelablePromise } from "../core/CancelablePromise"; import { OpenAPI } from "../core/OpenAPI"; @@ -24,12 +24,12 @@ export class DrawService { /** * @param requestBody - * @returns DrawEntity Success + * @returns any Success * @throws ApiError */ public static postApiDraw( requestBody: CreateDrawDto, - ): CancelablePromise { + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/Draw", @@ -39,65 +39,31 @@ export class DrawService { } /** - * @returns Draw Success - * @throws ApiError - */ - public static getApiDrawCurrent(): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/Draw/current", - }); - } - - /** - * @returns Draw Success - * @throws ApiError - */ - public static getApiDrawUpcoming(): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/Draw/upcoming", - }); - } - - /** - * @returns Draw Success - * @throws ApiError - */ - public static getApiDrawPast(): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/Draw/past", - }); - } - - /** - * @param drawId - * @returns DrawEntity Success + * @param id + * @returns any Success * @throws ApiError */ - public static getApiDraw1(drawId: string): CancelablePromise { + public static deleteApiDraw(id: string): CancelablePromise { return __request(OpenAPI, { - method: "GET", - url: "/api/Draw/{drawId}", - path: { - drawId: drawId, + method: "DELETE", + url: "/api/Draw", + query: { + drawId: id, }, }); } /** - * @param drawId + * @param requestBody * @returns any Success * @throws ApiError */ - public static deleteApiDraw(drawId: string): CancelablePromise { + public static putApiDraw(requestBody: UpdateDrawDto): CancelablePromise { return __request(OpenAPI, { - method: "DELETE", - url: "/api/Draw/{drawId}", - path: { - drawId: drawId, - }, + method: "PUT", + url: "/api/Draw", + body: requestBody, + mediaType: "application/json", }); } } diff --git a/kabinizer-front-end/api/services/PeriodService.ts b/kabinizer-front-end/api/services/PeriodService.ts index 2ce4720..65f9352 100644 --- a/kabinizer-front-end/api/services/PeriodService.ts +++ b/kabinizer-front-end/api/services/PeriodService.ts @@ -3,86 +3,20 @@ /* tslint:disable */ /* eslint-disable */ import type { Period } from "../models/Period"; -import type { ReadPeriodDto } from "../models/ReadPeriodDto"; import type { CancelablePromise } from "../core/CancelablePromise"; import { OpenAPI } from "../core/OpenAPI"; import { request as __request } from "../core/request"; export class PeriodService { - /** - * @param periodId - * @returns ReadPeriodDto Success - * @throws ApiError - */ - public static getApiPeriod( - periodId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: "GET", - url: "/api/Period/{periodId}", - path: { - periodId: periodId, - }, - errors: { - 404: `Not Found`, - }, - }); - } - /** * @returns Period Success * @throws ApiError */ - public static getApiPeriod1(): CancelablePromise> { + public static getApiPeriod(): CancelablePromise> { return __request(OpenAPI, { method: "GET", url: "/api/Period", - errors: { - 404: `Not Found`, - }, - }); - } - - /** - * @returns Period Success - * @throws ApiError - */ - public static getApiPeriodUpcoming(): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/Period/upcoming", - errors: { - 404: `Not Found`, - }, - }); - } - - /** - * @returns Period Success - * @throws ApiError - */ - public static getApiPeriodPast(): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/Period/past", - errors: { - 404: `Not Found`, - }, - }); - } - - /** - * @returns Period Success - * @throws ApiError - */ - public static getApiPeriodAll(): CancelablePromise> { - return __request(OpenAPI, { - method: "GET", - url: "/api/Period/all", - errors: { - 404: `Not Found`, - }, }); } } diff --git a/kabinizer-front-end/package.json b/kabinizer-front-end/package.json index 54eed9d..0f37480 100644 --- a/kabinizer-front-end/package.json +++ b/kabinizer-front-end/package.json @@ -17,8 +17,11 @@ "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-navigation-menu": "^1.1.4", "@radix-ui/react-slot": "^1.0.2", + "@tanstack/react-form": "^0.19.4", + "@tanstack/react-query": "^5.32.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", + "date-fns": "^3.6.0", "invariant": "^2.2.4", "jotai": "^2.4.3", "lucide-react": "^0.312.0", @@ -30,7 +33,9 @@ "react-query": "^3.39.3", "sass": "^1.68.0", "tailwind-merge": "^2.2.0", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "uuid": "^9.0.1", + "uuid4": "^2.0.3" }, "devDependencies": { "@azure/msal-browser": "^3.6.0", diff --git a/kabinizer-front-end/src/components/Button.tsx b/kabinizer-front-end/src/components/Button.tsx index 8540ef4..db2d7fe 100644 --- a/kabinizer-front-end/src/components/Button.tsx +++ b/kabinizer-front-end/src/components/Button.tsx @@ -21,7 +21,7 @@ const Button = ({ large: "text-lg h-10", }; - const classes = `${className} ${sizes[size]} flex w-full items-center justify-center rounded-full bg-[#354A71] px-4 font-poppins text-white hover:bg-blue-700`; + const classes = `${className} ${sizes[size]} flex w-full items-center justify-center rounded bg-[#354A71] px-4 font-poppins text-white hover:bg-blue-700`; if (href !== undefined) { return ( diff --git a/kabinizer-front-end/src/components/DeleteButtonIcon.tsx b/kabinizer-front-end/src/components/DeleteButtonIcon.tsx new file mode 100644 index 0000000..226c97c --- /dev/null +++ b/kabinizer-front-end/src/components/DeleteButtonIcon.tsx @@ -0,0 +1,16 @@ +const DeleteButtonIcon = () => { + return ( + + + + ); +}; + +export default DeleteButtonIcon; diff --git a/kabinizer-front-end/src/components/DeleteDraw.tsx b/kabinizer-front-end/src/components/DeleteDraw.tsx new file mode 100644 index 0000000..9789c46 --- /dev/null +++ b/kabinizer-front-end/src/components/DeleteDraw.tsx @@ -0,0 +1,64 @@ +import { format } from "date-fns"; +import { DrawService } from "../../api/services/DrawService"; +import { Draw } from "../../api/models/Draw"; +import DeleteButtonIcon from "../components/DeleteButtonIcon"; +import EditPeriodView from "../components/EditPeriodView"; +import { useState } from "react"; +import Editicon from "../components/EditIcon"; + +const DeleteDraw = ({ draws }: { draws: Array }) => { + const deleteDrawPeriods = (id: string | undefined) => { + if (!id) return; + DrawService.deleteApiDraw(id); + }; + const [youWantToDoSomeEditing, setYouWantToDoSomeEditing] = useState(false); + + const formatDate = (date: string | undefined) => { + if (!date) return ""; + + return format(new Date(date), "dd-MM-yyyy"); + }; + + const wantToEdit = () => { + setYouWantToDoSomeEditing(!youWantToDoSomeEditing); + }; + + return ( +
+
+

Slett eller endre trekning

+
+ {draws?.map((draw) => ( +
+
+ +
+

{draw?.title}

+ {draw?.periods?.map((period) => ( +
+ {`Periode ${formatDate(period?.periodStart)} - + ${formatDate(period?.periodEnd)}`} +
+ ))} +
+ + +
+ {youWantToDoSomeEditing && } +
+ ))} +
+ ); +}; +export default DeleteDraw; diff --git a/kabinizer-front-end/src/components/EditIcon.tsx b/kabinizer-front-end/src/components/EditIcon.tsx new file mode 100644 index 0000000..ac7629c --- /dev/null +++ b/kabinizer-front-end/src/components/EditIcon.tsx @@ -0,0 +1,16 @@ +const EditIcon = () => { + return ( + + + + ); +}; + +export default EditIcon; diff --git a/kabinizer-front-end/src/components/EditPeriodView.tsx b/kabinizer-front-end/src/components/EditPeriodView.tsx new file mode 100644 index 0000000..d6f8d18 --- /dev/null +++ b/kabinizer-front-end/src/components/EditPeriodView.tsx @@ -0,0 +1,325 @@ +import { DrawService } from "../../api/services/DrawService"; +import { format } from "date-fns"; +import { useForm, FieldApi } from "@tanstack/react-form"; +import { v4 as uuid } from "uuid"; + +function FieldInfo({ field }: { field: FieldApi }) { + return ( +
+ {field.state.meta.touchedErrors ? ( + {field.state.meta.touchedErrors} + ) : null} +
+ ); +} + +const EditPeriodView = (props: { draw: object }) => { + const { draw } = props; + + const formatStupidDate = (date: string | undefined) => { + if (!date) return ""; + + return format(new Date(date), "yyyy-MM-dd"); + }; + + const form = useForm({ + defaultValues: { + draw: draw, + }, + onSubmit: async ({ value }) => { + value?.draw?.periods.forEach((period) => { + period.drawId = draw.id; + period.id = period.id || uuid(); + }); + + try { + await DrawService.putApiDraw(value.draw); + } catch (error) { + console.error(error); + } + }, + }); + + const handleUpdatePeriods = (periods) => { + periods.pushValue({ + periodStart: "", + periodEnd: "", + title: "", + }); + }; + + return ( +
+
+
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + + !value ? "A title is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + children={(field) => ( + <> + field.handleChange(e.target.value)} + value={field.state.value} + onBlur={field.handleBlur} + name={field.name} + /> + + + )} + /> +
+ +
+ + + !value ? "A deadline is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + children={(field) => ( + <> + field.handleChange(e.target.value)} + value={formatStupidDate(field.state.value)} + onBlur={field.handleBlur} + name={field.name} + type="date" + /> + + + )} + /> +
+
+ + ( + <> + field.handleChange(e.target.checked)} + onBlur={field.handleBlur} + name={field.name} + type="checkbox" + checked={field.state.value} + /> + + + )} + /> +
+
+
+
+ + {(periods) => { + return ( +
+ {periods?.state?.value?.map((_, i) => { + return ( +
+ + !value ? "A start date is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => + setTimeout(resolve, 1000), + ); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + > + {(periods) => { + return ( +
+ + + periods.handleChange(e.target.value) + } + value={formatStupidDate(periods.state.value)} + onBlur={periods.handleBlur} + name={periods.name} + type="date" + /> + +
+ ); + }} +
+ + + !value ? "An enddate is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => + setTimeout(resolve, 1000), + ); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + > + {(periods) => { + return ( +
+ + + periods.handleChange(e.target.value) + } + value={formatStupidDate(periods.state.value)} + onBlur={periods.handleBlur} + name={periods.name} + type="date" + /> + +
+ ); + }} +
+ + {(periods) => { + return ( +
+ + + periods.handleChange(e.target.value) + } + value={periods.state.value} + onBlur={periods.handleBlur} + name={periods.name} + /> + +
+ ); + }} +
+ + {(periods) => { + return ( + + ); + }} + + + {(periods) => { + return ( + + ); + }} + +
+
+
+
+ ); + })} +
+ +
+
+ ); + }} +
+ + [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( +
+
+ +
+
+ +
+
+ )} + /> + +
+
+ ); +}; + +export default EditPeriodView; diff --git a/kabinizer-front-end/src/components/NewPeriodView.tsx b/kabinizer-front-end/src/components/NewPeriodView.tsx new file mode 100644 index 0000000..7c4223e --- /dev/null +++ b/kabinizer-front-end/src/components/NewPeriodView.tsx @@ -0,0 +1,285 @@ +import { CreateDrawDto } from "../../api"; +import { DrawService } from "../../api/services/DrawService"; +import { createFormFactory, FieldApi } from "@tanstack/react-form"; + +function FieldInfo({ field }: { field: FieldApi }) { + return ( +
+ {field.state.meta.touchedErrors ? ( + {field.state.meta.touchedErrors} + ) : null} +
+ ); +} + +const NewPeriodView = () => { + const formFactory = createFormFactory({ + deadlineEnd: "", + title: "", + isSpecial: false, + drawPeriods: [{ start: "", end: "", title: "" }], + }); + + const form = formFactory.useForm({ + onSubmit: async (values) => { + console.log("asdf", values); + try { + await DrawService.postApiDraw(values.value); + } catch (error) { + console.error(error); + } + }, + }); + + return ( +
+
+
{ + e.preventDefault(); + e.stopPropagation(); + form.handleSubmit(); + }} + > +
+ + + !value ? "A title is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + children={(field) => ( + <> + field.handleChange(e.target.value)} + value={field.state.value} + onBlur={field.handleBlur} + name={field.name} + /> + + + )} + /> +
+ +
+ + + !value ? "A deadline is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + children={(field) => ( + <> + field.handleChange(e.target.value)} + value={field.state.value} + onBlur={field.handleBlur} + name={field.name} + type="date" + /> + + + )} + /> +
+
+ + ( + <> + field.handleChange(e.target.checked)} + onBlur={field.handleBlur} + name={field.name} + type="checkbox" + checked={field.state.value} + /> + + + )} + /> +
+
+
+
+ + {(drawPeriods) => { + return ( +
+ {drawPeriods?.state?.value?.map((_, i) => { + return ( +
+ + !value ? "A start date is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => + setTimeout(resolve, 1000), + ); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + > + {(drawPeriods) => { + return ( +
+ + + drawPeriods.handleChange(e.target.value) + } + value={drawPeriods.state.value} + onBlur={drawPeriods.handleBlur} + name={drawPeriods.name} + type="date" + /> + +
+ ); + }} +
+ + !value ? "An enddate is required" : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => + setTimeout(resolve, 1000), + ); + return ( + value.includes("error") && + 'No "error" allowed in title name' + ); + }, + }} + > + {(drawPeriods) => { + return ( +
+ + + drawPeriods.handleChange(e.target.value) + } + value={drawPeriods.state.value} + onBlur={drawPeriods.handleBlur} + name={drawPeriods.name} + type="date" + /> + +
+ ); + }} +
+ + {(drawPeriods) => { + return ( +
+ + + drawPeriods.handleChange(e.target.value) + } + value={drawPeriods.state.value} + onBlur={drawPeriods.handleBlur} + name={drawPeriods.name} + /> + +
+ ); + }} +
+
+
+
+
+ ); + })} +
+ +
+
+ ); + }} +
+ + [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( +
+
+ +
+
+ +
+
+ )} + /> + +
+
+ ); +}; + +export default NewPeriodView; diff --git a/kabinizer-front-end/src/pages/admin/index.tsx b/kabinizer-front-end/src/pages/admin/index.tsx index 628a0a3..afb4ed8 100644 --- a/kabinizer-front-end/src/pages/admin/index.tsx +++ b/kabinizer-front-end/src/pages/admin/index.tsx @@ -1,8 +1,11 @@ -import { useMutation } from "react-query"; +import { useMutation, useQuery } from "react-query"; import Button from "../../components/Button"; import { BookingRequestService } from "../../../api"; import useUser from "../../hooks/useUser"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; +import NewPeriodView from "../../components/NewPeriodView"; +import { DrawService } from "../../../api/services/DrawService"; +import DeleteDraw from "../../components/DeleteDraw"; const Admin = () => { const { isAdmin } = useUser(); @@ -21,6 +24,11 @@ const Admin = () => { }, }, ); + const [showNewPeriodView, setShowNewPeriodView] = useState(false); + + const generateNewPeriod = () => { + setShowNewPeriodView(!showNewPeriodView); + }; useEffect(() => { if (!isAdmin) { @@ -28,17 +36,32 @@ const Admin = () => { } }, [isAdmin]); + const { data: draws = [], isLoading } = useQuery(["getApiDraw"], () => + DrawService.getApiDraw(), + ); + return (
-
-
+
+
-

Download selected periods

+
+

+ Last ned perioder +

+
+
+ +
+ {showNewPeriodView && } + {!isLoading && }
); diff --git a/kabinizer-front-end/src/pages/home/index.tsx b/kabinizer-front-end/src/pages/home/index.tsx index bbb3f84..c65a6cc 100644 --- a/kabinizer-front-end/src/pages/home/index.tsx +++ b/kabinizer-front-end/src/pages/home/index.tsx @@ -19,7 +19,7 @@ const Welcome = () => {

Velkommen til Tjørhomfjellet

-

+

I Miles Stavanger/Haugesund har vi tilgang til en flott firmahytte på Tjørhomfjellet i Sirdal, kun 1,5 time fra Stavanger. Her kan du ta med familie og venner og nyte alle årstider 😀 @@ -54,10 +54,10 @@ const Location = () => {

-

+

Odden 7D, 4443 Tjørhom

-

+

Kjør inn til Tjørhom fjellet og ta første vei til høyre. Følg veien helt til endes. (du passerer stolheisen på venstre side) Hytten ligger på nederste rad, merket med Miles skilt utenfor @@ -95,7 +95,7 @@ const Activeties = () => {

Vinter aktiviteter

-
    +
    • Alpinanlegg med stolheis, tallerkenheis og tautrekk
    • Langrennsløyper
    • Opplyst akebakke
    • @@ -106,7 +106,7 @@ const Activeties = () => {

      Sommer, vår, høst

      -
        +
        • Vannpark
        • Klatrepark
        • Sommerheis
        • @@ -142,7 +142,7 @@ const ImportantInformation = () => {

          Hva du må ta med

          -
            +
            • Sengetøy
            • Håndklær
            • Kjøkkenhåndklær
            • @@ -152,7 +152,7 @@ const ImportantInformation = () => {

              Regler

              -
                +
                • Firbente venner får lov til å bli med på hytta, men de får ikke være i sofa/senger! diff --git a/kabinizer-front-end/src/utils/calendar.ts b/kabinizer-front-end/src/utils/calendar.ts index 5e1808e..24e9a5a 100644 --- a/kabinizer-front-end/src/utils/calendar.ts +++ b/kabinizer-front-end/src/utils/calendar.ts @@ -121,7 +121,6 @@ export const getMonthsMap = (data: Option[]): MonthMapType => { monthsMap[month][Number(week)] = weeksMap[week]; } } - return monthsMap; };