Skip to content

Commit

Permalink
WIP) Reflect changes related to adding place logic
Browse files Browse the repository at this point in the history
  • Loading branch information
yihyun-kim1 committed Aug 21, 2024
1 parent dcbddc6 commit d29cb07
Show file tree
Hide file tree
Showing 26 changed files with 1,003 additions and 387 deletions.
1 change: 1 addition & 0 deletions apis/origin-place/types/dto/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type PlaceAutoCompleteResponse = {
data: {
openingHours?: string | null | undefined;
name: string;
url: string;
placeImageUrls: {
Expand Down
14 changes: 12 additions & 2 deletions apis/place/PlaceApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,24 @@ class PlaceApi {
placeImages: string[];
};
}): Promise<ResponseForm<PlaceResponseDto>> => {
//SuccessPlaceTypeGroupResponse[]
const formData = new FormData();

formData.append("addPlaceRequest", JSON.stringify(payload.addPlaceRequest));

payload.placeImages.forEach((image) => {
formData.append("placeImages", image);
});

const { data } = await this.axios({
method: "POST",
url: `/rooms/${roomUid}/places`,
data: payload,
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
});

return data;
};

Expand All @@ -68,7 +78,7 @@ class PlaceApi {
payload,
}: {
roomUid: string;
placeId: string;
placeId: number;
payload: {
modifyPlaceRequest: ModifyPlaceRequestDto;
newPlaceImages: string[];
Expand Down
26 changes: 15 additions & 11 deletions apis/place/types/dto/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* API Response
*/
export interface PlaceResponseDto {
id: number;
id?: number;
roomUid: string;
scheduleId: number;
name: string;
Expand All @@ -15,6 +15,7 @@ export interface PlaceResponseDto {
starGrade?: number;
origin: "AVOCADO" | "LEMON" | "MANUAL";
memo?: string;
openingHours?: string;
reviewCount?: number;
confirmed?: boolean;
}
Expand All @@ -34,15 +35,15 @@ export interface SuccessPlaceTypeGroupResponse {
* API Payloads
*/
export interface AddPlaceRequestDto {
scheduleId: number;
type: string;
scheduleIds: number[];
name: string;
url?: string;
address?: string | null;
openingHours?: string | null;
reviewCount?: number | null;
phoneNumber?: string | null;
starGrade?: number | null;
memo: string;
memo?: string;
voteLikeCount?: number | null;
voteDislikeCount?: number | null;
longitude?: number | null;
Expand All @@ -56,14 +57,17 @@ export interface CreatePlacePayloadDto {

export interface ModifyPlaceRequestDto {
scheduleId: number;
scheduleType: string;
name: string;
url: string;
url?: string;
deleteTargetUrls: string[];
address: string;
phoneNumber: string;
starGrade: number;
memo: string;
voteLikeCount: number;
voteDislikeCount: number;
phoneNumber?: string;
starGrade?: number;
memo?: string;
reviewCount?: number;
openingHours: string;
voteLikeCount?: number;
voteDislikeCount?: number;
longitude?: number;
latitude?: number;
}
52 changes: 26 additions & 26 deletions app/add-course/_components/AddCourse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ import { useCreatePlace } from "@/apis/origin-place/OriginPlaceApi.mutation";
import { PlaceContainer } from "./PlaceContainer";
import useShare from "@/hooks/useShare";
import { RoomResponse } from "@/apis/room/types/model";
import {
PlaceResponseDto,
ScheduleTypeGroupResponse,
} from "@/apis/place/types/dto";
import { ModalWithVote } from "@/components/common/Modal/ModalWithVote";

export interface AddCourseProps {
data: RoomResponse;
Expand All @@ -36,19 +33,20 @@ const AddCourse = ({ data }: AddCourseProps) => {
const [placeUrl, setPlaceUrl] = useState("");
const [showInput, setShowInput] = useState(true);
const [showAlternateInput, setShowAlternateInput] = useState(false);

const [isModalOpen, setIsModalOpen] = useState(false);
const [isReadyToVote, setIsReadyToVote] = useState(false);
const searchParams = useSearchParams();
const roomUid = searchParams.get("roomUid") || "";
const {
roomInfo,
setRoomInfo,
roomPlacesInfo,
setRoomPlacesInfo,
categoryList,
setCategoryList,
autoPlaceInfo,
setAutoPlaceInfo,
isClipboardText,
setIsClipboardText,
addPlaceInfo,
autoData,
setAutoData,
} = useCourseContext();
Expand Down Expand Up @@ -80,21 +78,6 @@ const AddCourse = ({ data }: AddCourseProps) => {
}
}, [currentPlacesData, setRoomPlacesInfo]);

const hasPlaces = useMemo(() => {
if (
!currentPlacesData ||
!Array.isArray(currentPlacesData) ||
currentPlacesData.length === 0
) {
console.error("currentPlacesData is not in expected format or is empty.");
return false;
}

return currentPlacesData.some(
(schedule) => Array.isArray(schedule.places) && schedule.places.length > 0
);
}, [currentPlacesData]);

const { mutate: createPlaceMutate } = useCreatePlace({
options: {
onSuccess: (res) => {
Expand Down Expand Up @@ -127,7 +110,11 @@ const AddCourse = ({ data }: AddCourseProps) => {
?.places || [];
return matchingPlaces;
}
}, [currentPlacesData, selectedCategory]);
}, [currentPlacesData, selectedCategory, roomPlacesInfo]);

const hasPlaces = useMemo(() => {
return filteredPlaces.length > 0;
}, [filteredPlaces]);

const fetchCoursePageData = async (roomUid: string) => {
try {
Expand All @@ -147,6 +134,14 @@ const AddCourse = ({ data }: AddCourseProps) => {
fetchCoursePageData(roomUid);
}, [roomUid]);

useEffect(() => {
if (filteredPlaces.length > 0) {
setIsReadyToVote(true);
} else {
setIsReadyToVote(false);
}
}, [filteredPlaces]);

useEffect(() => {
const fetchData = async () => {
if (!isMobile && isValidClipboardText) {
Expand Down Expand Up @@ -196,7 +191,6 @@ const AddCourse = ({ data }: AddCourseProps) => {

const handleChipClick = (index: number) => {
setSelectedChip(index === selectedChip ? null : index);

setSelectedCategory(index === selectedCategory ? null : index);
};

Expand All @@ -205,11 +199,14 @@ const AddCourse = ({ data }: AddCourseProps) => {
return (
<div className="flex flex-col">
<div className="flex items-center justify-center gap-x-[17px] cursor-pointer px-[20px] py-[11px]">
<p className="flex w-[232px] text-semibold-15 text-neutral-700">
<p className="flex w-[232px] items-center text-semibold-15 text-neutral-700">
{roomInfo?.name}
</p>

<Button className="flex border-2 border-[#E7E8EB] w-[86px] h-[34px] py-[8px] px-[12px] bg-white gap-[4px]">
<Button
className="flex border-2 border-[#E7E8EB] w-[86px] h-[34px] py-[8px] px-[12px] bg-white gap-[4px]"
onClick={!isReadyToVote ? () => setIsModalOpen(true) : undefined}
>
<p className="font-semibold text-neutral-700 text-[12px]">ํˆฌํ‘œ์‹œ์ž‘</p>
<Image
width={16}
Expand Down Expand Up @@ -413,6 +410,9 @@ const AddCourse = ({ data }: AddCourseProps) => {
/>
)
)}
{isModalOpen && (
<ModalWithVote onButtonClick={() => setIsModalOpen((prev) => !prev)} />
)}
</div>
);
};
Expand Down
39 changes: 39 additions & 0 deletions app/add-course/_components/LabelWithValue.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as React from "react";
import Image from "next/image";
import { cn } from "@/lib/utils";

export interface LabelWithValueProps
extends React.InputHTMLAttributes<HTMLInputElement> {
iconSrc?: string;
required?: boolean;
}

const LabelWithValue = React.forwardRef<HTMLInputElement, LabelWithValueProps>(
({ className, iconSrc, value, required, type = "text", ...props }, ref) => {
return (
<div className="flex items-center w-full h-[24px]">
{iconSrc && (
<Image
className="mr-[12px]"
src={iconSrc}
alt="icon"
width={18}
height={18}
/>
)}
<input
type={type}
className={cn(
"flex-1 bg-transparent text-[#8B95A1] text-[16px] outline-none",
className
)}
value={value}
ref={ref}
{...props}
/>
</div>
);
}
);
LabelWithValue.displayName = "LabelWithValue";
export { LabelWithValue };
21 changes: 20 additions & 1 deletion app/add-course/_components/PlaceContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { ScheduleTypeGroupResponse } from "@/apis/place/types/dto";
"use client";
import {
PlaceResponseDto,
ScheduleTypeGroupResponse,
} from "@/apis/place/types/dto";
import { CardWithImageSmall } from "@/components/common/Cards/CardWithImageSmall";
import { categoryImageMap } from "@/lib/utils";
import { useCourseContext } from "@/providers/course-provider";
import { roomUidStorage } from "@/utils/web-storage/room-uid";
import { useRouter } from "next/navigation";
import { useEffect } from "react";

export interface PlacesContainerProps {
placesData: ScheduleTypeGroupResponse;
Expand All @@ -12,6 +21,15 @@ export const PlaceContainer: React.FC<PlacesContainerProps> = ({
}) => {
const { places } = placesData;

const router = useRouter();
const { selectedPlaceInfo, setSelectedPlaceInfo } = useCourseContext();
const handleCardClick = (place: PlaceResponseDto) => {
setSelectedPlaceInfo(place);
router.push(
`add-course/detail/edit?roomUid=${roomUidStorage?.get()?.roomUid}`
);
};

return (
<div className="flex flex-wrap items-center justify-start gap-x-[12px] mx-[20px] gap-y-[20px] my-[20px]">
{places.map((place) => (
Expand All @@ -24,6 +42,7 @@ export const PlaceContainer: React.FC<PlacesContainerProps> = ({
reviewCount={place?.reviewCount}
images={place?.placeImageUrls?.contents}
category={scheduleInfo}
onButtonClick={() => handleCardClick(place)}
/>
</div>
))}
Expand Down
43 changes: 43 additions & 0 deletions app/add-course/_hooks/useAddPlaceDetailForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { z } from "zod";
import { UseFormProps, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";

export type CommonPlaceDetailFormType = {
// ํ•ด๋‹น ํŒŒ์ผ์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํ•ธ๋“ค๋ง ๊ฐ€๋Šฅํ•œ ๊ฐ’๋งŒ ์ •์˜
scheduleId: number;
name: string;
type: string;
url?: string;
reviewCount?: number;
starGrade?: number;
openingHours?: string;
phoneNumber?: string;
address?: string;
memo?: string;
pictures: string[];
};

const addPlaceDetailSchema = z.object({
scheduleId: z.number(),
name: z.string(),
type: z.string(),
url: z.string().optional(),
reviewCount: z.number().optional(),
starGrade: z.number().optional(),
openingHours: z.string().optional(),
phoneNumber: z.string().optional(),
address: z.string().optional(),
memo: z.string().optional(),
pictures: z.array(z.string()),
});

export const useAddPlaceDetailForm = (
options?: UseFormProps<CommonPlaceDetailFormType>
) => {
return useForm<CommonPlaceDetailFormType>({
resolver: zodResolver(addPlaceDetailSchema),
mode: "onChange",
reValidateMode: "onChange",
...options,
});
};
Loading

0 comments on commit d29cb07

Please sign in to comment.