Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chanatpakorn/joh-77-sprint-5-api-pets-info-petsid-query #57

Merged
9 changes: 8 additions & 1 deletion src/api/pets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ interface DeletePetResponse {
success: boolean;
}

const getPet = async (id: string): Promise<Pet> => {
const response = await axios.get<Pet>(
`${import.meta.env.VITE_API_URL}/pets/${id}`
);
return response.data;
};

const getPets = async (filters?: filterState) => {
const params = convertFiltertoParams(filters);
const response = await axios.get<PetsResponse>(
Expand Down Expand Up @@ -80,5 +87,5 @@ const deletePet = async (id: string) => {
return response.data;
};

export { deletePet, getPets, postPet, updateVisibility };
export { deletePet, getPet, getPets, postPet, updateVisibility };
export type { PetsResponse, postPetRequest };
20 changes: 18 additions & 2 deletions src/app/admin/pets/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import PetPageFallback from "@/components/Fallback/PetPageFallback";
import Details from "@/components/Pets/Details/Details";
import SmallPetCardList from "@/components/SmallPetCardList";
import { usePetQuery } from "@/hooks/queries/usePetQuery";
import { usePetsQuery } from "@/hooks/queries/usePetsQuery";
import { usePageParams } from "@/hooks/usePageParams";
import AdminLayout from "@/layouts/AdminLayout";
const EditPet = () => {
const { data } = usePetsQuery();
const { data, isLoading } = usePetsQuery();
const param = usePageParams(["id"]);

return <>{data && <Details isAdmin={true} data={data} />}</>;
const { data: petData, isLoading: petDataLoading } = usePetQuery(param.id);

return (
<>
{petDataLoading || !petData ? (
<PetPageFallback />
) : (
<Details isAdmin={true} data={petData} />
)}
<SmallPetCardList isLoading={isLoading} pets={data?.pets} />
</>
);
};

export default EditPet;
Expand Down
6 changes: 3 additions & 3 deletions src/app/admin/pets/add/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { useCreatePet } from "@/hooks/mutation/usePostPet";
import AdminLayout from "@/layouts/AdminLayout";
import dayjs from "dayjs";
const adminCreate = () => {
const { data } = usePetsQuery();
const { data, isLoading } = usePetsQuery();

const [name, setName] = useState("กรุณาใส่ชื่อ...");
const [text, setText] = useState("");
Expand Down Expand Up @@ -81,7 +81,7 @@ const adminCreate = () => {
type: info.type,
name: name,
birthdate: dayjs(info.age).toISOString(),
gender: info.gender,
gender: info.gender as "male" | "female",
color: info.color,
pattern: "a", // remove later
habit: info.nature,
Expand Down Expand Up @@ -152,7 +152,7 @@ const adminCreate = () => {
</div>
</div>
<div className="hidden md:block">
{data && <SmallPetCardList pets={data.pets} />}
<SmallPetCardList isLoading={isLoading} pets={data?.pets} />
</div>
</>
);
Expand Down
46 changes: 20 additions & 26 deletions src/app/pets/[id]/adopt/page.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,37 @@
import Container from "@/components/Container";
import PetThumbnails from "@/components/Pets/PetThumbnails";
import TermsAndConditions from "@/components/Pets/TermsAndConditions";
import { usePetQuery } from "@/hooks/queries/usePetQuery";
import { usePageParams } from "@/hooks/usePageParams";
import MainLayout from "@/layouts/MainLayout";
import { Icon } from "@iconify/react/dist/iconify.js";
import { Link } from "react-router-dom";

const AdoptionPage = () => {
const petName = "ไรลีย์";

const param = usePageParams(["id"]);

const petImagesArray = [
"https://f.ptcdn.info/251/076/000/r6phkmmxuGNF1erTdMG-o.jpg",
"https://f.ptcdn.info/277/076/000/r6txsu2haubx6Pgn31Mzf-o.jpg",
"https://f.ptcdn.info/078/076/000/r5tzwel2nq8YmxZm3w6-o.png",
];
const { data } = usePetQuery(param.id);
const petImagesArray = data?.images.map((img) => img.url) as string[];

return (
<>
<div className="flex justify-between px-6 lg:block lg:px-12">
<Link to={`/pets/${param.id}`}>
<Icon icon={"ion:chevron-back"} className="h-8 w-8 text-primary" />
</Link>
data && (
<>
<button type="button" onClick={() => window.history.back()}>
<Icon icon="ion:chevron-back" className="h-8 w-8 cursor-pointer" />
</button>
<h2 className="visible flex flex-row justify-between text-4xl font-bold text-primary underline md:hidden">
{petName}
{data.name}
</h2>
</div>

<Container className="flex flex-col items-center gap-8 md:flex-row md:items-start md:justify-between">
<PetThumbnails petImages={petImagesArray} />
<div>
<h2 className="mb-8 hidden text-4xl font-bold text-primary underline md:block">
{petName}
</h2>
<TermsAndConditions />
</div>
</Container>
</>
<Container className="flex flex-col items-center gap-8 md:flex-row md:items-start md:justify-between">
<PetThumbnails petImages={petImagesArray} origin={data?.origin} />
<div>
<h2 className="mb-8 hidden text-4xl font-bold text-primary underline md:block">
{data.name}
</h2>
<TermsAndConditions />
</div>
</Container>
</>
)
);
};

Expand Down
20 changes: 18 additions & 2 deletions src/app/pets/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import PetPageFallback from "@/components/Fallback/PetPageFallback";
import Details from "@/components/Pets/Details/Details";
import SmallPetCardList from "@/components/SmallPetCardList";
import { usePetQuery } from "@/hooks/queries/usePetQuery";
import { usePetsQuery } from "@/hooks/queries/usePetsQuery";
import { usePageParams } from "@/hooks/usePageParams";
import MainLayout from "@/layouts/MainLayout";
const PetInfo = () => {
const { data } = usePetsQuery();
const { data, isLoading } = usePetsQuery();
const param = usePageParams(["id"]);

return <>{data && <Details isAdmin={false} data={data} />}</>;
const { data: petData, isLoading: petDataLoading } = usePetQuery(param.id);

return (
<>
{petDataLoading || !petData ? (
<PetPageFallback />
) : (
<Details isAdmin={false} data={petData} />
)}
{<SmallPetCardList isLoading={isLoading} pets={data?.pets} />}
</>
);
};

export const Layout = MainLayout;
Expand Down
12 changes: 10 additions & 2 deletions src/components/Admin/Pets/Add/DateInputInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Icon } from "@iconify/react/dist/iconify.js";
import { ChangeEvent } from "react";
import dayjs from "dayjs";
import { ChangeEvent, useMemo } from "react";

interface DateInputInfoProps {
text: string;
Expand All @@ -17,6 +18,11 @@ const DateInputInfo = (props: DateInputInfoProps) => {
props.onChange(date);
};

const birthdate = useMemo(() => {
if (props.value != "-") return dayjs(props.value).format("MMMM DD, YYYY");
return "-";
}, [props.value]);

return (
<div className="grid grid-cols-4 gap-2">
<div className="flex flex-row items-center">
Expand All @@ -35,7 +41,9 @@ const DateInputInfo = (props: DateInputInfoProps) => {
/>
</div>
) : (
<div className="ml-2 font-semibold">{props.value}</div>
<div className="ml-2 font-semibold">
{birthdate ? birthdate : "-"}
</div>
)}
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Admin/Pets/Add/DropdownInputInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ const DropdownInputInfo = (props: DropdownInputInfoProps) => {
</div>
) : (
<div className={`ml-2 font-semibold`}>
{currentOption ? currentOption.label : "-"}
{currentOption ? currentOption.label : props.value}
</div>
)}
</div>
Expand Down
9 changes: 8 additions & 1 deletion src/components/Admin/Pets/Add/EditInfoAndSubmit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ const EditInfoAndSubmit = (props: EditInfoAndSubmitProps) => {
}
};

const genderType =
showInfo.gender != "-"
? showInfo.gender === "female"
? "ตัวเมีย"
: "ตัวผู้"
: "-";

return (
<div className="flex w-full flex-col">
{/* EditInfo */}
Expand Down Expand Up @@ -131,7 +138,7 @@ const EditInfoAndSubmit = (props: EditInfoAndSubmitProps) => {
<DropdownInputInfo
text={"เพศ:"}
icon={"ph:gender-intersex"}
value={showInfo.gender}
value={genderType}
setValue={(newOption) =>
handleOnChangeDropDown(newOption, "gender")
}
Expand Down
14 changes: 7 additions & 7 deletions src/components/Admin/Pets/Add/PetBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface PetBadgeProps {
const PetBadge = (props: PetBadgeProps) => {
const handleOnClick = () => {
if (!props.isEditabled) return;
props.setValue(props.value === "fromClub" ? "fromOutside" : "fromClub");
props.setValue(props.value === "entrust" ? "club" : "entrust");
};
return (
<div
Expand All @@ -21,7 +21,7 @@ const PetBadge = (props: PetBadgeProps) => {
>
<Icon
icon={
props.value === "fromClub"
props.value === "club"
? "custom:primary:banner"
: "custom:yellow:banner"
}
Expand All @@ -30,23 +30,23 @@ const PetBadge = (props: PetBadgeProps) => {
<div
className={
"absolute top-[0.4rem] flex w-full flex-col items-center text-sm " +
(props.value === "fromClub" ? "text-white" : "text-black")
(props.value === "club" ? "text-white" : "text-black")
}
>
<Icon
icon={props.value === "fromClub" ? "custom:chess" : "ph:paw-print"}
icon={props.value === "club" ? "custom:chess" : "ph:paw-print"}
className="h-6 w-6"
/>
<div className="">
{props.value === "fromClub" ? "สัตว์เลี้ยง" : "สัตว์ฝาก"}
{props.value === "club" ? "สัตว์เลี้ยง" : "สัตว์ฝาก"}
</div>
<div className="flex flex-row items-center">
{props.value === "fromClub" ? "ชมรม" : "หาบ้าน"}
{props.value === "club" ? "ชมรม" : "หาบ้าน"}
<Icon
icon="fluent:arrow-swap-20-regular"
className="h-5 w-5"
hFlip={true}
color={props.value === "fromClub" ? "white" : "black"}
color={props.value === "club" ? "white" : "black"}
/>
</div>
</div>
Expand Down
36 changes: 23 additions & 13 deletions src/components/Pets/Details/BigPetCard.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
import petImg from "@/assets/details/pet.svg";
import dog from "@/assets/dog.webp";
import AddSmallPicture from "@/components/Admin/Pets/Add/AddSmallPicture";
import AddThumbnail from "@/components/Admin/Pets/Add/AddThumbnail";
import EditName from "@/components/Admin/Pets/Add/EditName";
import EditText from "@/components/Admin/Pets/Add/EditText";
import Container from "@/components/Container";
import { Pet } from "@/types/pets";
import { Icon } from "@iconify/react/dist/iconify.js";
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import "react-responsive-carousel/lib/styles/carousel.min.css";
import PetThumbnails from "../PetThumbnails";

const BigPetCard = ({ isAdmin }: { isAdmin: boolean }) => {
const [name, setName] = useState("ไรลีย์");
const [text, setText] = useState(
"ทาวน์เทปวโรกาส ลิมูซีนเพลซบาร์บี้อุเทนเพลย์บอย ฟลุก เซอร์ไพรส์ รูบิคบึมเฝอมายาคติ ทรู ภคันทลาพาธ วาไรตี้ ท็อปบูตสงบสุขวอลนัต โนติส เบลอ แรงใจ เป่ายิงฉุบโยโย่ ภควัทคีตา อิเหนาช็อปนินจารูบิคคาสิโน คีตกวีบอกซ์โพลารอยด์ดิกชันนารี แกสโซฮอล์ผู้นำ จิ๊กโก๋ธัมโมคอร์รัปชั่น เหี่ยวย่นออทิสติก เวเฟอร์เดโมเจ๊วีนโอวัลติน"
);
const [petFrom, setPetFrom] = useState("fromClub");
const BigPetCard = ({ isAdmin, data }: { isAdmin: boolean; data: Pet }) => {
const [name, setName] = useState(data.name);
const [text, setText] = useState(data.caption);
const [petFrom, setPetFrom] = useState(data.origin);
const [image, setImage] = useState<File | null>(null);
const [images, setImages] = useState<File[]>([]);
const imgs = [petImg, petImg, petImg, petImg];

const convertImgToFile = async (imgFilePath: string) => {
const response = await fetch(imgFilePath);
const blob = await response.blob();
const file = new File([blob], "image.jpg", { type: blob.type });
setImages(() => [file, file, file]);
setImage(file);
return file;
};

const imgs = useMemo(() => {
if (!data.images) return [dog];
return data.images?.map((img) => img.url);
}, [data.images]);

useEffect(() => {
convertImgToFile(petImg);
if (!data.images || !isAdmin) return;

// Set 1st image to thumbnail
convertImgToFile(data.images[0].url).then((file) => setImage(file));

// Set the rest of the images to images
const imgFiles = data.images.map((img) => img.url).slice(1);
const imgPromises = imgFiles.map((img) => convertImgToFile(img));
Promise.all(imgPromises).then((files) => setImages(files));
}, []);

return (
Expand All @@ -47,7 +57,7 @@ const BigPetCard = ({ isAdmin }: { isAdmin: boolean }) => {
<div className="mx-auto flex w-full flex-col items-center justify-between gap-8 md:h-80 md:flex-row md:items-start">
<div className="relative w-80">
{!isAdmin ? (
<PetThumbnails petImages={imgs} />
<PetThumbnails petImages={imgs} origin={data.origin} />
) : (
<AddThumbnail
valueOrigin={petFrom}
Expand Down
Loading
Loading