Skip to content

Commit

Permalink
Merge pull request #213 from GTBitsOfGood/ash/183-deleteNewBuildingTypes
Browse files Browse the repository at this point in the history
feat: flow for deleting building types
  • Loading branch information
avayedawadi authored Oct 29, 2023
2 parents 8bbe210 + d75f584 commit df4d6ec
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 41 deletions.
14 changes: 13 additions & 1 deletion server/mongodb/actions/BuildingType.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import mongoDB from "../index";
import BuildingType from "../models/BuildingType";
import Card from "../models/Card";

export async function createBuildingType(type) {
await mongoDB();
Expand All @@ -18,7 +19,18 @@ export async function updateBuildingTypeById(id, updatedType) {
export async function deleteBuildingTypeById(id) {
await mongoDB();

await BuildingType.findOneAndRemove({ _id: id });
const type = await BuildingType.findOneAndRemove(
{ _id: id },
{ select: "name" }
);
const name = type.name;

await Card.updateMany(
{ buildingType: name },
{ $pull: { buildingType: name } }
);

await Card.deleteMany({ buildingType: { $size: 0 } });
}

export async function getBuildingTypeById(id) {
Expand Down
22 changes: 22 additions & 0 deletions src/actions/BuildingType.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,25 @@ export const createBuildingType = async (type) => {
return json.payload;
});
};

export const deleteBuildingTypeById = async (id) => {
return fetch(urls.api.buildingType.delete, {
method: "DELETE",
mode: "same-origin",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(id),
})
.then((response) => response.json())
.then((json) => {
if (json == null) {
throw new Error("Could not connect to API!");
} else if (!json.success) {
throw new Error(json.message);
}

return json.payload;
});
};
12 changes: 4 additions & 8 deletions src/components/BuildingTypeCard/BuildingTypeCard.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { Flex, Image, Text } from "@chakra-ui/react";
import { Box, Flex, Image, Text } from "@chakra-ui/react";
import Link from "next/link";

function BuildingTypeCard(props) {
return (
<Flex justifyContent="center" direction="column" height="full" id="test">
<Link href={props.href}>
<Flex alignItems="center" direction="column" cursor="pointer">
<Image
src={props.src}
alt={props.alt}
width="250px"
height="250px"
objectFit="contain"
/>
<Box maxWidth="250px" maxHeight="250px">
<Image src={props.src} alt={props.alt} objectFit="contain" />
</Box>
<Text fontFamily="Roboto Slab">{props.title}</Text>
</Flex>
</Link>
Expand Down
1 change: 1 addition & 0 deletions src/lib/utils/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default {
buildingType: {
create: "/api/buildingType/create/",
get: "/api/buildingType/get/",
delete: "/api/buildingType/delete/",
},
card: {
create: "/api/card/create/",
Expand Down
23 changes: 23 additions & 0 deletions src/pages/api/buildingType/delete/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { deleteBuildingTypeById } from "server/mongodb/actions/BuildingType";
import { withSessionRoute } from "src/lib/utils/session";

// @route DELETE api/card/delete
// @desc Delete Card Request
// @access Public
const handler = async (req, res) => {
try {
const deletedType = await deleteBuildingTypeById(req.body);

return res.status(200).json({
success: true,
payload: deletedType,
});
} catch (error) {
res.status(400).json({
success: false,
message: error.message,
});
}
};

export default withSessionRoute(handler);
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const LibraryCategoryPage = (props) => {
</Text>
<Link href={`/library/${props.params.buildingType}`}>
<Button variant="Blue" size="md">
Return to {props.params.buildingType}
Return to {capitalizeAndRemoveDash(props.params.buildingType)}
</Button>
</Link>
</Flex>
Expand Down
161 changes: 130 additions & 31 deletions src/pages/library/index.jsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,156 @@
import { Button, Flex, useDisclosure } from "@chakra-ui/react";
import {
Box,
Button,
CloseButton,
Flex,
useDisclosure,
} from "@chakra-ui/react";
import { useState } from "react";
import { getBuildingTypes } from "server/mongodb/actions/BuildingType";
import { deleteBuildingTypeById } from "src/actions/BuildingType";
import BuildingTypeModal from "src/components/Modals/BuildingTypeModal";
import ConfirmActionModal from "src/components/Modals/ConfirmActionModal";
import useUser from "src/lib/hooks/useUser";
import urls from "src/lib/utils/urls";
import { capitalizeAndRemoveDash } from "src/lib/utils/utilFunctions";
import useSWR from "swr";
import BuildingType from "../../components/BuildingTypeCard";
const LibraryPage = ({ initialBuildingTypes }) => {
const {
isOpen: isFirstDeleteModalOpen,
onOpen: onFirstDeleteModalOpen,
onClose: onFirstDeleteModalClose,
} = useDisclosure();
const {
isOpen: isSecondDeleteModalOpen,
onOpen: onSecondDeleteModalOpen,
onClose: onSecondDeleteModalClose,
} = useDisclosure();
const [deleteMode, setDeleteMode] = useState(false);
const { user } = useUser();
const { isOpen, onOpen, onClose } = useDisclosure();
const {
isOpen: isCreateModalOpen,
onOpen: onCreateModalOpen,
onClose: onCreateModalClose,
} = useDisclosure();
const [buildingTypeToDelete, setBuildingTypeToDelete] = useState({
name: "initialValue",
});
const { data, mutate } = useSWR(urls.api.buildingType.get, {
initialBuildingTypes,
// initialBuildingTypes,
initialData: initialBuildingTypes,
});
const buildingTypes = data?.payload;
const handleModalClose = () => {
const handleCreateModalClose = () => {
mutate();
onCreateModalClose();
};
const handleDeleteModalOpen = (buildingType) => {
setBuildingTypeToDelete(buildingType);
onSecondDeleteModalOpen();
};
const handleDeleteType = async () => {
await deleteBuildingTypeById(buildingTypeToDelete._id);
mutate();
onClose();
onSecondDeleteModalClose();
setDeleteMode(false);
};
return (
<>
<Flex justifyContent="center" height="78vh" paddingX="10vw">
<Flex justifyContent="space-between" height="40vw" width="full">
<Box height="78vh" paddingX="10vw" position="relative">
<Flex
justifyContent="space-between"
alignItems="center"
height="40vw"
width="full"
>
{buildingTypes &&
buildingTypes.map((type) => (
<BuildingType
key={type._id}
src={type.imageUrl}
alt={`${type.name} Icon`}
title={capitalizeAndRemoveDash(type.name)}
href={`library/${type.name}`}
/>
<Box key={type._id} position="relative">
{deleteMode && (
<CloseButton
onClick={() => handleDeleteModalOpen(type)}
position="absolute"
top="0"
right="0"
bg="#D9D9D980"
rounded="full"
_hover={{ bg: "#D9D9D9B0" }}
></CloseButton>
)}
<BuildingType
src={type.imageUrl}
alt={`${type.name} Icon`}
title={capitalizeAndRemoveDash(type.name)}
href={`library/${type.name}`}
/>
</Box>
))}
</Flex>
</Flex>
<Flex justifyContent="flex-end" position="relative" marginTop="2vh">
{user?.isAdmin ? (
<Button
onClick={onOpen}
position="absolute" // position the button
bottom="5vh" // space from the bottom
right="5vw" // space from the right
variant="Blue-rounded"
size="lg"
isDisabled={user?.isAdmin ? false : true}
{user?.isAdmin && (
<Flex
justifyContent="flex-end"
position="absolute"
bottom="0"
right="5vw"
>
Create New Building Type
</Button>
) : null}
</Flex>
<Flex
flexDirection="column"
justifyContent="center"
gap="1vh"
padding="2vh"
>
<Button onClick={onCreateModalOpen} variant="Blue" size="lg">
Create New Building Type
</Button>
<Button
onClick={() => {
if (deleteMode) {
setDeleteMode(!deleteMode);
return;
}
onFirstDeleteModalOpen();
}}
variant={deleteMode ? "Grey" : "Red"}
size="lg"
>
{deleteMode ? "Return to Home" : "Delete Building Type"}
</Button>
</Flex>
</Flex>
)}
</Box>
<BuildingTypeModal
isOpen={isOpen}
onClose={handleModalClose}
isOpen={isCreateModalOpen}
onClose={handleCreateModalClose}
></BuildingTypeModal>
<ConfirmActionModal
isOpen={isFirstDeleteModalOpen}
onClose={onFirstDeleteModalClose}
mainText="Are you sure you want to continue?"
subText={`Deleting a building type will permanently delete the build type and the standards within the building type`}
confirmButtonText="Yes, continue"
cancelButtonText="No, return to home"
handleAction={() => {
setDeleteMode(!deleteMode);
onFirstDeleteModalClose();
}}
handleCancelAction={onFirstDeleteModalClose}
isDanger={true}
></ConfirmActionModal>
<ConfirmActionModal
isOpen={isSecondDeleteModalOpen}
onClose={onSecondDeleteModalClose}
mainText={`Are you sure you want to delete (${capitalizeAndRemoveDash(
buildingTypeToDelete.name
)})?`}
subText="You will permanently delete this building type and will be unable to recover it."
confirmButtonText="Yes, delete building type"
cancelButtonText="No, return"
handleAction={handleDeleteType}
handleCancelAction={onSecondDeleteModalClose}
isDanger={true}
></ConfirmActionModal>
</>
);
};
Expand Down

1 comment on commit df4d6ec

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for southface ready!

✅ Preview
https://southface-7pefzdzpa-bitsofgood.vercel.app

Built with commit df4d6ec.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.