diff --git a/backend/api/delete_event.go b/backend/api/delete_event.go new file mode 100644 index 0000000..586eac4 --- /dev/null +++ b/backend/api/delete_event.go @@ -0,0 +1,33 @@ +package api + +import ( + "context" + "log" + "net/http" + + "fr.latosa-escrima/api/core" +) + +func HandleDeleteEvent(w http.ResponseWriter, r *http.Request) { + uuid := r.PathValue("event_uuid") + var event core.Event + res, err := core.DB.NewDelete(). + Model(&event). + Where("id = ?", uuid). + Returning("*"). + Exec(context.Background()) + if err != nil { + core.JSONError{ + Status: core.Error, + Message: err.Error(), + }.Respond(w, http.StatusInternalServerError) + return + } + log.Println(res) + + core.JSONSuccess{ + Status: core.Success, + Message: "Event deleted.", + }.Respond(w, http.StatusOK) +} + diff --git a/backend/api/event.go b/backend/api/event.go deleted file mode 100644 index 20e3869..0000000 --- a/backend/api/event.go +++ /dev/null @@ -1,39 +0,0 @@ -package api - -import ( - "context" - "net/http" - - core "fr.latosa-escrima/api/core" -) - -func HandleGetEvent(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - - if r.Method != http.MethodGet { - core.JSONError{ - Status: core.Error, - Message: "Method not Allowed", - }.Respond(w, http.StatusMethodNotAllowed) - return - } - - event_uuid := r.PathValue("uuid") - - var event core.Event - _, err := core.DB.NewSelect().Model(&event).Where("uuid = ?", event_uuid).ScanAndCount(context.Background()) - if err != nil { - core.JSONError{ - Status: core.Error, - Message: err.Error(), - }.Respond(w, http.StatusNotAcceptable) - return - } - - core.JSONSuccess{ - Status: core.Success, - Message: "Event Returned", - Data: event, - }.Respond(w, http.StatusOK) - return -} diff --git a/backend/api/get_event.go b/backend/api/get_event.go new file mode 100644 index 0000000..56bbc11 --- /dev/null +++ b/backend/api/get_event.go @@ -0,0 +1,49 @@ +package api + +import ( + "context" + "fmt" + "net/http" + + core "fr.latosa-escrima/api/core" +) + +func HandleGetEvent(w http.ResponseWriter, r *http.Request) { + event_uuid := r.PathValue("event_uuid") + var event core.Event + _, err := core.DB.NewSelect().Model(&event).Where("uuid = ?", event_uuid).ScanAndCount(context.Background()) + if err != nil { + core.JSONError{ + Status: core.Error, + Message: err.Error(), + }.Respond(w, http.StatusInternalServerError) + return + } + + core.JSONSuccess{ + Status: core.Success, + Message: "Event successfully sent", + Data: event, + }.Respond(w, http.StatusOK) + return +} + +func HangleGetEvents(w http.ResponseWriter, r *http.Request) { + var events []core.Event + rowsCount, err := core.DB.NewSelect().Model(&events).ScanAndCount(context.Background()) + if err != nil { + core.JSONError{ + Status: core.Error, + Message: err.Error(), + }.Respond(w, http.StatusInternalServerError) + return + } + + core.JSONSuccess{ + Status: core.Success, + Message: fmt.Sprintf("%d Event successfully sent", rowsCount), + Data: events, + }.Respond(w, http.StatusOK) + return +} + diff --git a/backend/api/new_event.go b/backend/api/new_event.go index cefd342..6abba18 100644 --- a/backend/api/new_event.go +++ b/backend/api/new_event.go @@ -2,50 +2,34 @@ package api import ( "context" - "net/http" - "io" "encoding/json" + "net/http" core "fr.latosa-escrima/api/core" ) func HandleCreateEvent(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - core.JSONError{ - Status: core.Error, - Message: "Method is not allowed", - }.Respond(w, http.StatusMethodNotAllowed) - return - } - - body, err := io.ReadAll(r.Body) + var event core.Event + err := json.NewDecoder(r.Body).Decode(&event) if err != nil { core.JSONError{ Status: core.Error, Message: err.Error(), - }.Respond(w, http.StatusNoContent) + }.Respond(w, http.StatusBadRequest) return } - var event core.Event - if err = json.Unmarshal(body, &event); err != nil { - core.JSONError{ - Status: core.Error, - Message: err.Error(), - }.Respond(w, http.StatusNoContent) - return - } - + _, err = core.DB.NewInsert().Model(&event).Exec(context.Background()) if err != nil { core.JSONError{ Status: core.Error, Message: err.Error(), }.Respond(w, http.StatusNotAcceptable) - } + } core.JSONSuccess{ Status: core.Success, - Message: "Event inserted", + Message: "Event created", Data: event, }.Respond(w, http.StatusCreated) } diff --git a/backend/api/update_event.go b/backend/api/update_event.go new file mode 100644 index 0000000..ed143ae --- /dev/null +++ b/backend/api/update_event.go @@ -0,0 +1,65 @@ +package api + +import ( + "context" + "encoding/json" + "log" + "net/http" + + "fr.latosa-escrima/api/core" + "github.com/google/uuid" +) + +func HandleUpdateEvent(w http.ResponseWriter, r *http.Request) { + var event core.Event + err := json.NewDecoder(r.Body).Decode(&event) + if err != nil { + core.JSONError{ + Status: core.Error, + Message: err.Error(), + }.Respond(w, http.StatusBadRequest) + return + } + + event_uuid := r.PathValue("event_uuid") + event.EventID, err = uuid.FromBytes([]byte(event_uuid)) + if err != nil { + core.JSONError{ + Status: core.Error, + Message: err.Error(), + }.Respond(w, http.StatusBadRequest) + return + } + + log.Println(event) + + // val := reflect.ValueOf(event) + // typ := val.Type() + // + // for i := 0; i < val.NumField(); i++ { + // field := val.Field(i) + // fieldType := typ.Field(i) + // fmt.Printf("Field Name: %s, Field Value: %v\n", fieldType.Name, field.Interface()) + // if fiel + // } + + _, err = core.DB.NewUpdate(). + Model(event). + OmitZero(). + WherePK(). + Exec(context.Background()) + if err != nil { + core.JSONError{ + Status: core.Error, + Message: "Event not found.", + }.Respond(w, http.StatusInternalServerError) + return + } + + core.JSONSuccess{ + Status: core.Success, + Message: "Event updated", + Data: event, + }.Respond(w, http.StatusOK) +} + diff --git a/backend/main.go b/backend/main.go index 7cc078e..0613c85 100644 --- a/backend/main.go +++ b/backend/main.go @@ -105,11 +105,24 @@ func main() { "/users/{user_uuid}/update": { Handler: api.HandleUpdateUser, Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT}}, - // "/users/{user_uuid}/events": {Handler: nil, Middleware: nil}, - // "/users/{user_uuid}/events/{event_uuid}": {Handler: nil, Middleware: nil}, - // "/users/{user_uuid}/events/{event_uuid}/delete": {Handler: nil, Middleware: nil}, - // "/users/{user_uuid}/events/{event_uuid}/update": {Handler: nil, Middleware: nil}, - "/blogs/new": {Handler: api.HandleCreateBlog, Middlewares: nil}, + "/events": { + Handler: api.HangleGetEvents, + Middlewares: []core.Middleware{api.Methods("GET")}}, + "/events/new": { + Handler: api.HandleCreateEvent, + Middlewares: []core.Middleware{api.Methods("POST")}}, + "/events/{event_uuid}": { + Handler: api.HandleGetEvent, + Middlewares: []core.Middleware{api.Methods("GET")}}, + "/events/{event_uuid}/delete": { + Handler: api.HandleDeleteEvent, + Middlewares: []core.Middleware{api.Methods("DELETE")}}, + "/events/{event_uuid}/update": { + Handler: api.HandleUpdateEvent, + Middlewares: []core.Middleware{api.Methods("PATCH")}}, + "/blogs/new": { + Handler: api.HandleCreateBlog, + Middlewares: []core.Middleware{api.Methods(("POST"))}}, "/blogs/{uuid}": { Handler: api.HandleGetBlog, Middlewares: []core.Middleware{api.Methods("GET")}}, diff --git a/frontend/app/(main)/planning/page.tsx b/frontend/app/(main)/planning/page.tsx index 4079025..3584f6a 100644 --- a/frontend/app/(main)/planning/page.tsx +++ b/frontend/app/(main)/planning/page.tsx @@ -1,5 +1,6 @@ "use client"; +import { request, useApi } from "@/hooks/use-api"; import "@schedule-x/theme-shadcn/dist/index.css"; import { useNextCalendarApp, ScheduleXCalendar } from "@schedule-x/react"; import { createEventsServicePlugin } from "@schedule-x/events-service"; @@ -29,6 +30,7 @@ import { import { CalendarIcon } from "lucide-react"; import { Calendar } from "@/components/ui/calendar"; import { cn } from "@/lib/utils"; +import { requestFormReset } from "react-dom"; const Planning = () => { const plugins = [createEventsServicePlugin()]; @@ -36,7 +38,7 @@ const Planning = () => { useState(null); const [events, setEvents] = useState([ { - id: "1", + id: "1", // TODO put an uuid there title: "Event 1", start: format(new Date(Date.now()), "yyyy-MM-dd HH:mm"), end: format( @@ -45,6 +47,9 @@ const Planning = () => { ), }, ]); + + const [requestCreateEvent, setRequestCreateEvent] = useState(false) + const calendar = useNextCalendarApp( { theme: "shadcn", @@ -62,11 +67,47 @@ const Planning = () => { onEventClick(event, e) { setEventSelected(event); }, + async onClickDateTime(dateTime) { + setRequestCreateEvent(true) + const newEvent: CalendarEventExternal = { + id: "5", + title: "Event 1", + start: dateTime, + end: format( + new Date(dateTime).getTime() + (1000 * 60 * 60), + "yyyy-MM-dd HH:mm", + ), + } + try { + const res = await request( + `/events/new`, + { + method: "POST", + body: JSON.stringify(newEvent), + requiresAuth: true, + csrfToken: false + },) + if (res.status === "Error") { + console.log("Error") + } + if (res.status === "Success") { + console.log("Success") + } + } catch (e) { + console.log(e) + } + }, }, }, plugins, ); - + + const {data: requestedEvents, isLoading, success} = useApi("/events", { + onSuccess: (data) => { + calendar?.events.set(data) + } + }, false, false) + useEffect(() => { // get all events calendar?.events.getAll(); @@ -78,7 +119,7 @@ const Planning = () => { { setEventSelected((e) => (open ? e : null)); }} @@ -137,10 +178,9 @@ const Planning = () => { */} { const val = e.currentTarget.value; - console.log(val); setEventSelected((ev) => { if (ev) return { @@ -159,35 +199,72 @@ const Planning = () => { + value={eventSelected?.end || ""} + onChange={(e) => { + const val = e.currentTarget.value setEventSelected((ev) => { if (ev) return { ...ev, - end: e.currentTarget.value, + end: val, }; return ev; }) - } + }} className="col-span-3" /> - - + diff --git a/frontend/hooks/events.tsx b/frontend/hooks/events.tsx new file mode 100644 index 0000000..a8b4eb5 --- /dev/null +++ b/frontend/hooks/events.tsx @@ -0,0 +1,38 @@ +"use client"; + +import { setCookie } from "cookies-next"; +import { useEffect, useState } from "react"; +import { API_URL } from "@/lib/constants"; + +export interface LoginArgs { + email: string; + password: string; +} + +export default function useLogin() { + const { + data, + isLoading: loading, + isSuccess, + } = request( + "/users/login", + undefined, + "POST", + false, + true, + ); + + const login = async (inputs: LoginArgs) => { + try { + const res = await trigger(inputs); + if (!res) throw new Error("The server hasn't responded."); + if (res.status === "Error") throw new Error(res.message); + if (res.data) setCookie("auth_token", res.data); + return res; + } catch (error: any) { + throw new Error(error.message); + } + }; + + return { login, loading, isSuccess }; +}