Skip to content

Commit

Permalink
Merge pull request #233 from Nexters/feature/show-info-form-renewal
Browse files Browse the repository at this point in the history
feat: 공연 기본 정보 변경 사항 적용
  • Loading branch information
Puterism authored Nov 2, 2024
2 parents 1abb8fa + 5cde6eb commit 1845811
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const ShowBasicInfoFormContent = ({

const { getRootProps, getInputProps } = useDropzone({
accept: {
'image/*': [],
'image/jpeg, image/png': [],
},
maxFiles: MAX_IMAGE_COUNT,
onDrop: onDropImage,
Expand Down Expand Up @@ -75,8 +75,9 @@ const ShowBasicInfoFormContent = ({
<Styled.ShowInfoFormContent>
<Styled.ShowInfoFormLabel required>공연 포스터</Styled.ShowInfoFormLabel>
<Styled.ShowInfoFormDescription>
원하시는 노출 순서대로 이미지를 업로드해주세요. 표준 종이규격(A, B)의 이미지를 권장합니다.<br />
(최소 1장, 최대 {MAX_IMAGE_COUNT}장 업로드 가능 / jpg, png 형식)
<span>원하시는 노출 순서대로 이미지를 업로드해주세요.&nbsp;</span>
<span>표준 종이규격(A, B)의 이미지를 권장합니다.</span><br />
<span>(최소 1장, 최대 {MAX_IMAGE_COUNT}장 업로드 가능 / jpg, png 형식)</span>
</Styled.ShowInfoFormDescription>
<Styled.PreviewImageContainer>
{imageFiles.map((file, index) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,21 @@ const ShowInfoFormDescription = styled.p`
color: ${({ theme }) => theme.palette.grey.g60};
margin-top: 2px;
span {
display: inline-block;
width: 100%;
}
strong {
font-weight: 600;
}
${mq_lg} {
span {
display: inline;
width: auto;
}
}
`;

const ShowInfoFormButtonContainer = styled.div`
Expand All @@ -130,21 +142,21 @@ const ShowInfoFormButton = styled(Button) <ShowInfoFormButtonProps>`

const PreviewImageContainer = styled.div`
display: grid;
grid-template-columns: repeat(3, 88px);
grid-template-columns: repeat(3, 1fr);
gap: 8px;
height: 124px;
margin-top: 16px;
aspect-ratio: 562 / 256;
${mq_lg} {
grid-template-columns: repeat(3, 1fr);
gap: 28px;
height: 256px;
aspect-ratio: initial;
}
`;

const PreviewImage = styled.div<{ isFirstImage: boolean }>`
max-width: 100%;
height: ${({ isFirstImage }) => (isFirstImage ? 'calc(124px - 16px)' : '124px')};
height: ${({ isFirstImage }) => (isFirstImage ? 'calc(100% - 16px)' : '100%')};
width: 100%;
background-size: cover;
background-repeat: no-repeat;
Expand All @@ -160,6 +172,7 @@ const PreviewImageWrap = styled.div<{ isFirstImage: boolean }>`
position: relative;
border-radius: 4px;
border: 1px solid ${({ theme }) => theme.palette.grey.g20};
aspect-ratio: 182 / 256;
`;

const FirstImageText = styled.span`
Expand Down Expand Up @@ -263,7 +276,7 @@ const FileUploadAreaText = styled.span`
const TextField = styled.div<TextFieldProps>`
margin-top: 8px;
display: flex;
align-items: start;
align-items: center;
gap: 8px;
flex: ${({ flex }) => flex};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,48 @@
import { TextField } from '@boolti/ui';
import { format, sub } from 'date-fns';
import { useState } from 'react';
import { Controller, UseFormReturn } from 'react-hook-form';

import Styled from './ShowInfoFormContent.styles';
import { ShowTicketFormInputs } from './types';

type ShowTicketFormRequiredInputs = Omit<ShowTicketFormInputs, 'ticketNotice'>;

interface ShowTicketInfoFormContentProps {
form: UseFormReturn<ShowTicketFormInputs>;
showDate: string;
salesMinStartDate?: string;
salesStartTime?: string;
disabled?: boolean;
}

const ShowTicketInfoFormContent = ({
form,
showDate,
salesMinStartDate,
salesStartTime,
disabled,
}: ShowTicketInfoFormContentProps) => {
const { watch, control } = form;
const { watch, control, formState: { errors }, setError, clearErrors } = form;

// TODO: react-hook-form의 에러 기능을 사용하도록 수정
const [hasBlurred, setHasBlurred] = useState<Record<keyof ShowTicketFormRequiredInputs, boolean>>(
{
startDate: false,
endDate: false,
},
);
const minStartDate = format(salesMinStartDate ?? new Date(), 'yyyy-MM-dd')
const minEndDate = format(
watch('startDate') ||
(salesStartTime ? new Date(salesStartTime) : new Date()),
'yyyy-MM-dd',
)
const maxDate = format(
sub(showDate ? new Date(showDate) : new Date(), { days: 1 }),
'yyyy-MM-dd',
)

return (
<Styled.ShowInfoFormGroup>
<Styled.ShowInfoFormGroupInfo>
<Styled.ShowInfoFormTitle>티켓 판매 정보</Styled.ShowInfoFormTitle>
<Styled.ShowInfoFormTitle>티켓 판매</Styled.ShowInfoFormTitle>
</Styled.ShowInfoFormGroupInfo>
<Styled.ShowInfoFormRow>
<Styled.ShowInfoFormContent>
<Styled.ShowInfoFormRow>
<Styled.ShowInfoFormResponsiveRowColumn>
<Styled.ShowInfoFormContent>
<Styled.ShowInfoFormLabel required>판매 시작일</Styled.ShowInfoFormLabel>
<Styled.ShowInfoFormLabel required>시작일</Styled.ShowInfoFormLabel>
<Styled.TextField>
<Controller
control={control}
Expand All @@ -51,30 +53,37 @@ const ShowTicketInfoFormContent = ({
<TextField
inputType="date"
size="big"
onChange={onChange}
onChange={(event) => {
onChange(event);
clearErrors('startDate');

if (new Date(event.target.value) < new Date(minStartDate)) {
setError('startDate', { type: 'min', message: '공연 생성일 이후의 날짜를 선택해 주세요.' });
return
}
}}
onBlur={() => {
onBlur();
setHasBlurred((prev) => ({ ...prev, startDate: true }));

if (!value) {
setError('startDate', { type: 'required', message: '필수 입력사항입니다.' });
return
}
}}
placeholder={value}
min={format(salesStartTime ?? new Date(), 'yyyy-MM-dd')}
max={format(
sub(showDate ? new Date(showDate) : new Date(), { days: 1 }),
'yyyy-MM-dd',
)}
min={minStartDate}
max={maxDate}
required
disabled={disabled}
errorMessage={
hasBlurred.startDate && !value ? '필수 입력사항입니다.' : undefined
}
errorMessage={errors.startDate?.message}
/>
)}
name="startDate"
/>
</Styled.TextField>
</Styled.ShowInfoFormContent>
<Styled.ShowInfoFormContent>
<Styled.ShowInfoFormLabel required>판매 종료일</Styled.ShowInfoFormLabel>
<Styled.ShowInfoFormLabel required>종료일</Styled.ShowInfoFormLabel>
<Styled.TextField>
<Controller
control={control}
Expand All @@ -85,33 +94,41 @@ const ShowTicketInfoFormContent = ({
<TextField
inputType="date"
size="big"
onChange={onChange}
onChange={(event) => {
onChange(event);
clearErrors('endDate');

if (new Date(event.target.value) < new Date(minEndDate)) {
setError('endDate', { type: 'min', message: '시작일 이후로 선택 가능합니다.' });
return
}

if (new Date(event.target.value) > new Date(maxDate)) {
setError('endDate', { type: 'max', message: '공연 전날까지 선택 가능합니다.' });
return
}
}}
onBlur={() => {
onBlur();
setHasBlurred((prev) => ({ ...prev, endDate: true }));

if (!value) {
setError('endDate', { type: 'required', message: '필수 입력사항입니다.' });
return
}
}}
placeholder={value}
min={format(
watch('startDate') ||
(salesStartTime ? new Date(salesStartTime) : new Date()),
'yyyy-MM-dd',
)}
max={format(
sub(showDate ? new Date(showDate) : new Date(), { days: 1 }),
'yyyy-MM-dd',
)}
min={minEndDate}
max={maxDate}
required
disabled={disabled}
errorMessage={
hasBlurred.endDate && !value ? '필수 입력사항입니다.' : undefined
}
errorMessage={errors.endDate?.message}
/>
)}
name="endDate"
/>
</Styled.TextField>
</Styled.ShowInfoFormContent>
</Styled.ShowInfoFormRow>
</Styled.ShowInfoFormResponsiveRowColumn>
</Styled.ShowInfoFormContent>
</Styled.ShowInfoFormRow>
<Styled.ShowInfoFormRow>
Expand Down
1 change: 1 addition & 0 deletions apps/admin/src/pages/ShowTicketPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const ShowTicketPage = () => {
form={showTicketForm}
showDate={format(show.date, 'yyyy-MM-dd')}
salesStartTime={format(showSalesInfo.salesStartTime, 'yyyy-MM-dd')}
salesMinStartDate={show.createdAt}
disabled={show.isEnded}
/>
</Styled.ShowTicketFormContent>
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/types/show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface ShowResponse {
host: Host;
isEnded: boolean;
settlementStatus: 'SETTLEMENT_REQUIRED' | 'SETTLEMENT_REQUEST' | 'SETTLEMENT_DONE' | null;
createdAt: string;
}

export type ShowSummaryResponse = Array<{
Expand Down

0 comments on commit 1845811

Please sign in to comment.