Skip to content

Commit

Permalink
Add types and component for delete confirmation dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
SirSanctified committed Mar 14, 2024
1 parent 0fa94aa commit 1910e28
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 48 deletions.
64 changes: 64 additions & 0 deletions client/src/components/shared/deleteConfirmition.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"use client";

import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import axios from "axios";
import { toast } from "sonner";
import type { AxiosErrorWithDetails } from "@/types";

const DeleteConfirmition = ({
trigger,
actionUrl,
item,
}: {
trigger: React.ReactNode;
actionUrl: string;
item: string;
}) => {
async function action() {
try {
await axios.delete(actionUrl, {
withCredentials: true,
});
toast.success("Successfully deleted");
window.location.reload();
} catch (error) {
alert(JSON.stringify(error));
const message =
(error as AxiosErrorWithDetails)?.response?.data?.detail ??
"Cannot delete, something went wrong";
toast(`Failed to delete: ${message}`);
}
}
return (
<AlertDialog>
<AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete your
{item} and remove your data from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction className="bg-red-500" onClick={action}>
Continue
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};

export default DeleteConfirmition;
133 changes: 85 additions & 48 deletions client/src/components/shared/properties/roomCard.tsx
Original file line number Diff line number Diff line change
@@ -1,65 +1,102 @@
"use client";

import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { formatCurrency } from "@/lib/utils";
import type { Property, Room } from "@/types";
import { BedIcon, BuildingIcon, MapPinIcon, TagIcon } from "lucide-react";
import {
BedIcon,
BuildingIcon,
EditIcon,
MapPinIcon,
TagIcon,
TrashIcon,
} from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import DeleteConfirmition from "../deleteConfirmition";
import { useAuthStore } from "@/store/store";

const RoomCard = ({ room, property }: { room: Room; property?: Property }) => {
const { user } = useAuthStore();
return (
<Link href={`/listings/${room.id}`}>
<Card className="w-full min-w-[92vw] rounded-lg border-none bg-blue-200/75 p-0 text-indigo-950 md:min-w-[350px] md:max-w-sm lg:min-w-[450px]">
<CardHeader className="p-0">
<Image
src={"/auth-bg.jpg"}
alt="Room"
width={500}
height={500}
className="max-h-52 w-full rounded-t-lg object-cover"
/>
</CardHeader>
<CardContent className="px-2 py-4">
<div className="mb-4 flex items-center gap-4">
<h3 className="text-md font-bold">
{property?.name ? `${property.name}, room ` : null}
{room.name}
</h3>
<p className="flex items-center gap-2 rounded-full bg-indigo-200 px-2 py-0.5 text-sm font-semibold text-blue-900">
<TagIcon
size={12}
className="rotate-90 transform text-indigo-600"
/>{" "}
{formatCurrency(room.price)} / month
</p>
</div>
{property ? (
<div className="group relative min-w-[92vw] rounded-lg border-none md:min-w-[350px] md:max-w-sm lg:min-w-[450px]">
<Link href={`/listings/${room.id}`}>
<Card className="w-full min-w-[92vw] rounded-lg border-none bg-blue-200/75 p-0 text-indigo-950 md:min-w-[350px] md:max-w-sm lg:min-w-[450px]">
<CardHeader className="p-0">
<Image
src={"/auth-bg.jpg"}
alt="Room"
width={500}
height={500}
className="max-h-52 w-full rounded-t-lg object-cover"
/>
</CardHeader>
<CardContent className="px-2 py-4">
<div className="mb-4 flex items-center gap-4">
<p className="flex items-center gap-2 text-sm font-semibold text-indigo-950">
<MapPinIcon size={12} className="text-indigo-600" />{" "}
{property.city}, {property.location}
<h3 className="text-md font-bold">
{property?.name ? `${property.name}, room ` : null}
{room.name}
</h3>
<p className="flex items-center gap-2 rounded-full bg-indigo-200 px-2 py-0.5 text-sm font-semibold text-blue-900">
<TagIcon
size={12}
className="rotate-90 transform text-indigo-600"
/>{" "}
{formatCurrency(room.price)} / month
</p>
</div>
) : null}
<div className="mb-2 flex items-center gap-4 text-sm font-semibold text-indigo-950">
{property ? (
<div className="mb-4 flex items-center gap-4">
<p className="flex items-center gap-2 text-sm font-semibold text-indigo-950">
<MapPinIcon size={12} className="text-indigo-600" />{" "}
{property.city}, {property.location}
</p>
</div>
) : null}
<div className="mb-2 flex items-center gap-4 text-sm font-semibold text-indigo-950">
{property ? (
<p className="flex items-center gap-2 text-sm font-semibold">
<BuildingIcon size={12} className="text-indigo-600" />
{property?.property_type[0]?.toUpperCase() +
property.property_type.slice(1)}
</p>
) : null}
<p className="flex items-center gap-2 text-sm font-semibold">
<BuildingIcon size={12} className="text-indigo-600" />
{property?.property_type[0]?.toUpperCase() +
property.property_type.slice(1)}
<BedIcon size={16} className="text-indigo-600" />
{room.num_beds} Total
</p>
) : null}
<p className="flex items-center gap-2 text-sm font-semibold">
<BedIcon size={16} className="text-indigo-600" />
{room.num_beds} Total
</p>
<p className="flex items-center gap-2 text-sm font-semibold">
<BedIcon size={16} className="text-indigo-600" />
{room.available_beds} Available
</p>
</div>
</CardContent>
</Card>
</Link>
<p className="flex items-center gap-2 text-sm font-semibold">
<BedIcon size={16} className="text-indigo-600" />
{room.available_beds} Available
</p>
</div>
</CardContent>
</Card>
</Link>
{user?.id === property?.owner && (
<div className="absolute right-0 top-0 z-10 hidden h-max w-max flex-col items-center justify-center gap-4 rounded-lg bg-indigo-300 bg-opacity-50 p-4 px-1 group-hover:flex">
<Button
variant={"ghost"}
className="h-max w-max text-indigo-600 transition-all duration-500 ease-linear hover:scale-110 hover:bg-transparent hover:text-blue-700"
>
<EditIcon size={24} />
</Button>
<DeleteConfirmition
item="room"
trigger={
<Button
variant={"ghost"}
className="h-max w-max text-red-500 transition-all duration-500 ease-linear hover:scale-110 hover:bg-transparent hover:text-red-800"
>
<TrashIcon size={24} />
</Button>
}
actionUrl={`${process.env.NEXT_PUBLIC_API_URL}/rooms/${room.id}/`}
/>
</div>
)}
</div>
);
};

Expand Down
10 changes: 10 additions & 0 deletions client/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { AxiosError, AxiosResponse } from "axios";

export type RegisterType = {
email: string;
phone: string;
Expand Down Expand Up @@ -168,3 +170,11 @@ export type RoomState = {
setDisplayImage: (displayImage: string | File) => void;
setImages: (images: File[] | string[]) => void;
};

export type ErrorResponseData = {
detail?: string;
};

export interface AxiosErrorWithDetails extends AxiosError {
response?: AxiosResponse<ErrorResponse, unknown>;
}

0 comments on commit 1910e28

Please sign in to comment.