-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
90d492d
commit a8fdbb0
Showing
22 changed files
with
334 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
"use server"; | ||
import { db } from "@/lib/db"; | ||
import { getSessionUser } from "@/utils/getSessionUser"; | ||
import { Routes } from "@/utils/router/Routes.constants"; | ||
import { revalidatePath } from "next/cache"; | ||
|
||
async function addRaceLocation(formData: FormData): Promise<void> { | ||
const sessionUser = await getSessionUser(); | ||
|
||
if (!sessionUser || !sessionUser.userId) { | ||
throw new Error("User ID is required"); | ||
} | ||
|
||
const { userId } = sessionUser; | ||
|
||
await db.raceLocation.create({ | ||
data: { | ||
city: formData.get("city") as string, | ||
state: formData.get("state") as string, | ||
userId, | ||
}, | ||
}); | ||
|
||
revalidatePath(Routes.ManageRaceLocations, "layout"); | ||
} | ||
|
||
export default addRaceLocation; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"use server"; | ||
import { db } from "@/lib/db"; | ||
import { getSessionUser } from "../../utils/getSessionUser"; | ||
import { revalidatePath } from "next/cache"; | ||
import { Routes } from "@/utils/router/Routes.constants"; | ||
|
||
async function deleteRaceLocation(raceLocationId: string): Promise<void> { | ||
const sessionUser = await getSessionUser(); | ||
|
||
if (!sessionUser || !sessionUser.userId) { | ||
throw new Error("User ID is required"); | ||
} | ||
|
||
const { userId } = sessionUser; | ||
|
||
const raceLocation = await db.raceLocation.findFirst({ | ||
where: { id: raceLocationId }, | ||
}); | ||
|
||
if (!raceLocation) throw new Error("Race Location Not Found"); | ||
|
||
if (raceLocation.userId.toString() !== userId) { | ||
throw new Error("Unauthorized"); | ||
} | ||
|
||
await db.raceLocation.delete({ where: { id: raceLocationId } }); | ||
|
||
revalidatePath(Routes.ManageRaceLocations, "layout"); | ||
} | ||
|
||
export default deleteRaceLocation; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import Link from "next/link"; | ||
import { ArrowLeft } from "lucide-react"; | ||
import { Routes } from "@/utils/router/Routes.constants"; | ||
import { TabCard } from "@/components/tab-card/TabCard"; | ||
import { Tab } from "@/components/tabs/Tabs.constants"; | ||
import { db } from "@/lib/db"; | ||
import { getSessionUser } from "@/utils/getSessionUser"; | ||
import { LayoutContainer } from "@/components/layout-container/LayoutContainer"; | ||
import { LocationsList } from "@/components/locations-list/LocationsList"; | ||
|
||
export default async function ManageLocationsPage() { | ||
const session = await getSessionUser(); | ||
const locations = await db.raceLocation.findMany({ | ||
where: { userId: session?.userId }, | ||
}); | ||
|
||
return ( | ||
<LayoutContainer> | ||
<Link | ||
href={Routes.Results} | ||
className="inline-flex items-center text-blue-600 hover:text-blue-800 mb-4" | ||
> | ||
<ArrowLeft className="mr-2 h-4 w-4" /> | ||
Back to Dashboard | ||
</Link> | ||
<TabCard tab={Tab.ManageLocations}> | ||
<div className="space-y-4 mt-4"> | ||
<div className="space-y-2"> | ||
<LocationsList locations={locations} /> | ||
</div> | ||
</div> | ||
</TabCard> | ||
</LayoutContainer> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
"use client"; | ||
|
||
import { Button } from "@/components/ui/button"; | ||
import { Plus, Trash2 } from "lucide-react"; | ||
import { Input } from "@/components/ui/input"; | ||
import { useRef, useState } from "react"; | ||
import { useToast } from "@/hooks/use-toast"; | ||
import { ConfirmationDialog } from "@/components/confirmation-dialog/ConfirmationDialog"; | ||
import { | ||
Select, | ||
SelectContent, | ||
SelectItem, | ||
SelectTrigger, | ||
SelectValue, | ||
} from "../ui/select"; | ||
import { states } from "../personal-results/PersonalResults.constants"; | ||
import addRaceLocation from "@/app/actions/addRaceLocation"; | ||
import { IRaceLocation } from "./LocationsList.types"; | ||
import deleteRaceLocation from "@/app/actions/deleteRaceLocation"; | ||
|
||
interface IProps { | ||
locations: IRaceLocation[]; | ||
} | ||
|
||
export const LocationsList = (props: IProps) => { | ||
const formRef = useRef<HTMLFormElement | null>(null); | ||
const selectRef = useRef<HTMLSelectElement | null>(null); | ||
const { toast } = useToast(); | ||
const [isConfirmationDialogOpen, setIsConfirmationDialogOpen] = | ||
useState<boolean>(false); | ||
|
||
const handleRemoveLocation = async (locationId: string) => { | ||
await deleteRaceLocation(locationId); | ||
toast({ | ||
title: "Successfully deleted race location", | ||
}); | ||
setIsConfirmationDialogOpen(false); | ||
}; | ||
|
||
const handleAddLocation = async (formData: FormData) => { | ||
await addRaceLocation(formData); | ||
toast({ | ||
title: "Successfully added race location", | ||
}); | ||
|
||
formRef.current?.reset(); | ||
if (selectRef.current) { | ||
selectRef.current.value = ""; | ||
} | ||
}; | ||
|
||
return ( | ||
<> | ||
<form action={handleAddLocation} className="flex space-x-2" ref={formRef}> | ||
<Input | ||
name="city" | ||
placeholder="Enter city" | ||
className="flex-grow" | ||
required={true} | ||
/> | ||
<Select name="state" required={true} defaultValue=""> | ||
<SelectTrigger className="border-blue-300 focus:border-blue-500"> | ||
<SelectValue | ||
placeholder="Select State" | ||
defaultValue="" | ||
ref={selectRef} | ||
/> | ||
</SelectTrigger> | ||
<SelectContent className="bg-white"> | ||
{states.map((state) => ( | ||
<SelectItem key={state.value} value={state.value}> | ||
{state.label} | ||
</SelectItem> | ||
))} | ||
</SelectContent> | ||
</Select> | ||
<Button | ||
className="bg-blue-500 hover:bg-blue-600 text-white" | ||
type="submit" | ||
> | ||
<Plus className="h-4 w-4 mr-2" /> | ||
Add | ||
</Button> | ||
</form> | ||
<div className="space-y-2"> | ||
{props.locations.map((location, index) => ( | ||
<div | ||
key={index} | ||
className="flex justify-between items-center bg-gray-100 p-2 rounded" | ||
> | ||
<span> | ||
{location.city}, {location.state} | ||
</span> | ||
<div> | ||
{/* <EditRaceDistanceDialog | ||
distance={distance.distance} | ||
id={distance.id} | ||
/> */} | ||
<Button | ||
variant="ghost" | ||
size="sm" | ||
onClick={() => setIsConfirmationDialogOpen(true)} | ||
className="text-red-500 hover:text-red-700" | ||
> | ||
<Trash2 className="h-4 w-4" /> | ||
</Button> | ||
<ConfirmationDialog | ||
description={`This will permanently delete ${location.city}, ${location.state}.`} | ||
isOpen={isConfirmationDialogOpen} | ||
title="Are you sure you want to delete?" | ||
onClose={() => setIsConfirmationDialogOpen(false)} | ||
onConfirm={() => handleRemoveLocation(location.id)} | ||
/> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export interface IRaceLocation { | ||
createdAt: Date; | ||
city: string; | ||
id: string; | ||
state: string; | ||
userId: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.