Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

요청주제관리 페이지 UI 수정 및 API 연동 #285

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,74 @@
import { style } from '@vanilla-extract/css';
import { style, styleVariants } from '@vanilla-extract/css';
import { vars } from '@/styles/theme.css';
import * as fonts from '@/styles/font.css';

export const bodyRow = style([
fonts.Label,
{
padding: '1rem 0.5rem',
marginBottom: '1rem',
borderBottom: `1px solid ${vars.color.bluegray6}`,

display: 'grid',
gridTemplateColumns: 'repeat(8, 1fr)',
alignItems: 'center',

textAlign: 'center',
},
]);

export const rowItem = style({
gridColumn: 'span 2',

display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
});

export const rowText = style({
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
});

export const buttons = style({
display: 'flex',
justifyContent: 'center',
gap: '0.5rem',

whiteSpace: 'nowrap',
});

const button = style({
padding: '0.5rem 1rem',
borderRadius: '4px',
backgroundColor: vars.color.blue,
color: vars.color.white,

whiteSpace: 'nowrap',

':hover': {
opacity: 0.7,
},
});

export const variantsButton = styleVariants({
default: [button],
disabled: [
button,
{
opacity: 0.7,
cursor: 'default',
},
],
});

export const modal = style({
width: '100%',
height: '100vh',
overflow: 'scroll',
});

export const container = style({
width: '100%',
padding: '12px',
Expand Down Expand Up @@ -39,28 +106,22 @@ export const buttonWrapper = style({
gap: '10px',
});

export const button = style({
padding: '6px 12px',

width: '80px',

display: 'flex',
alignItems: 'center',
justifyContent: 'center',

flexShrink: 0,

borderRadius: '14px',
});

export const exposeToggleButton = style([
export const exposedButton = style([
button,
{
backgroundColor: vars.color.blue,
color: vars.color.white,
},
]);

export const notExposedButton = style([
button,
{
backgroundColor: vars.color.lightgray,
color: vars.color.white,
},
]);

export const editButton = style([
button,
{
Expand Down
87 changes: 87 additions & 0 deletions src/app/admin/topics/_components/AdminTopicBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use client';
import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';

import BottomSheet from './BottomSheet';

import { RequestedTopicType } from '@/lib/types/requestedTopicType';
import editAdminTopic from '@/app/_api/adminTopics/editAdminTopic';
import formatDate from '@/lib/utils/dateFormat';
import getCategories from '@/app/_api/category/getCategories';
import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import { CategoryType } from '@/lib/types/categoriesType';

import * as styles from './AdminTopicBox.css';

interface TopicBoxProps {
topic: RequestedTopicType;
}

function TopicBox({ topic }: TopicBoxProps) {
const queryClient = useQueryClient();
const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false);

Comment on lines +22 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useBooleanOutput() 훅을 사용해서 추후 리팩토링하면 좋을 것 같습니당✨👍

const editTopicMutation = useMutation({
mutationFn: () =>
editAdminTopic({
topicId: topic?.id,
isExposed: !topic.isExposed,
title: topic?.title,
categoryCode: topic?.categoryCode,
}),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.getAdminTopics],
});
},
});

const handleClickEditButton = () => {
setIsBottomSheetOpen(true);
};

const handleToggleExposeButton = () => {
editTopicMutation.mutate();
};

return (
<>
<tr className={styles.bodyRow}>
<td>{formatDate(topic?.createdDate)}</td>
<td>{topic?.categoryKorName}</td>
<td className={styles.rowItem}>
<span className={styles.rowText}>{topic?.title}</span>
<span className={styles.rowText}>{topic?.description}</span>
</td>
<td className={styles.buttons}>
<span className={styles.rowText}>{topic?.isAnonymous ? 'O' : 'X'}</span>
</td>
Comment on lines +56 to +58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 나현님, 클론 받아서 테스트해보니 요청 주제를 '익명'으로 만들었을때도 리스폰스에서는 isAnonymous 필드 값이 false로 보여집니다. 이 부분 수정이 필요할 것 같아요~!
  2. 요청 주제 생성시 노출값이 default로 true인 것이 맞을까요? 검토 후 보여지는 플로우인것 같아서 확인차 여쭤봅니다.
  3. (의견) 테이블 제목을 '익명' 대신 만든사람 닉네임을 두는 것이 어떨까요? 리스폰스로 해당값이 내려가기도 하고, 관리자가 주제 요청한 사용자에 대해 알아야할 것 같아서요~! 다만, 익명일때만 사용자아이디(익명 요청) 이런식으로 표현해도 될 것 같아요,,

<td className={styles.buttons}>
<button className={styles.editButton} onClick={handleClickEditButton}>
수정하기
</button>
</td>
<td>
<select onChange={handleToggleExposeButton} value={topic?.isExposed ? '공개' : '비공개'}>
<option>공개</option>
<option>비공개</option>
</select>
</td>
Comment on lines +64 to +69
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(의견) 혹시 요청 주제 관리 페이지에서 토글로 노출상태를 바로 변경하는 기능을 두신 이유가 무엇인지 궁금합니당 👀
공지의 경우는 생성/수정 필드와 노출 관련 API가 분리되어 있는 상황이었는데, 요청 주제 관리는 수정 바텀시트에서 함께 수정할 수 있을 것 같다는 생각이 들어서요~! 중복 코드도 제거할 수 있고, 사용성 면에서도 불편함이 없을 것 같아서 제안드려봅니다!

</tr>

{isBottomSheetOpen && (
<BottomSheet
onClose={() => {
setIsBottomSheetOpen(false);
}}
topicTitle={topic?.title}
category={topic?.categoryKorName}
isExposed={topic?.isExposed}
topicId={topic?.id}
/>
)}
</>
);
}

export default TopicBox;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 파일은 삭제해야 하는 파일이 맞을까요?! 👀

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@

import * as styles from './BottomSheet.css';
import { MouseEventHandler, useState } from 'react';
import { useMutation, useQuery } from '@tanstack/react-query';
import { useUser } from '@/store/useUser';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import useOnClickOutside from '@/hooks/useOnClickOutside';
import getCategories from '@/app/_api/category/getCategories';
import editAdminTopic from '@/app/_api/adminTopics/editAdminTopic';

import { CategoryType } from '@/lib/types/categoriesType';
import ArrowDown from '/public/icons/down_chevron.svg';
import useBooleanOutput from '@/hooks/useBooleanOutput';
import Modal from '@/components/Modal/Modal';

interface BottomSheetProps {
onClose: MouseEventHandler<HTMLDivElement>;
onClose: () => void;
topicTitle: string;
category: string;
isExposed: boolean;
topicId: number;
}
// TODO: 컴포넌트 공통화 작업
function BottomSheet({ onClose, topicTitle, category, isExposed }: BottomSheetProps) {
function BottomSheet({ onClose, topicTitle, category, isExposed, topicId }: BottomSheetProps) {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const { isOn: isModalOn, handleSetOn: openModal, handleSetOff: closeModal } = useBooleanOutput(false);
const queryClient = useQueryClient();

const [title, setTitle] = useState(topicTitle);
const [selectedCategory, setSelectedCategory] = useState<string>(category);
Expand All @@ -35,17 +33,26 @@ function BottomSheet({ onClose, topicTitle, category, isExposed }: BottomSheetPr
queryFn: getCategories,
});

const convertCategoryKorNameToCode = (korName: string) => {
const category = categories?.find((cat) => cat.korName === korName);
return category ? category.code : null; // 찾지 못하면 null 반환
};

const editTopicMutation = useMutation({
// mutationFn: () =>
// editAdminTopic({
// isExposed,
// title,
// categoryCode,
// }),
mutationFn: () =>
editAdminTopic({
topicId,
isExposed,
title,
categoryCode: convertCategoryKorNameToCode(selectedCategory as string) || '',
}),
Comment on lines +36 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후 리팩토링 하실 때 드롭다운을 ul, li태그가 아닌 select 태그를 사용하는 것으로 수정하면 카테고리 선택하고, 뮤테이션에 넣어주는 부분에 대해 코드 가독성면에서 좋을 것 같아요, 아래 코드 참고 부탁드립니당

// 제거
// const convertCategoryKorNameToCode = (korName: string) => {
//  const category = categories?.find((cat) => cat.korName === korName);
//  return category ? category.code : null; // 찾지 못하면 null 반환
//  };

  const editTopicMutation = useMutation({
    mutationFn: () =>
      editAdminTopic({
        ...
        categoryCode: selectedCategory, // 수정
      }),
    ...
    },
  });

return (
   <select ... onChange={(e: ChangeEvent<HTMLSelectElement>) => setSelectedCategory(e.target.value)}>
    {categories?.map((category) => (
      <option ... value={category.code}>{category.korName}</option>))}
  </select>
)

onSuccess: () => {
setTitle('');
setSelectedCategory(selectedCategory);
openModal();
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.getAdminTopics],
});
onClose();
},
onError: (error) => {
setErrorMessage('요청 중 오류가 발생했습니다. 다시 시도해 주세요. :(');
Expand Down Expand Up @@ -131,24 +138,10 @@ function BottomSheet({ onClose, topicTitle, category, isExposed }: BottomSheetPr
</div>

<button type="submit" className={styles.submitButton} disabled={!title || title.length > 30}>
요청 보내기
수정하기
</button>
</form>
</div>
{isModalOn && (
<Modal handleModalClose={closeModal} size="large">
<div className={styles.modalText}>{`요청 주제 수정이 완료되었어요.`} </div>
<button
className={styles.modalButton}
onClick={() => {
closeModal();
setIsDropdownOpen(false); //실행안됨
}}
>
닫기
</button>
</Modal>
)}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { vars } from '@/styles/theme.css';
import * as fonts from '@/styles/font.css';

export const body = style({
width: '100vw',
width: '100%',
minHeight: '100vh',
padding: '16px 16px 120px',

Comment on lines -6 to 9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래처럼 높이가 보여져서 수정이 필요할 것 같아요.

    width: 100%;
    height: 100%; 
    padding: 1.5rem; // 패딩 수정
    /* position: relative; */ //제거
    /* overflow-y: auto; // 제거

image

Expand Down Expand Up @@ -87,3 +87,36 @@ export const page = style([
color: vars.color.bluegray6,
},
]);

export const table = style({
maxWidth: '850px',
padding: '1rem',

display: 'flex',
flexDirection: 'column',
gap: '1rem',

backgroundColor: vars.color.white,
borderRadius: '8px',
});

Comment on lines +91 to +102
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 스타일 파일에 사용하지 않는 클래스네임이 많은 것 같아서 제거하면 좋을 것 같습니당!

export const headRow = style([
fonts.BodyRegular,
{
padding: '1rem 0.5rem',

display: 'grid',
gridTemplateColumns: 'repeat(8, 1fr)',
alignItems: 'center',

textAlign: 'center',
},
]);

export const rowItem = style({
gridColumn: 'span 2',

display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
});
Loading
Loading