Skip to content

Commit

Permalink
feat: 공연 기본 정보 기능 구현 (#41)
Browse files Browse the repository at this point in the history
* feat: 공연 기본 정보 UI 구현 및 공연 정보 입력 관련 폼 컴포넌트화

* feat: 공연 티켓 관리 UI 구현 및 공연 티켓 입력 관련 폼 컴포넌트화

* feat: 공연 기본 정보 수정 API 연동 및 폼 비활성화 구현

* feat: 공연 기본 정보 페이지에서 이탈 시, 입력한 정보 저장 여부 확인 기능 구현

* feat: 공연 삭제 API 연동 및 관련 기능 구현

* fix: ShowDetailLayout에서 상단 공연 제목의 모양이 어색하게 보이는 문제 수정
  • Loading branch information
Puterism authored Feb 13, 2024
1 parent 6746139 commit e0686a0
Show file tree
Hide file tree
Showing 36 changed files with 1,519 additions and 625 deletions.
3 changes: 2 additions & 1 deletion apps/admin/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import OAuthKakaoPage from './pages/OAuth/OAuthKakaoPage';
import ShowAddCompletePage from './pages/ShowAddCompletePage/ShowAddCompletePage';
import ShowAddPage from './pages/ShowAddPage/ShowAddPage';
import ShowInfoPage from './pages/ShowInfoPage/ShowInfoPage';
import ShowTicketPage from './pages/ShowTicketPage/ShowTicketPage';
import SignUpCompletePage from './pages/SignUpComplete/SignUpCompletePage';

const PublicRoute = () => {
Expand Down Expand Up @@ -84,7 +85,7 @@ const privateRoutes = [
{ path: PATH.SHOW_ADD, element: <ShowAddPage step="info" /> },
{ path: PATH.SHOW_ADD_TICKET, element: <ShowAddPage step="ticket" /> },
{ path: PATH.SHOW_INFO, element: <ShowInfoPage /> },
{ path: PATH.SHOW_TICKET, element: null },
{ path: PATH.SHOW_TICKET, element: <ShowTicketPage /> },
{ path: PATH.SHOW_RESERVATION, element: null },
{ path: PATH.SHOW_ENTRY, element: null },
{
Expand Down
30 changes: 30 additions & 0 deletions apps/admin/src/components/ShowDeleteForm/ShowDeleteForm.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import styled from '@emotion/styled';

const ShowDeleteForm = styled.form``;

const Description = styled.p`
${({ theme }) => theme.typo.b3};
color: ${({ theme }) => theme.palette.grey.g70};
margin-bottom: 28px;
`;

const TextFieldContainer = styled.div`
margin-bottom: 32px;
div {
width: 100%;
}
`;

const ButtonContainer = styled.div`
display: flex;
justify-content: flex-end;
gap: 8px;
`;

export default {
ShowDeleteForm,
Description,
TextFieldContainer,
ButtonContainer,
};
69 changes: 69 additions & 0 deletions apps/admin/src/components/ShowDeleteForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Button, TextField } from '@boolti/ui';
import { useState } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';

import Styled from './ShowDeleteForm.styles';

export interface ShowDeleteFormInputs {
showName: string;
}

interface ShowDeleteFormProps {
showName: string;
onSubmit: SubmitHandler<ShowDeleteFormInputs>;
}

const ShowDeleteForm = ({ showName, onSubmit }: ShowDeleteFormProps) => {
const { register, handleSubmit, watch } = useForm<ShowDeleteFormInputs>();

const [error, setError] = useState<string | null>(null);

const onSubmitForm: SubmitHandler<ShowDeleteFormInputs> = (data) => {
if (data.showName === showName) {
onSubmit(data);

return;
}

setError('정확한 공연명을 입력해주세요.');
};

return (
<Styled.ShowDeleteForm onSubmit={handleSubmit(onSubmitForm)}>
<Styled.Description>
삭제한 공연은 다시 되돌릴 수 없습니다.
<br />
삭제하시려면 정확한 공연명을 입력해 주세요.
</Styled.Description>
<Styled.TextFieldContainer>
<TextField
inputType="text"
size="big"
placeholder="공연명을 입력해 주세요"
errorMessage={error ?? undefined}
{...register('showName', {
required: true,
onChange: () => {
setError(null);
},
})}
/>
</Styled.TextFieldContainer>
<Styled.ButtonContainer>
<Button type="button" size="bold" colorTheme="line">
취소
</Button>
<Button
type="submit"
size="bold"
colorTheme="primary"
disabled={watch('showName', '').length === 0}
>
삭제
</Button>
</Styled.ButtonContainer>
</Styled.ShowDeleteForm>
);
};

export default ShowDeleteForm;
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const TopObserver = styled.div`

const HeaderObserver = styled.div`
position: absolute;
top: -130px;
top: calc(-197px + 68px - 40px);
left: 0;
width: 100%;
height: 1px;
Expand Down
41 changes: 33 additions & 8 deletions apps/admin/src/components/ShowDetailLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ import Styled from './ShowDetailLayout.styles.ts';
interface ShowDetailLayoutProps {
showName: string;
children?: React.ReactNode;
onClickMiddleware?: () => Promise<boolean>;
}

const ShowDetailLayout = ({ showName, children }: ShowDetailLayoutProps) => {
const ShowDetailLayout = ({ showName, children, onClickMiddleware }: ShowDetailLayoutProps) => {
const { ref: topObserverRef, inView: topInView } = useInView({
threshold: 1,
});
const { ref: headerObserverRef, inView: headerInView } = useInView({
threshold: 0.01,
threshold: 1,
initialInView: true,
});
const theme = useTheme();

Expand All @@ -45,7 +47,11 @@ const ShowDetailLayout = ({ showName, children }: ShowDetailLayoutProps) => {
<Styled.HeaderLeft>
<Styled.BackButton
type="button"
onClick={() => {
onClick={async () => {
if (onClickMiddleware && !(await onClickMiddleware())) {
return;
}

navigate(PATH.HOME);
}}
>
Expand All @@ -57,8 +63,11 @@ const ShowDetailLayout = ({ showName, children }: ShowDetailLayoutProps) => {
right={
<TextButton
onClick={async () => {
await logoutMutation.mutateAsync();
if (onClickMiddleware && !(await onClickMiddleware())) {
return;
}

await logoutMutation.mutateAsync();
navigate(PATH.LOGIN);
}}
>
Expand All @@ -71,39 +80,55 @@ const ShowDetailLayout = ({ showName, children }: ShowDetailLayoutProps) => {
<Styled.Tab>
<Styled.TabItem
active={matchInfoTab !== null}
onClick={() => {
onClick={async () => {
if (!params.showId) return;

if (onClickMiddleware && !(await onClickMiddleware())) {
return;
}

navigate(HREF.SHOW_INFO(params.showId));
}}
>
공연 기본 정보
</Styled.TabItem>
<Styled.TabItem
active={matchTicketTab !== null}
onClick={() => {
onClick={async () => {
if (!params.showId) return;

if (onClickMiddleware && !(await onClickMiddleware())) {
return;
}

navigate(HREF.SHOW_TICKET(params.showId));
}}
>
티켓 관리
</Styled.TabItem>
<Styled.TabItem
active={matchReservationTab !== null}
onClick={() => {
onClick={async () => {
if (!params.showId) return;

if (onClickMiddleware && !(await onClickMiddleware())) {
return;
}

navigate(HREF.SHOW_RESERVATION(params.showId));
}}
>
예매자 관리
</Styled.TabItem>
<Styled.TabItem
active={matchEntryTab !== null}
onClick={() => {
onClick={async () => {
if (!params.showId) return;

if (onClickMiddleware && !(await onClickMiddleware())) {
return;
}

navigate(HREF.SHOW_ENTRY(params.showId));
}}
>
Expand Down
Loading

0 comments on commit e0686a0

Please sign in to comment.