Skip to content

Commit

Permalink
feat(surau): Add more image function to surau
Browse files Browse the repository at this point in the history
  • Loading branch information
farhan-helmy committed Sep 6, 2023
1 parent 3004e5a commit f6ac37b
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 26 deletions.
28 changes: 11 additions & 17 deletions src/components/SurauList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Image from "next/image";
import { useRouter } from "next/router";
import { api } from "../utils/api";
import Badge from "./shared/Badge";
import Link from "next/link";

const SurauList = ({
type,
Expand All @@ -18,13 +19,6 @@ const SurauList = ({
state: userState,
});

const router = useRouter();

const handleRouterPush = (e: React.FormEvent, surauName: string) => {
e.preventDefault();
void router.push(`/${surauName}`);
};

if (type === "new") {
const pendingApprovalList = api.surau.getPendingApproval.useQuery();

Expand All @@ -35,10 +29,10 @@ const SurauList = ({

<div className="grid grid-cols-1 gap-y-10 gap-x-6 sm:grid-cols-2 lg:grid-cols-4 xl:grid-cols-4 xl:gap-x-8">
{pendingApprovalList.data?.map((surau) => (
<a key={surau.id} href={surau.name} className="group">
<div
<div key={surau.id} href={surau.name} className="group">
<Link
className=" w-full overflow-hidden rounded-lg bg-primary xl:aspect-w-1 xl:aspect-h-1"
onClick={(e) => handleRouterPush(e, surau.name)}
href={`/${surau.unique_name}`}
>
{surau.images[0]?.file_path ? (
<Image
Expand All @@ -51,14 +45,14 @@ const SurauList = ({
) : (
<></>
)}
</div>
</Link>
<h3 className="mt-4 text-sm text-gray-700">
{surau.district.name}
</h3>
<p className="mt-1 text-lg font-medium text-foreground">
{surau.name}
</p>
</a>
</div>
))}
</div>
</div>
Expand All @@ -78,10 +72,10 @@ const SurauList = ({
<div>Error: {latestAddedSurau.error.message}</div>
) : (
latestAddedSurau.data?.map((surau) => (
<a key={surau.id} href="#" className="group flex flex-col">
<div
<div key={surau.id} href="#" className="group flex flex-col">
<Link
className="h-full overflow-hidden rounded-xl bg-primary object-fill"
onClick={(e) => handleRouterPush(e, surau.unique_name)}
href={`/${surau.unique_name}`}
>
{surau.images.some((image) => image.is_thumbnail) ? (
// Display the image marked as thumbnail
Expand Down Expand Up @@ -117,7 +111,7 @@ const SurauList = ({
className="h-full w-full object-cover group-hover:opacity-75"
/>
)}
</div>
</Link>
{/* <h3 className="mt-4 text-sm text-gray-700">{surau.location}</h3> */}
<div className="mt-1 flex justify-between">
<p className="truncate text-start text-lg font-medium text-foreground">
Expand All @@ -132,7 +126,7 @@ const SurauList = ({
<Badge color="purple" text="Qiblat Certified" />
)}
</div>
</a>
</div>
))
)}
</div>
Expand Down
163 changes: 155 additions & 8 deletions src/components/SurauOverview.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
"use client";
import type { SurauPhoto } from "@prisma/client";
import Image from "next/image";
import { useRouter } from "next/router";
import type { FC } from "react";
import { capitalizeFirstLetter } from "../utils";
import { useEffect, useState } from "react";
import ImageModal from "./shared/ImageModal";
import Modal from "./shared/Modal";
import Link from "next/link";
import CustomUpload from "./shared/CustomUpload";
import { api } from "../utils/api";
import { useRouter } from "next/router";
import { toast } from "react-toastify";
import { CheckCircleIcon } from "@heroicons/react/24/outline";

type Surau = {
id: string;
Expand All @@ -16,12 +23,16 @@ type SurauOverviewProps = {
surau?: Surau | null;
};

type FileUrl = {
fileUrls: string[];
};

const SurauOverview: FC<SurauOverviewProps> = ({ surau }) => {
const router = useRouter();
const [imageHighlighted, setImageHighlighted] = useState<
SurauPhoto | null | undefined
>(null);
const [showCarousel, setShowCarousel] = useState<boolean>(false);
const [openAddMorePhotos, setOpenAddMorePhotos] = useState<boolean>(false);

useEffect(() => {
if (surau?.images.length) {
Expand All @@ -37,9 +48,13 @@ const SurauOverview: FC<SurauOverviewProps> = ({ surau }) => {
return (
<>
<div className="mb-4 flex flex-col">
<button
className="text-left text-indigo-500 hover:underline flex items-center gap-2 pb-2"
onClick={() => void router.push("/")}
<AddMorePhotos
openAddMorePhotos={openAddMorePhotos}
setOpenAddMorePhotos={setOpenAddMorePhotos}
/>
<Link
className="flex items-center gap-2 pb-2 text-left text-indigo-500 hover:underline"
href="/"
>
<svg
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -56,9 +71,11 @@ const SurauOverview: FC<SurauOverviewProps> = ({ surau }) => {
/>
</svg>
Go back
</button>
<div className="mb-2 text-left text-2xl">
{capitalizeFirstLetter(surau?.name as string)}
</Link>
<div className="mb-2 flex justify-between text-left text-xl">
<div className="truncate text-ellipsis">
{capitalizeFirstLetter(surau?.name as string)}
</div>
</div>
{surau?.images.length === 0 ? (
<div className="flex flex-col items-center justify-center">
Expand All @@ -70,6 +87,12 @@ const SurauOverview: FC<SurauOverviewProps> = ({ surau }) => {
priority
/>
<div className="italic text-muted-foreground">No image</div>
<button
className="mt-2 rounded-md bg-indigo-500 px-2 py-1 text-xs text-white hover:bg-indigo-600"
onClick={() => setOpenAddMorePhotos(true)}
>
Add image
</button>
</div>
) : (
<>
Expand Down Expand Up @@ -113,11 +136,135 @@ const SurauOverview: FC<SurauOverviewProps> = ({ surau }) => {
/>
))}
</div>
<div>
<button
className="mt-2 rounded-md bg-indigo-500 px-2 py-1 text-xs text-white hover:bg-indigo-600"
onClick={() => setOpenAddMorePhotos(true)}
>
Add more photos
</button>
</div>
</>
)}
</div>
</>
);
};

type AddMorePhotosProps = {
openAddMorePhotos: boolean;
setOpenAddMorePhotos: (open: boolean) => void;
};

export type FilePath = {
file_path: string;
is_thumbnail: boolean;
};

const AddMorePhotos = ({
openAddMorePhotos,
setOpenAddMorePhotos,
}: AddMorePhotosProps) => {
const [imageList, setImageList] = useState<FileUrl>();
const [filePath, setFilePath] = useState<FilePath[]>([]);
const [uploadCompleted, setUploadCompleted] = useState<boolean>(false);

const router = useRouter();
const uniqueName = router.query["id"];

const addPhotos = api.surau.addPhotos.useMutation();

useEffect(() => {
setFilePath((prev) => {
const updatedFilePath = [...prev];
imageList?.fileUrls.forEach((image) => {
updatedFilePath.push({
file_path: image,
is_thumbnail: false,
});
});
return updatedFilePath;
});

if (uploadCompleted) {
toast.success("Upload completed");
}
}, [imageList, uploadCompleted]);

const handleSubmit = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();
e.stopPropagation();
if (!filePath) return;

if (!uploadCompleted) {
toast.warning("Please press upload files first!");
return;
}

addPhotos
.mutateAsync({
unique_name: uniqueName as string,
image: filePath,
})
.then(() => {
toast.success("Photos added successfully");
setOpenAddMorePhotos(false);
})
.catch((err) => {
toast.error("Something went wrong");
console.error(err);
});
};

return (
<Modal open={openAddMorePhotos} setOpen={setOpenAddMorePhotos}>
<div className="md:grid md:grid-cols-2 md:gap-6">
<div className="md:col-span-1">
<div className="px-4 sm:px-0">
<h3 className="text-lg font-medium leading-6 text-primary-foreground">
Upload more photos
</h3>
<p className="mt-1 text-xs italic text-muted-foreground">
Help to give a better view of this surau, upload more photos
</p>
</div>
</div>
<div className="mt-4 md:col-span-2 md:mt-0">
<div className="shadow sm:overflow-hidden sm:rounded-md">
{uploadCompleted ? (
<div className="flex flex-col items-center justify-center">
<div className="text-center font-bold">Upload completed!</div>
<CheckCircleIcon className="h-6 w-6 text-center text-green-500" />
<div className="text-xs font-light italic">
Please press submit button
</div>
</div>
) : (
<CustomUpload
uploadedFileList={setImageList}
setUploadCompleted={setUploadCompleted}
/>
)}

<div className="mt-4 flex flex-row items-end justify-end gap-2 bg-gray-50 px-4 py-3 text-right dark:bg-gray-800 sm:px-6">
<button
className="justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
onClick={(e) => handleSubmit(e)}
>
Submit
</button>
<div
className="mb-2 cursor-pointer font-light underline hover:text-indigo-500"
onClick={() => setOpenAddMorePhotos(false)}
>
Close
</div>
</div>
</div>
</div>
</div>
</Modal>
);
};

export default SurauOverview;
2 changes: 1 addition & 1 deletion src/components/SurauReview.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */

"use client"
import { StarIcon } from "@heroicons/react/20/solid";
import { useSession } from "next-auth/react";
import Head from "next/head";
Expand Down
30 changes: 30 additions & 0 deletions src/server/api/routers/surau.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,34 @@ export const surauRouter = createTRPCRouter({

return suraulocationbased;
}),
addPhotos: publicProcedure
.input(
z.object({
unique_name: z.string(),
image: z.array(
z.object({
file_path: z.string(),
is_thumbnail: z.boolean().optional(),
})
),
})
)
.mutation(async ({ ctx, input }) => {
return ctx.prisma.surau.update({
where: {
unique_name: input.unique_name,
},
data: {
images: {
createMany: {
data: input.image.map((image) => ({
file_path: image.file_path,
is_thumbnail: !!image.is_thumbnail,
})),
},
},
},
});
}
),
});

0 comments on commit f6ac37b

Please sign in to comment.