Skip to content

Commit

Permalink
feat: implement rental management page
Browse files Browse the repository at this point in the history
  • Loading branch information
CH4MD0M committed Feb 4, 2025
1 parent be6dac5 commit 7b5fb2f
Show file tree
Hide file tree
Showing 8 changed files with 463 additions and 4 deletions.
28 changes: 27 additions & 1 deletion src/api/rentalApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { endPoint } from 'constants/endPoint';
import type { DepositFormResponse, PageParam } from 'types';
import type { RentalAccountResponse, RentalDetailResponse, RentalListResponse } from 'types';
import type {
RentalAccountResponse,
RentalDetailResponse,
RentalListResponse,
ManagingRentalListResponse,
ManagingRentalDetailResponse,
} from 'types';
import { publicAxios, tokenAxios } from 'utils';

export const createRentalQuery = (filterQuery: string, pageParam: PageParam) => {
Expand Down Expand Up @@ -29,3 +35,23 @@ export const requestGetDepositAccount = async (id: string) => {
export const requestPostDepositForm = async (formData: string) => {
return await tokenAxios.post<DepositFormResponse>(`${endPoint.APPLY_RENT_FORM}`, formData);
};

export const requestGetManagingRentalList = async () => {
const { data } = await tokenAxios.get<ManagingRentalListResponse>(endPoint.GET_CREATED_RENT_LIST);
return data.result;
};

export const requestGetManagingRentalDetail = async (id: string, boardingDate: string) => {
const { data } = await tokenAxios.get<ManagingRentalDetailResponse>(
endPoint.GET_CREATED_RENT_DETAIL(id),
{
params: {
boardingDate,
},
}
);

return data;
};

export const requestGetParticipatingRentalList = () => {};
18 changes: 16 additions & 2 deletions src/components/badge/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,18 @@ type BadgeColor = 'gray' | 'red';
interface BadgeStyle {
variant: BadgeVariant;
size: BadgeSize;
color: BadgeColor;
color?: BadgeColor;
}

interface BadgeProps extends BadgeStyle {
children: string;
}

const DefaultStyle = (theme: Theme) => css`
background-color: ${theme.colors.primary};
color: ${theme.colors.white};
`;

const GrayStyle = (theme: Theme) => css`
background-color: ${theme.colors.dark[500]};
color: ${theme.colors.white};
Expand All @@ -29,6 +34,15 @@ const RedStyle = (theme: Theme) => css`
color: ${theme.colors.red};
`;

const getColorStyle = (color: BadgeColor | undefined, theme: Theme) => {
const styles = {
gray: GrayStyle(theme),
red: RedStyle(theme),
};

return color ? styles[color] : DefaultStyle(theme);
};

const BadgeContainer = styled.div<BadgeStyle>`
display: flex;
justify-content: center;
Expand All @@ -39,7 +53,7 @@ const BadgeContainer = styled.div<BadgeStyle>`
padding: ${({ size }) => (size === 'medium' ? '0 1.2rem' : '0 .8rem')};
border-radius: ${({ variant }) => (variant === 'round' ? '24px' : '4px')};
${({ color, theme }) => (color === 'gray' ? GrayStyle(theme) : RedStyle(theme))}
${({ color, theme }) => getColorStyle(color, theme)}
`;

const Badge = ({ variant, size, color, children }: BadgeProps) => {
Expand Down
62 changes: 62 additions & 0 deletions src/pages/managingRentalDetail/ManagingRentalDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import styled from '@emotion/styled';
import { useSuspenseQuery } from '@tanstack/react-query';
import { useParams } from 'react-router-dom';

import { requestGetManagingRentalDetail } from 'api';
import Badge from 'components/badge/Badge';

const ManagingRentalDetail = () => {
const { id } = useParams();

const { data: managingRentalDetail } = useSuspenseQuery({
queryKey: ['managingRentalDetail'],
queryFn: async () => {
const data = await requestGetManagingRentalDetail(id as string, '2025-01-18');
return data.result;
},
});

console.log(managingRentalDetail);

return (
<Wrapper>
<TitleWrapper>
<Title>{managingRentalDetail.title}</Title>
<Badge size="medium" variant="square">
{managingRentalDetail.isClosed ? '마감' : '모집중'}
</Badge>
</TitleWrapper>
</Wrapper>
);
};

const Wrapper = styled.div`
padding: 2.4rem;
`;

const TitleWrapper = styled.div`
display: flex;
align-items: flex-start;
gap: 1.2rem;
`;

const StatusBadge = styled.span`
display: inline-block;
padding: 0.4rem 0.8rem;
background: #6366f1;
border-radius: 0.4rem;
font-size: 1.2rem;
flex-shrink: 0;
`;

const Title = styled.h1`
font-size: 1.8rem;
font-weight: bold;
flex: 1;
`;

const HeaderSection = styled.div``;

const InfoSection = styled.div``;

export default ManagingRentalDetail;
138 changes: 138 additions & 0 deletions src/pages/managingRentalDetail/components/RentalItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import styled from '@emotion/styled';
import { LuCalendar } from 'react-icons/lu';
import { PiMapPin } from 'react-icons/pi';

import { CaptionText, ChipText, TitleText2 } from 'styles/Typography';
import type { ManagingRental } from 'types';

interface RentalItemProps {
rental: ManagingRental;
}

const RentalItem = ({ rental }: RentalItemProps) => {
return (
<Container>
<TitleSection>
<TitleText2>{rental.title}</TitleText2>
</TitleSection>

<InfoWrapper>
<InfoGroup>
<InfoLabel>
<LuCalendar size={16} />
<ChipText>공연일</ChipText>
</InfoLabel>
<CaptionText>{rental.boardingDate}</CaptionText>
</InfoGroup>
<InfoGroup>
<InfoLabel>
<PiMapPin size={16} />
<ChipText>출발지</ChipText>
</InfoLabel>
<CaptionText>{rental.boardingArea}</CaptionText>
</InfoGroup>
</InfoWrapper>

<RecruitmentPeriod>
<CaptionText>{rental.isClosed ? '차량 대절 마감' : '차량 대절 진행중'}</CaptionText>
<CaptionText>
{new Date(rental.rentStartDate).toLocaleDateString()} ~
{new Date(rental.rentEndDate).toLocaleDateString()}
</CaptionText>
</RecruitmentPeriod>

<ProgressSection>
<InfoWrapper>
<CaptionText>전체 신청 인원</CaptionText>
<CaptionText>
{rental.participationCount} / {rental.recruitmentCount}
</CaptionText>
</InfoWrapper>
<ProgressBar>
<ProgressFill
style={{
width: `${(rental.participationCount / rental.recruitmentCount) * 100}%`,
}}
/>
</ProgressBar>
</ProgressSection>
</Container>
);
};

// 카드 컨테이너
const Container = styled.div`
background-color: ${({ theme }) => theme.colors.dark[700]};
display: flex;
flex-direction: column;
gap: 1.6rem;
border-radius: 0.5rem;
padding: 1.6rem;
color: white;
width: 100%;
`;

// 제목 영역
const TitleSection = styled.div`
margin-bottom: 1rem;
`;

const InfoWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
gap: 0.8rem;
`;

const InfoLabel = styled.span`
color: ${({ theme }) => theme.colors.primary};
display: flex;
align-items: center;
gap: 0.4rem;
`;

const InfoGroup = styled.div`
color: ${({ theme }) => theme.colors.white};
display: flex;
flex-grow: 1;
flex-direction: column;
background-color: ${({ theme }) => theme.colors.dark[500]};
padding: 0.8rem;
gap: 0.4rem;
border-radius: 4px;
`;

// 프로그레스 바 영역
const ProgressSection = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
color: ${({ theme }) => theme.colors.dark[50]};
`;

const ProgressBar = styled.div`
background-color: #e1e3e8;
border-radius: 9999px;
height: 1rem;
`;

const ProgressFill = styled.div`
background-color: ${({ theme }) => theme.colors.primary};
height: 100%;
border-radius: 9999px;
transition: width 0.3s ease;
`;

// 모집 기간 영역
const RecruitmentPeriod = styled.div`
display: flex;
align-items: center;
gap: 0.4rem;
color: ${({ theme }) => theme.colors.dark[200]};
span:first-child {
color: ${({ theme }) => theme.colors.red};
}
`;

export default RentalItem;
28 changes: 27 additions & 1 deletion src/pages/myRentalManagement/MyRentalManagement.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
import styled from '@emotion/styled';
import { useQuery } from '@tanstack/react-query';

import RentalItem from './components/RentalItem';

import { requestGetManagingRentalList } from 'api';

const MyRentalManagement = () => {
return <div>MyRentalManagement</div>;
const {
data: managingRentalList,
isLoading,
error,
} = useQuery({
queryKey: ['managingRentals'],
queryFn: requestGetManagingRentalList,
});

return (
<Wrapper>
{managingRentalList?.map((rental) => {
return <RentalItem key={rental.rentId} rental={rental} />;
})}
</Wrapper>
);
};

const Wrapper = styled.div`
padding: 2.4rem;
`;

export default MyRentalManagement;
Loading

0 comments on commit 7b5fb2f

Please sign in to comment.