Skip to content

Commit

Permalink
Add Deletion Functionality to Locations
Browse files Browse the repository at this point in the history
  • Loading branch information
DonXavierdev committed Feb 12, 2025
1 parent 7d7cfd6 commit 6ebc0fe
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 4 deletions.
57 changes: 56 additions & 1 deletion src/pages/Facility/settings/locations/LocationList.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { useQuery } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import CareIcon from "@/CAREUI/icons/CareIcon";

import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";

import ConfirmDialog from "@/components/Common/ConfirmDialog";
import Pagination from "@/components/Common/Pagination";
import { CardGridSkeleton } from "@/components/Common/SkeletonLoading";

import mutate from "@/Utils/request/mutate";
import query from "@/Utils/request/query";
import { LocationList as LocationListType } from "@/types/location/location";
import locationApi from "@/types/location/locationApi";
Expand All @@ -26,10 +29,12 @@ export default function LocationList({ facilityId }: Props) {
const { t } = useTranslation();
const [page, setPage] = useState(1);
const [searchQuery, setSearchQuery] = useState("");
const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
const [selectedLocation, setSelectedLocation] =
useState<LocationListType | null>(null);
const [isSheetOpen, setIsSheetOpen] = useState(false);
const limit = 12;
const queryClient = useQueryClient();

const { data, isLoading } = useQuery({
queryKey: ["locations", facilityId, page, limit, searchQuery],
Expand All @@ -53,6 +58,41 @@ export default function LocationList({ facilityId }: Props) {
setSelectedLocation(location);
setIsSheetOpen(true);
};
const { mutate: removeLocation } = useMutation({
mutationFn: ({
facilityId,
locationId,
}: {
facilityId: string;
locationId: string;
}) =>
mutate(locationApi.delete, {
pathParams: { facility_id: facilityId, id: locationId },
})({ facilityId, locationId }),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["locations", facilityId, page, limit, searchQuery],
});
toast.success("Location removed successfully");
},
onError: (error) => {
const errorData = error.cause as { errors: { msg: string }[] };
errorData.errors.forEach((er) => {
toast.error(er.msg);
});
},
});

const handleDeleteLocation = (location: LocationListType) => {
setSelectedLocation(location);
setOpenDeleteDialog(true);
};
const confirmDelete = () => {
if (!selectedLocation) return;
removeLocation({ facilityId, locationId: selectedLocation.id });
setOpenDeleteDialog(false);
setSelectedLocation(null);
};

const handleSheetClose = () => {
setIsSheetOpen(false);
Expand All @@ -61,6 +101,20 @@ export default function LocationList({ facilityId }: Props) {

return (
<div className="space-y-6">
<ConfirmDialog
title={t("delete_item", { name: selectedLocation?.name })}
description={
<span>
{t("are_you_sure_want_to_delete", { name: selectedLocation?.name })}
</span>
}
action="Delete"
variant="destructive"
show={openDeleteDialog}
onClose={() => setOpenDeleteDialog(false)}
onConfirm={confirmDelete}
cancelLabel={t("cancel")}
/>
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
<div className="flex items-center gap-4">
<h2 className="text-lg font-semibold">{t("locations")}</h2>
Expand Down Expand Up @@ -95,6 +149,7 @@ export default function LocationList({ facilityId }: Props) {
key={location.id}
location={location}
onEdit={handleEditLocation}
onDelete={handleDeleteLocation}
/>
))
) : (
Expand Down
62 changes: 61 additions & 1 deletion src/pages/Facility/settings/locations/LocationView.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Link } from "raviger";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import CareIcon from "@/CAREUI/icons/CareIcon";

Expand All @@ -17,11 +18,13 @@ import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";

import ConfirmDialog from "@/components/Common/ConfirmDialog";
import Page from "@/components/Common/Page";
import Pagination from "@/components/Common/Pagination";
import { CardGridSkeleton } from "@/components/Common/SkeletonLoading";
import LinkDepartmentsSheet from "@/components/Patient/LinkDepartmentsSheet";

import mutate from "@/Utils/request/mutate";
import query from "@/Utils/request/query";
import { LocationList, getLocationFormLabel } from "@/types/location/location";
import locationApi from "@/types/location/locationApi";
Expand All @@ -40,6 +43,7 @@ export default function LocationView({ id, facilityId }: Props) {

const [page, setPage] = useState(1);
const [searchQuery, setSearchQuery] = useState("");
const [openDeleteDialog, setOpenDeleteDialog] = useState(false);
const [selectedLocation, setSelectedLocation] = useState<LocationList | null>(
null,
);
Expand Down Expand Up @@ -92,6 +96,47 @@ export default function LocationView({ id, facilityId }: Props) {
setIsSheetOpen(false);
setSelectedLocation(null);
};
const { mutate: removeLocation } = useMutation({
mutationFn: ({
facilityId,
locationId,
}: {
facilityId: string;
locationId: string;
}) =>
mutate(locationApi.delete, {
pathParams: { facility_id: facilityId, id: locationId },
})({ facilityId, locationId }),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: [
"locations",
facilityId,
id,
"children",
{ page, limit, searchQuery },
],
});
toast.success("Location removed successfully");
},
onError: (error) => {
const errorData = error.cause as { errors: { msg: string }[] };
errorData.errors.forEach((er) => {
toast.error(er.msg);
});
},
});

const handleDeleteLocation = (location: LocationList) => {
setSelectedLocation(location);
setOpenDeleteDialog(true);
};
const confirmDelete = () => {
if (!selectedLocation) return;
removeLocation({ facilityId, locationId: selectedLocation.id });
setOpenDeleteDialog(false);
setSelectedLocation(null);
};

if (!location)
return (
Expand All @@ -115,6 +160,20 @@ export default function LocationView({ id, facilityId }: Props) {

return (
<>
<ConfirmDialog
title={t("delete_item", { name: selectedLocation?.name })}
description={
<span>
{t("are_you_sure_want_to_delete", { name: selectedLocation?.name })}
</span>
}
action="Delete"
variant="destructive"
show={openDeleteDialog}
onClose={() => setOpenDeleteDialog(false)}
onConfirm={confirmDelete}
cancelLabel={t("cancel")}
/>
<Breadcrumb className="m-4">
<BreadcrumbList>
<BreadcrumbItem>
Expand Down Expand Up @@ -216,6 +275,7 @@ export default function LocationView({ id, facilityId }: Props) {
key={childLocation.id}
location={childLocation}
onEdit={handleEditLocation}
onDelete={handleDeleteLocation}
/>
))
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { useTranslation } from "react-i18next";

import { cn } from "@/lib/utils";

import CareIcon from "@/CAREUI/icons/CareIcon";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
Expand All @@ -26,10 +28,11 @@ import { LocationList, getLocationFormLabel } from "@/types/location/location";
interface Props {
location: LocationList;
onEdit?: (location: LocationList) => void;
onDelete?: (location: LocationList) => void;
className?: string;
}

export function LocationCard({ location, onEdit, className }: Props) {
export function LocationCard({ location, onEdit, onDelete, className }: Props) {
const { t } = useTranslation();

const getLocationTypeIcon = (form: string) => {
Expand Down Expand Up @@ -127,7 +130,10 @@ export function LocationCard({ location, onEdit, className }: Props) {
</div>

<div className="mt-auto border-t border-gray-100 bg-gray-50 p-4">
<div className="flex justify-end">
<div className="flex justify-between">
<Button variant="destructive" onClick={() => onDelete?.(location)}>
<CareIcon icon="l-trash" />
</Button>
<Button variant="outline" asChild>
<Link
href={`/location/${location.id}`}
Expand Down
5 changes: 5 additions & 0 deletions src/types/location/locationApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export default {
TRes: Type<LocationDetail>(),
TBody: Type<LocationWrite>(),
},
delete: {
path: "/api/v1/facility/{facility_id}/location/{id}/",
method: HttpMethod.DELETE,
TRes: Type<void>(),
},
getOrganizations: {
path: "/api/v1/facility/{facility_id}/location/{id}/organizations",
method: HttpMethod.GET,
Expand Down

0 comments on commit 6ebc0fe

Please sign in to comment.