Skip to content

Commit

Permalink
Merge pull request #128 from Step3-kakao-tech-campus/feat/#127
Browse files Browse the repository at this point in the history
feat: 프로필리스트, 보호소 프로필 api 연결, 스켈레톤 구현
  • Loading branch information
LimSumi authored Oct 21, 2023
2 parents d69d2ce + 36c94e3 commit f70badb
Show file tree
Hide file tree
Showing 17 changed files with 481 additions and 238 deletions.
2 changes: 1 addition & 1 deletion src/commons/SelectBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ for (let idx = 0; idx < 32; idx += 1) {
}

const monthOptions: SelectProps[] = [];
for (let idx = 0; idx < 13; idx += 1) {
for (let idx = 0; idx < 12; idx += 1) {
monthOptions.push({ label: `${idx}`, value: `${idx}` });
}

Expand Down
2 changes: 1 addition & 1 deletion src/pages/detailPet/VDetailPetInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const VDetailPetInfo = (data: DetailPetInfoProps) => {
{'애니모리에 등록된 보호소입니다. '}
</span>
<Link
to={`/shelter/${data.shelterInfo.id}`}
to={`/shelter/${data.shelterInfo.id}/1`}
className="text-xs font-bold text-blue-700"
>
정보 보기
Expand Down
13 changes: 3 additions & 10 deletions src/pages/profileList/ProfileCard.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { ProfileListProps } from 'pages/profileList/VProfileListHome';
import { useNavigate } from 'react-router-dom';
import VProfileCard from './VProfileCard';
import VProfileCard, { VProfileInfoProps } from './VProfileCard';

const ProfileCard = (data: ProfileListProps) => {
return <VProfileCard {...data} />;
const ProfileCard = (vProfileListProps: VProfileInfoProps) => {
return <VProfileCard {...vProfileListProps} />;
};
// const navigate = useNavigate();

// export function navigatePet(id: number) {
// return navigate('pet/$id');
// }

export default ProfileCard;
69 changes: 53 additions & 16 deletions src/pages/profileList/ProfileListHome.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,61 @@
import { useEffect, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import VProfileListHome, { ProfileListProps } from './VProfileListHome';
import ProfileListHomeSkeleton from './ProfileListHomeSkeleton';

const ProfileListHome = () => {
// const [list, setlist] = useState([]);

// useEffect(() => {
// fetch('public/data/profileHomeMock.json')
// .then((res) => res.json()) // javascript객체로 변환
// .then(setlist); // list에 저장
// }, []);
const profileListProps: ProfileListProps = {
image: '/assets/pet.png',
id: 1,
name: '보리',
age: 1,
shelter: '광주보호소',
state: '입양완료',
const [profileListProps, setProfileListProps] =
useState<ProfileListProps | null>(null);

const getProfiles = async () => {
const response = await fetch(`${process.env.REACT_APP_URI}/pet/profiles`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const json = await response.json();
return json.response;
};

// JSX를 VAC로 교체
const { data, isLoading, isError } = useQuery({
queryKey: ['pet-list'],
queryFn: getProfiles,
});

useEffect(() => {
if (!isLoading && !isError && data) {
const sosListData = data.sosList;

const newListData = data.newList;

const updatedProfileListProps: ProfileListProps = {
sosListProps: sosListData,
newListProps: newListData,
};

return <VProfileListHome {...profileListProps} />;
setProfileListProps(updatedProfileListProps);
}
}, [data, isLoading, isError]);

if (isLoading) {
return <ProfileListHomeSkeleton />;
}

if (isError) {
return <div>Error: {isError}</div>;
}

if (profileListProps) {
return <VProfileListHome {...profileListProps} />;
}

return null;
};

export default ProfileListHome;
38 changes: 38 additions & 0 deletions src/pages/profileList/ProfileListHomeSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const ProfileListHomeSkeleton = () => {
return (
<div className="mx-16 sm:mx-40 lg:mx-64 my-14">
<h2 className="flex w-full font-bold text-xl sm:text-2xl justify-center items-center whitespace-nowrap">
긴급 도움이 필요해요!
<a
href="profile/urgent/1"
className="font-normal w-full text-right justify-end text-sm flex sm:float-right text-gray-600"
>
더보기
</a>
</h2>
<div className="grid grid-cols-1 gap-1 md:grid-cols-2 my-10 w-full whitespace-nowrap">
<div className="w-3/4 h-28 bg-gray-200 m-2" />
<div className="w-3/4 h-28 bg-gray-200 m-2" />
<div className="w-3/4 h-28 bg-gray-200 m-2" />
<div className="w-3/4 h-28 bg-gray-200 m-2" />
</div>
<h2 className="flex w-full font-bold text-xl sm:text-2xl justify-center items-center whitespace-nowrap">
신규 애니모리 친구들
<a
href="/profile/new/1"
className="font-normal w-full text-right justify-end text-sm flex sm:float-right text-gray-600"
>
더보기
</a>
</h2>
<div className="grid grid-cols-1 gap-1 md:grid-cols-2 my-10 w-full whitespace-nowrap">
<div className="w-3/4 h-28 bg-gray-200 m-2" />
<div className="w-3/4 h-28 bg-gray-200 m-2" />
<div className="w-3/4 h-28 bg-gray-200 m-2" />
<div className="w-3/4 h-28 bg-gray-200 m-2" />
</div>
</div>
);
};

export default ProfileListHomeSkeleton;
44 changes: 24 additions & 20 deletions src/pages/profileList/VProfileCard.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
interface VProfileInfoProps {
image?: string;
id?: number;
name?: string;
age?: number;
shelter?: string;
state?: string;
export interface VProfileInfoProps {
profileImageUrl: string;
petId: number;
petName: string;
petAge: number;
shelterName: string;
adoptionStatus: string;
}

const VProfileCard = ({
image,
name,
age,
shelter,
state,
}: VProfileInfoProps) => (
<div className="flex items-center justify-center m-5 flex-nowrap">
<a href="/pet/1" className="flex items-center justify-center gap-6">
<img className="relative w-28 cursor-pointer" src={image} alt="" />
const VProfileCard = (vProfileInfoProps: VProfileInfoProps) => (
<div className="flex flex-col items-center justify-center m-5 flex-nowrap">
<a
href={`/pet/${vProfileInfoProps.petId}`}
className="flex items-center justify-center gap-6"
>
<img
className="relative w-28 cursor-pointer"
src={vProfileInfoProps.profileImageUrl}
alt=""
/>
<div className=" whitespace-nowrap">
<div className="flex flex-col-reverse">
{name} ({age})
{vProfileInfoProps.petName} ({vProfileInfoProps.petAge})
</div>
<div className="text-sm text-gray-400">{shelter}</div>
<div className="font-bold">{state}</div>
<div className="text-sm text-gray-400">
{vProfileInfoProps.shelterName}
</div>
<div className="font-bold">{vProfileInfoProps.adoptionStatus}</div>
</div>
</a>
<hr className="mt-5 w-full h-1"></hr>
</div>
);

Expand Down
49 changes: 35 additions & 14 deletions src/pages/profileList/VProfileListHome.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
import ProfileCard from 'pages/profileList/ProfileCard';

export interface SosListProps {
map(
arg0: (sosItem: any, index: any) => import('react/jsx-runtime').JSX.Element,
): import('react').ReactNode;
profileImageUrl: string;
petId: number;
petName: string;
petAge: number;
shelterName: string;
protectionExpirationDate: string;
}

export interface NewListProps {
map(
arg0: (newItem: any, index: any) => import('react/jsx-runtime').JSX.Element,
): import('react').ReactNode;
profileImageUrl: string;
petId: number;
petName: string;
petAge: number;
shelterName: string;
adoptionStatus: string;
}
export interface ProfileListProps {
image: string;
id: number;
name: string;
age: number;
shelter: string;
state: string;
sosListProps: SosListProps;
newListProps: NewListProps;
}

const VProfileListHome = (profileListProps: ProfileListProps) => {
Expand All @@ -22,10 +41,13 @@ const VProfileListHome = (profileListProps: ProfileListProps) => {
</a>
</h2>
<div className="grid grid-cols-1 gap-1 md:grid-cols-2 my-10 w-full whitespace-nowrap">
<ProfileCard {...profileListProps} />
<ProfileCard {...profileListProps} />
<ProfileCard {...profileListProps} />
<ProfileCard {...profileListProps} />
{profileListProps.sosListProps.map((sosItem, index) => (
<ProfileCard
key={index}
adoptionStatus={sosItem.protectionExpirationDate}
{...sosItem}
/>
))}
</div>
<h2 className="flex w-full font-bold text-xl sm:text-2xl justify-center items-center whitespace-nowrap">
신규 애니모리 친구들
Expand All @@ -37,10 +59,9 @@ const VProfileListHome = (profileListProps: ProfileListProps) => {
</a>
</h2>
<div className="grid grid-cols-1 gap-1 md:grid-cols-2 my-10 w-full whitespace-nowrap">
<ProfileCard {...profileListProps} />
<ProfileCard {...profileListProps} />
<ProfileCard {...profileListProps} />
<ProfileCard {...profileListProps} />
{profileListProps.newListProps.map((newItem, index) => (
<ProfileCard key={index} {...newItem} />
))}
</div>
</div>
);
Expand Down
93 changes: 63 additions & 30 deletions src/pages/profileList/newList/NewList.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,77 @@
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import VNewList, { PageNationProps, Props } from './VNewList';
import { ProfileListProps } from '../VProfileListHome';
import { useEffect, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import VNewList, { Props } from './VNewList';
import NewListSkeleton from './NewListSkeleton';

const NewList = () => {
const [currentPage, setCurrentPage] = useState(1); // 현재 페이지 상태
const navigate = useNavigate();
// 페이지 변경 함수
const handlePageChange = (page: number) => {
setCurrentPage(page);
navigate(`/profile/urgent/${page}`);
};
// const [list, setlist] = useState([]);

// useEffect(() => {
// fetch('public/data/profileHomeMock.json')
// .then((res) => res.json()) // javascript객체로 변환
// .then(setlist); // list에 저장
// }, []);
const profileListProps: ProfileListProps = {
image: '/assets/pet.png',
id: 1,
name: '보리',
age: 1,
shelter: '광주보호소',
state: '입양완료',
};
const pageNationProps: PageNationProps = {
currentPage, // 현재 페이지 상태를 전달
lastPage: 10,
maxLength: 7,
setCurrentPage: handlePageChange, // 페이지 변경 함수를 전달
navigate(`/profile/new/${page}`);
};

const props: Props = {
pageNationProps,
profileListProps,
const [newList, setNewList] = useState<Props | null>(null);

const getProfiles = async () => {
const response = await fetch(
`${process.env.REACT_APP_URI}/pet/profiles/new?page=${currentPage}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
},
);

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const json = await response.json();
return json.response;
};
// JSX를 VAC로 교체

return <VNewList {...props} />;
const { data, isLoading, isError } = useQuery({
queryKey: ['new-list', currentPage],
queryFn: getProfiles,
});

useEffect(() => {
if (!isLoading && !isError && data) {
const pageData = {
currentPage, // 현재 페이지 상태를 전달
lastPage: data.totalPages,
maxLength: 7,
setCurrentPage: handlePageChange,
};

const newListData = data.newList;

const newListProps: Props = {
pageNationProps: pageData,
profileListProps: newListData,
};

setNewList(newListProps);
}
}, [data, isLoading, isError]);

if (isLoading) {
return <NewListSkeleton />;
}

if (isError) {
return <div>Error: {isError}</div>;
}

if (newList) {
return <VNewList {...newList} />;
}

return null;
};

export default NewList;
Loading

0 comments on commit f70badb

Please sign in to comment.