From 4c2b23f2a50347474b9e38ba4ee13237d9ec98ce Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Mon, 21 Jul 2025 20:47:17 +0900 Subject: [PATCH 1/8] =?UTF-8?q?refactor=20:=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=97=90=EC=84=9C=20"=EB=AA=A8=EC=A7=91=20?= =?UTF-8?q?=EC=9D=B8=EC=9B=90"=EA=B3=BC=20"=EC=98=88=EC=83=81=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=84"=20input=20=EC=99=BC=EC=AA=BD=20=EC=A0=95=EB=A0=AC=20?= =?UTF-8?q?+=20=EB=8B=A8=EC=9C=84=20=EC=B6=94=EA=B0=80=20+=20=EC=9D=8C?= =?UTF-8?q?=EC=88=98=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inputComponent/InputComponent.styled.ts | 40 ++++++++++---- .../inputComponent/InputComponent.tsx | 52 ++++++++++++++++++- src/constants/user/projectConstants.ts | 36 +++++++++---- .../user/createProject/CreateProject.tsx | 4 +- .../user/modifyProject/ModifyProject.tsx | 6 +-- 5 files changed, 110 insertions(+), 28 deletions(-) diff --git a/src/components/user/projectFormComponents/inputComponent/InputComponent.styled.ts b/src/components/user/projectFormComponents/inputComponent/InputComponent.styled.ts index 3d19b40b..41ed1fff 100644 --- a/src/components/user/projectFormComponents/inputComponent/InputComponent.styled.ts +++ b/src/components/user/projectFormComponents/inputComponent/InputComponent.styled.ts @@ -6,15 +6,34 @@ export const InputContainer = styled.div` flex-direction: column; `; -export const InputStyle = styled.input<{ type?: string }>` +export const InputWrapper = styled.div` + display: flex; + align-items: center; + gap: 2px; +`; + +export const UnitText = styled.span` + font-size: ${({ theme }) => theme.heading.xsSmall.fontSize}; + color: ${({ theme }) => theme.color.deepGrey}; + white-space: nowrap; +`; + +export const InputStyle = styled.input<{ type?: string; name?: string }>` padding: 10px; border: 1px solid ${({ theme }) => theme.color.border}; border-radius: ${({ theme }) => theme.borderRadius.primary}; font-size: ${({ theme }) => theme.heading.small.fontSize}; - ${({ type }) => { + ${({ type, name }) => { switch (type) { case 'text': + if (name === 'maxVolunteers' || name === 'duration') { + return css` + width: 60px; + text-align: right; + border-radius: 13px; + `; + } return css` width: 100%; border-radius: 13px; @@ -40,19 +59,20 @@ export const InputStyle = styled.input<{ type?: string }>` }} `; -export const InputInfoStyle = styled.input<{ type?: string }>` +export const InputInfoStyle = styled.input<{ type?: string; name?: string }>` font-size: ${({ theme }) => theme.heading.small.fontSize}; border: none; - ${({ type }) => { + ${({ type, name }) => { switch (type) { case 'text': - return css` - width: 220px; - text-align: left; - padding-left: 1px; - `; - case 'number': + if (name === 'maxVolunteers' || name === 'duration') { + return css` + width: 30px; + text-align: right; + padding-left: 1px; + `; + } return css` width: 220px; text-align: left; diff --git a/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx b/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx index d73c3233..1ab3287b 100644 --- a/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx +++ b/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx @@ -3,12 +3,15 @@ import * as S from './InputComponent.styled'; import MdEditorInput from '../editor/MarkdownEditor'; type InputProps = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any control: Control; name: string; placeholder?: string; errors?: FieldErrors; type?: 'text' | 'date' | 'textarea' | 'number' | string; indexInfo?: string; + unit?: string; + min?: number; }; const Input = ({ @@ -18,6 +21,8 @@ const Input = ({ placeholder, type, indexInfo, + unit, + min = 0, }: InputProps) => { const { field } = useController({ control, @@ -25,10 +30,41 @@ const Input = ({ }); const hasError = Boolean(errors?.[name]); + const handleInputChange = (e: React.ChangeEvent) => { + const value = e.target.value; + + // 숫자 입력 필드인 경우 숫자만 허용 + if (name === 'maxVolunteers' || name === 'duration') { + // 숫자가 아닌 문자 제거 + const numericValue = value.replace(/[^0-9]/g, ''); + if (numericValue !== value) { + e.target.value = numericValue; + } + + // 음수 방지 (0보다 작은 값은 허용하지 않음) + const numValue = Number(numericValue); + if (numValue < min) { + return; + } + } + + field.onChange(e); + }; + const renderInput = () => { if (indexInfo) { return ( - + + + {unit && {unit}} + ); } @@ -36,7 +72,19 @@ const Input = ({ return ; } - return ; + return ( + + + {unit && {unit}} + + ); }; return ( diff --git a/src/constants/user/projectConstants.ts b/src/constants/user/projectConstants.ts index d0f89be4..f87f5615 100644 --- a/src/constants/user/projectConstants.ts +++ b/src/constants/user/projectConstants.ts @@ -7,8 +7,8 @@ export const PROJECT_DATA = [ id: '1', name: 'maxVolunteers', label: '모집 인원', - type: 'number', - placeholder: '모집 인원을 입력하세요. (ex. 5)', + type: 'text', + unit: '명', }, { id: '2', @@ -16,14 +16,15 @@ export const PROJECT_DATA = [ label: '시작 예정', type: 'text', placeholder: 'YYYY-MM-DD', + unit: '', }, { id: '3', name: 'duration', label: '예상 기간', - type: 'number', - placeholder: '예상 기간을 입력하세요. (ex. 5)', + type: 'text', + unit: '개월', }, { @@ -32,6 +33,7 @@ export const PROJECT_DATA = [ label: '새싹 여부', type: 'checkbox', placeholder: '', + unit: '', }, ] as const; @@ -74,20 +76,32 @@ export const createProjectScheme = z.object({ .string({ message: '프로젝트 제목을 입력해주세요.' }) .min(1, { message: '프로젝트 제목을 입력해주세요.' }), - maxVolunteers: z.coerce + maxVolunteers: z .number({ message: '모집 인원을 입력해주세요.' }) - .min(1, { message: '모집 인원은 1명 이상이어야 합니다.' }) - .max(1000, { message: '모집 인원은 1000명 이하이어야 합니다.' }), + .min(1, { message: '모집 인원을 입력해주세요.' }) + .refine( + (val) => { + const num = Number(val); + return !isNaN(num) && num >= 1 && num <= 1000; + }, + { message: '모집 인원은 1명 이상 1000명 이하여야 합니다.' } + ), startDatePre: z .string({ required_error: '종료 날짜를 입력해주세요.' }) .refine((date) => !isNaN(Date.parse(date)), { message: '유효한 날짜를 입력해주세요.', }), field: z.number({ message: '진행 방식을 선택 해주세요.' }), - duration: z.coerce - .number({ message: '예상 기간을 입력해주세요.' }) - .positive({ message: '예상 기간은 1 이상이어야 합니다.' }) - .max(365, { message: '예상 기간은 365일을 초과할 수 없습니다.' }), + duration: z + .string({ message: '예상 기간을 입력해주세요.' }) + .min(1, { message: '예상 기간을 입력해주세요.' }) + .refine( + (val) => { + const num = Number(val); + return !isNaN(num) && num >= 1 && num <= 365; + }, + { message: '예상 기간은 1일 이상 365일 이하여야 합니다.' } + ), position: z .array(z.number({ message: '숫자로 입력 되어야 합니다.' })) .min(1, { message: '1개의 분야를 선택해주세요.' }), diff --git a/src/pages/user/createProject/CreateProject.tsx b/src/pages/user/createProject/CreateProject.tsx index 0abaed9c..351c785f 100644 --- a/src/pages/user/createProject/CreateProject.tsx +++ b/src/pages/user/createProject/CreateProject.tsx @@ -43,12 +43,12 @@ const CreateProject = () => { const handleSubmit = (data: z.infer) => { const formData: FormData = { title: data.title, - totalMember: data.maxVolunteers, + totalMember: Number(data.maxVolunteers), recruitmentStartDate: data.startDate, recruitmentEndDate: data.endDate, startDate: data.startDatePre, positionTagIds: data.position, - estimatedPeriod: `${data.duration}개월`, + estimatedPeriod: `${Number(data.duration)}개월`, methodTypeId: data.field, isBeginner: data.newBy, skillTagIds: data.languages, diff --git a/src/pages/user/modifyProject/ModifyProject.tsx b/src/pages/user/modifyProject/ModifyProject.tsx index 609f240f..7f429650 100644 --- a/src/pages/user/modifyProject/ModifyProject.tsx +++ b/src/pages/user/modifyProject/ModifyProject.tsx @@ -57,7 +57,7 @@ const ModifyProject = () => { setValue('title', projectData.title); setValue('newBy', projectData.isBeginner); setValue('maxVolunteers', projectData.totalMember); - setValue('duration', Number(projectData.estimatedPeriod.slice(0, 1))); + setValue('duration', projectData.estimatedPeriod.slice(0, 1)); setValue('markdownEditor', projectData.description); } }, [projectData, setValue]); @@ -73,12 +73,12 @@ const ModifyProject = () => { const handleSubmit = async (data: z.infer) => { const formData: FormData = { title: data.title, - totalMember: data.maxVolunteers, + totalMember: Number(data.maxVolunteers), recruitmentStartDate: data.startDate, recruitmentEndDate: data.endDate, startDate: data.startDatePre, positionTagIds: data.position, - estimatedPeriod: `${data.duration}개월`, + estimatedPeriod: `${Number(data.duration)}일`, methodTypeId: data.field, isBeginner: data.newBy, skillTagIds: data.languages, From cc041cd69a12992a937b94253303dc146ed015d6 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Mon, 21 Jul 2025 20:48:27 +0900 Subject: [PATCH 2/8] =?UTF-8?q?refactor=20:=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=97=90=EC=84=9C=20"=EB=AA=A8=EC=A7=91=20?= =?UTF-8?q?=EB=B6=84=EC=95=BC"=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectInformationInput.styled.ts | 7 ++++ .../ProjectInformationInput.tsx | 42 ++++++++++--------- .../user/ProjectHooks/useTagSelectors.ts | 33 ++++++++++++--- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.styled.ts b/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.styled.ts index 5aaa430f..08bc9a32 100644 --- a/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.styled.ts +++ b/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.styled.ts @@ -17,6 +17,13 @@ export const InfoLabel = styled.label` color: #333; `; +export const LabelDescription = styled.span` + font-size: ${({ theme }) => theme.heading.xsSmall.fontSize}; + color: ${({ theme }) => theme.color.grey}; + font-weight: normal; + margin-left: 8px; +`; + export const welcomeSprout = styled.p` font-size: 1rem; font-weight: bold; diff --git a/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.tsx b/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.tsx index b3a89955..0dac716e 100644 --- a/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.tsx +++ b/src/components/user/projectFormComponents/projectInformationInput/ProjectInformationInput.tsx @@ -27,24 +27,23 @@ const ProjectInformationInput = ({ return ( <> {PROJECT_DATA.map((input, index) => ( - <> - - {input.label} - - {input.type === 'checkbox' && ( - - 새싹 멤버를 환영한다면 체크를 눌러주세요!! - - )} - - + + {input.label} + + {input.type === 'checkbox' && ( + + 새싹 멤버를 환영한다면 체크를 눌러주세요!! + + )} + ))} @@ -59,7 +58,12 @@ const ProjectInformationInput = ({ /> - 모집 분야 + + 모집 분야 + + 전체를 클릭하면 다른 카테고리가 해제됩니다 ! + + { - if (prev.includes(1) && idx !== 1) { - return prev; + // 전체(인덱스 1)를 클릭하는 경우 + if (idx === 1) { + // 이미 전체가 선택되어 있으면 해제 + if (selectedTag.includes(1)) { + const updated = selectedTag.filter((item) => item !== 1); + setSelectedTag(updated); + setValue(fieldName, updated); + return; + } + + // 다른 카테고리가 선택되어 있으면 확인 메시지 표시 + if (selectedTag.length > 0 && !selectedTag.includes(1)) { + const confirmed = window.confirm('선택된 카테고리가 해제됩니다.'); + if (!confirmed) { + return; + } } - if (idx === 1) { - const updated = prev.includes(1) ? [] : [1]; + // 전체 선택 + setSelectedTag([1]); + setValue(fieldName, [1]); + return; + } + + // 다른 카테고리를 클릭하는 경우 + setSelectedTag((prev) => { + // 전체가 선택되어 있으면 전체 해제하고 해당 카테고리 선택 + if (prev.includes(1)) { + const updated = [idx]; setValue(fieldName, updated); return updated; } + // 일반적인 토글 로직 const isAlreadySelected = prev.includes(idx); const updated = isAlreadySelected ? prev.filter((item) => item !== idx) From 7ad8482a4bf61978bfdac7f8a1f6b0be22ec663d Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Mon, 21 Jul 2025 20:49:01 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat=20:=20=EB=AC=B8=EC=9D=98=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20preview=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/admin/customerService/inquiry.api.ts | 5 +++++ .../inquiresPreview/InquiresPreview.tsx | 16 +++++----------- .../noticePreview/NoticePreview.tsx | 2 +- src/components/user/mypage/ContentTab.tsx | 1 - src/hooks/admin/useGetInquiriesPreview.ts | 17 +++++++++++++++++ 5 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 src/hooks/admin/useGetInquiriesPreview.ts diff --git a/src/api/admin/customerService/inquiry.api.ts b/src/api/admin/customerService/inquiry.api.ts index c3228c55..bcdcdb77 100644 --- a/src/api/admin/customerService/inquiry.api.ts +++ b/src/api/admin/customerService/inquiry.api.ts @@ -21,6 +21,11 @@ export const getAllInquiries = async ( } }; +export const getInquiriesPreview = async () => { + const response = await httpClient.get(`/inquiry/preview`); + return response.data.data; +}; + export const getInquiryDetail = async (id: string) => { try { const response = await httpClient.get( diff --git a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx index 030a8177..96bf180f 100644 --- a/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx +++ b/src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx @@ -1,19 +1,13 @@ import * as S from './InquiresPreview.styled'; -import { useGetAllInquiries } from '../../../../hooks/admin/useGetAllInquiries'; import Avatar from '../../../common/avatar/Avatar'; import { ADMIN_ROUTE } from '../../../../constants/routes'; import arrow_right from '../../../../assets/ArrowRight.svg'; import Spinner from '../../../user/mypage/Spinner'; -import { AdminInquiryChangeSearchParams } from '../../../../models/inquiry'; +import { useGetInquiriesPreview } from '../../../../hooks/admin/useGetInquiriesPreview'; const InquiresPreview = () => { - const childSearchParams: AdminInquiryChangeSearchParams = { - userId: '', - startDate: '', - endDate: '', - }; - const { allInquiriesData, isLoading, isFetching } = - useGetAllInquiries(childSearchParams); + const { allInquiriesPreviewData, isLoading, isFetching } = + useGetInquiriesPreview(); if (isLoading || isFetching) { return ( @@ -23,13 +17,13 @@ const InquiresPreview = () => { ); } - if (!allInquiriesData || allInquiriesData.length === 0) { + if (!allInquiriesPreviewData || allInquiriesPreviewData.length === 0) { return 등록된 문의가 없습니다.; } return ( - {allInquiriesData?.map((inquiry) => ( + {allInquiriesPreviewData.map((inquiry) => ( {/* { } if (!noticeData) { - return 공지사힝이 없습니다.; + return 공지사항이 없습니다.; } return ( diff --git a/src/components/user/mypage/ContentTab.tsx b/src/components/user/mypage/ContentTab.tsx index 9f11a91d..86d60aa7 100644 --- a/src/components/user/mypage/ContentTab.tsx +++ b/src/components/user/mypage/ContentTab.tsx @@ -57,7 +57,6 @@ export default function ContentTab({ filter, $justifyContent }: ContentProps) { to={filter.url} onClick={() => handleChangeId(filter.id as number)} > - {' '} {filter.title} diff --git a/src/hooks/admin/useGetInquiriesPreview.ts b/src/hooks/admin/useGetInquiriesPreview.ts new file mode 100644 index 00000000..8b9de1f4 --- /dev/null +++ b/src/hooks/admin/useGetInquiriesPreview.ts @@ -0,0 +1,17 @@ +import { useQuery } from '@tanstack/react-query'; +import { Inquiries } from '../queries/keys'; +import { getInquiriesPreview } from '../../api/admin/customerService/inquiry.api'; + +export const useGetInquiriesPreview = () => { + const { + data: allInquiriesPreviewData, + isLoading, + isFetching, + } = useQuery({ + queryKey: [Inquiries.inquiriesPreview], + queryFn: () => getInquiriesPreview(), + select: (data) => data.slice(0, 5), + }); + + return { allInquiriesPreviewData, isLoading, isFetching }; +}; From f85aec7686c16497820c088930bf8bb19b332a78 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:42:23 +0900 Subject: [PATCH 4/8] =?UTF-8?q?bug=20:=20build=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/admin/tag.api.ts | 2 +- src/api/http.api.ts | 3 +-- .../admin/adminInquiry/AdminInquiryList.tsx | 2 +- .../admin/adminTags/AdminTagsBasic.tsx | 2 +- .../admin/adminUserReport/AdminReportDetail.tsx | 1 - .../admin/mainCard/graphCard/GraphCard.tsx | 5 ----- .../allUserPreview/AllUserPreview.tsx | 1 - src/components/admin/userCard/UserCard.tsx | 1 - src/components/user/comment/DropDownItem.tsx | 1 - .../activityLog/inquiries/inquiry/Inquiry.tsx | 16 ++++++++-------- .../editProfile/ProfileGithubSuccess.tsx | 2 -- src/hooks/useOauth.ts | 9 --------- src/hooks/user/useMyInfo.ts | 6 +++--- src/models/auth.ts | 2 +- src/pages/admin/adminUser/AdminUser.tsx | 2 +- src/routes/AdminRoutes.tsx | 13 ++++--------- src/routes/AppRoutes.tsx | 1 - src/store/authStore.ts | 1 - 18 files changed, 21 insertions(+), 49 deletions(-) delete mode 100644 src/hooks/useOauth.ts diff --git a/src/api/admin/tag.api.ts b/src/api/admin/tag.api.ts index 7d1d467c..6d7cd322 100644 --- a/src/api/admin/tag.api.ts +++ b/src/api/admin/tag.api.ts @@ -1,5 +1,5 @@ import type { ApiCommonBasicType } from '../../models/apiCommon'; -import type { TagFormType } from '../../models/tags'; + import { httpClient } from '../http.api'; export const postSkillTag = async (formData: FormData) => { diff --git a/src/api/http.api.ts b/src/api/http.api.ts index 18e9ef22..2626985d 100644 --- a/src/api/http.api.ts +++ b/src/api/http.api.ts @@ -1,12 +1,11 @@ import axios, { AxiosRequestConfig } from 'axios'; import useAuthStore from '../store/authStore'; -import { postRefresh } from './auth.api'; export const BASE_URL = `${import.meta.env.VITE_APP_API_BASE_URL}`; const DEFAULT_TIMEOUT = 15000; export const createClient = (config?: AxiosRequestConfig) => { - const { login, logout } = useAuthStore.getState(); + const { logout } = useAuthStore.getState(); const axiosInstance = axios.create({ baseURL: BASE_URL, diff --git a/src/components/admin/adminInquiry/AdminInquiryList.tsx b/src/components/admin/adminInquiry/AdminInquiryList.tsx index 8804b253..8485493e 100644 --- a/src/components/admin/adminInquiry/AdminInquiryList.tsx +++ b/src/components/admin/adminInquiry/AdminInquiryList.tsx @@ -8,7 +8,7 @@ import type { AdminInquiryChangeSearchParams } from '../../../models/inquiry'; export type SearchParamsInquiryKeyType = keyof AdminInquiryChangeSearchParams; export default function AdminInquiryList() { - const [searchParams, setSearchParams] = useSearchParams(); + const [searchParams] = useSearchParams(); const userId = searchParams.get('userId') || ''; const startDate = searchParams.get('startDate') || ''; const endDate = searchParams.get('endDate') || ''; diff --git a/src/components/admin/adminTags/AdminTagsBasic.tsx b/src/components/admin/adminTags/AdminTagsBasic.tsx index 671b9f7a..0d1a0aab 100644 --- a/src/components/admin/adminTags/AdminTagsBasic.tsx +++ b/src/components/admin/adminTags/AdminTagsBasic.tsx @@ -4,7 +4,7 @@ import { useAdminSkillTag } from '../../../hooks/admin/useAdminTag'; import { useLocation } from 'react-router-dom'; import AdminTagCRUD from './AdminTagCRUD'; import AdminSkillTagItems from './skills/AdminSkillTagItems'; -import type { TagFormType } from '../../../models/tags'; + import AdminPositionItems from './positions/AdminPositionItems'; export type TWitchTag = 'skill' | 'position'; diff --git a/src/components/admin/adminUserReport/AdminReportDetail.tsx b/src/components/admin/adminUserReport/AdminReportDetail.tsx index b20158ef..bbc39665 100644 --- a/src/components/admin/adminUserReport/AdminReportDetail.tsx +++ b/src/components/admin/adminUserReport/AdminReportDetail.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import * as S from './AdminReportDetail.styled'; import AdminTitle from '../../common/admin/title/AdminTitle'; import Avatar from '../../common/avatar/Avatar'; diff --git a/src/components/admin/mainCard/graphCard/GraphCard.tsx b/src/components/admin/mainCard/graphCard/GraphCard.tsx index 576a1cab..37926d57 100644 --- a/src/components/admin/mainCard/graphCard/GraphCard.tsx +++ b/src/components/admin/mainCard/graphCard/GraphCard.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import * as S from './GraphCard.styled'; import { Line } from 'react-chartjs-2'; import 'chart.js/auto'; @@ -58,7 +57,6 @@ const options: ChartOptions<'line'> = { x: { grid: { display: true, - borderDash: [5, 5], color: 'rgba(0,0,0,0.1)', }, ticks: { @@ -71,9 +69,6 @@ const options: ChartOptions<'line'> = { y: { grid: { display: true, - drawBorder: false, - - borderDash: [5, 5], color: 'rgba(0,0,0,0.1)', }, ticks: { diff --git a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx index dd1deb6c..22e36bf8 100644 --- a/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx +++ b/src/components/admin/previewComponent/allUserPreview/AllUserPreview.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import * as S from './AllUserPreview.styled'; import Avatar from '../../../common/avatar/Avatar'; import { ADMIN_ROUTE } from '../../../../constants/routes'; diff --git a/src/components/admin/userCard/UserCard.tsx b/src/components/admin/userCard/UserCard.tsx index 430814b2..bc670e92 100644 --- a/src/components/admin/userCard/UserCard.tsx +++ b/src/components/admin/userCard/UserCard.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import * as S from './UserCard.styled'; import Avatar from '../../common/avatar/Avatar'; import type { AllUser } from '../../../models/auth'; diff --git a/src/components/user/comment/DropDownItem.tsx b/src/components/user/comment/DropDownItem.tsx index 27bcbb3b..987a9fd4 100644 --- a/src/components/user/comment/DropDownItem.tsx +++ b/src/components/user/comment/DropDownItem.tsx @@ -61,7 +61,6 @@ const DropDownItem = ({ targetId={recommentId ? recommentId : commentId} type={recommentId ? 'recomment' : 'comment'} onClose={handleCloseReportModal} - route={projectId} /> )} diff --git a/src/components/user/mypage/activityLog/inquiries/inquiry/Inquiry.tsx b/src/components/user/mypage/activityLog/inquiries/inquiry/Inquiry.tsx index 21881354..f167a916 100644 --- a/src/components/user/mypage/activityLog/inquiries/inquiry/Inquiry.tsx +++ b/src/components/user/mypage/activityLog/inquiries/inquiry/Inquiry.tsx @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react'; +import { useState } from 'react'; import type { MyInquiries } from '../../../../../../models/activityLog'; import * as S from './Inquiry.styled'; import { My_INQUIRIES_MESSAGE } from '../../../../../../constants/user/customerService'; @@ -22,14 +22,14 @@ export default function Inquiry({ list, no }: InquiryProps) { url: '', }); const answer = list.answer || ''; - const answerRef = useRef(null); + // const answerRef = useRef(null); - const handleChangeAnswerRef = () => { - if (answerRef && answerRef.current) { - answerRef.current.style.height = 'auto'; - answerRef.current.style.height = `${answerRef.current.scrollHeight}px`; - } - }; + // const handleChangeAnswerRef = () => { + // if (answerRef && answerRef.current) { + // answerRef.current.style.height = 'auto'; + // answerRef.current.style.height = `${answerRef.current.scrollHeight}px`; + // } + // }; return ( diff --git a/src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx b/src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx index eb856cd0..9952c1da 100644 --- a/src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx +++ b/src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx @@ -1,9 +1,7 @@ import { useEffect } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; -import { ROUTES } from '../../../../../constants/routes'; import { useModal } from '../../../../../hooks/useModal'; import Modal from '../../../../common/modal/Modal'; -import { MODAL_MESSAGE } from '../../../../../constants/user/modalMessage'; import { useGithubLink } from '../../../../../hooks/user/useMyInfo'; export default function ProfileGithubSuccess() { diff --git a/src/hooks/useOauth.ts b/src/hooks/useOauth.ts deleted file mode 100644 index 5c615298..00000000 --- a/src/hooks/useOauth.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import { getOauthLogin } from '../api/auth.api'; - -export const useOauth = () => { - const { data, isLoading, isError } = useQuery({ - queryKey: [], - queryFn: () => getOauthLogin(), - }); -}; diff --git a/src/hooks/user/useMyInfo.ts b/src/hooks/user/useMyInfo.ts index 9860023f..610ac55b 100644 --- a/src/hooks/user/useMyInfo.ts +++ b/src/hooks/user/useMyInfo.ts @@ -15,8 +15,8 @@ import { import { MODAL_MESSAGE } from '../../constants/user/modalMessage'; import { ROUTES } from '../../constants/routes'; import type { - ApiAppliedProject, ApiJoinedProject, + AppliedProject, } from '../../models/userProject'; export const useMyProfileInfo = () => { @@ -130,11 +130,11 @@ export const useMyJoinedProjectList = () => { export const useMyAppliedStatusList = () => { const isLoggedIn = useAuthStore.getState().isLoggedIn; - const { data, isLoading } = useQuery({ + const { data, isLoading } = useQuery({ queryKey: ProjectListKey.myAppliedStatusList, queryFn: () => getMyAppliedStatusList(), enabled: isLoggedIn, }); - return { myAppliedStatusListData: data?.data, isLoading }; + return { myAppliedStatusListData: data, isLoading }; }; diff --git a/src/models/auth.ts b/src/models/auth.ts index dc22a4b7..883e7cf5 100644 --- a/src/models/auth.ts +++ b/src/models/auth.ts @@ -1,5 +1,5 @@ import { PositionTag, SkillTag } from './tags'; -import { type ApiCommonType, type User } from './apiCommon'; +import type { ApiCommonType } from './apiCommon'; export enum UserState { ONLINE = 'ONLINE', diff --git a/src/pages/admin/adminUser/AdminUser.tsx b/src/pages/admin/adminUser/AdminUser.tsx index 224bd1ae..eef5725c 100644 --- a/src/pages/admin/adminUser/AdminUser.tsx +++ b/src/pages/admin/adminUser/AdminUser.tsx @@ -27,7 +27,7 @@ const AdminUser = () => { return {ADMIN_MODAL_MESSAGE.NO_RESULT}; } - const onBan = (userId: number) => { + const onBan = () => { // TODO : 버튼을 누르면 해당 유저 강퇴 조치 API 전송. }; diff --git a/src/routes/AdminRoutes.tsx b/src/routes/AdminRoutes.tsx index 2ec80a06..baf0f46b 100644 --- a/src/routes/AdminRoutes.tsx +++ b/src/routes/AdminRoutes.tsx @@ -15,12 +15,7 @@ const UserProjects = lazy( const ActivityLog = lazy( () => import('../components/user/mypage/activityLog/ActivityLog') ); -const Notifications = lazy( - () => import('../components/user/mypage/notifications/Notifications') -); -// const AdminReportDetail = lazy( -// () => import('../components/admin/adminUserReport/AdminReportDetail') -// ); + const Sidebar = lazy( () => import('../components/common/admin/sidebar/AdminSidebar') ); @@ -102,9 +97,9 @@ const NotificationsAppliedProjects = lazy( '../components/user/mypage/notifications/appliedProjects/AppliedProjects' ) ); -const NotificationsAll = lazy( - () => import('../components/user/mypage/notifications/all/All') -); +// const NotificationsAll = lazy( +// () => import('../components/user/mypage/notifications/all/All') +// ); export const AdminRoutes = () => { const routeList = [ diff --git a/src/routes/AppRoutes.tsx b/src/routes/AppRoutes.tsx index 166be35e..df3f7d86 100644 --- a/src/routes/AppRoutes.tsx +++ b/src/routes/AppRoutes.tsx @@ -7,7 +7,6 @@ import NotFoundPage from '../pages/notFoundPage/NotFoundPage'; import QueryErrorBoundary from '../components/common/error/QueryErrorBoundary'; import { ROUTES } from '../constants/routes'; const Login = lazy(() => import('../pages/login/Login')); -const LoginSuccess = lazy(() => import('../pages/login/LoginSuccess')); const LoginApi = lazy(() => import('../pages/login/LoginApi')); const Register = lazy(() => import('../pages/user/register/Register')); const ChangePassword = lazy( diff --git a/src/store/authStore.ts b/src/store/authStore.ts index 3511827d..25ee9086 100644 --- a/src/store/authStore.ts +++ b/src/store/authStore.ts @@ -1,6 +1,5 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; -import { decryptData, encryptData } from '../util/cryptoUtils'; import type { UserData } from '../models/auth'; interface AuthState { From b7b71d108e7d8efb2c9c771c5373ff2fcd1a1c98 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Tue, 22 Jul 2025 22:53:49 +0900 Subject: [PATCH 5/8] =?UTF-8?q?bug=20:=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=EC=9D=B4=20=EC=A0=84=EC=86=A1=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/user/useNotification.ts | 5 +---- src/routes/MergeRoutes.tsx | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/hooks/user/useNotification.ts b/src/hooks/user/useNotification.ts index 3287dad0..95b728bc 100644 --- a/src/hooks/user/useNotification.ts +++ b/src/hooks/user/useNotification.ts @@ -36,10 +36,7 @@ const useNotification = () => { eventSourceRef.current = eventSource; - eventSource.onopen = () => { - console.log('확인'); - console.log(eventSource.readyState); - }; + eventSource.onopen = () => {}; eventSource.addEventListener('alarm', (e) => { const event = e as MessageEvent; diff --git a/src/routes/MergeRoutes.tsx b/src/routes/MergeRoutes.tsx index 48f0f910..eee2024f 100644 --- a/src/routes/MergeRoutes.tsx +++ b/src/routes/MergeRoutes.tsx @@ -11,8 +11,8 @@ export default function MergeRoutes() { { element: ( - + From 3a6c2dee00b9633597512733dd0e004912150110 Mon Sep 17 00:00:00 2001 From: Cho SeungYeon <111514472+layout-SY@users.noreply.github.com> Date: Tue, 22 Jul 2025 22:54:30 +0900 Subject: [PATCH 6/8] =?UTF-8?q?bug=20:=20=EB=8C=80=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EC=8B=9C=20input=EC=9D=98=20=EA=B0=80?= =?UTF-8?q?=EB=A1=9C=20=EC=98=81=EC=97=AD=EC=9D=B4=20=EC=B6=95=EC=86=8C=20?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commentComponent/CommentComponentLayout.styled.ts | 7 +++++-- .../commentComponent/CommentComponent.styled.ts | 3 ++- .../user/comment/commentInput/CommentInput.styled.ts | 11 +++++++---- .../user/comment/commentInput/CommentInput.tsx | 5 +++-- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/components/user/comment/commentComponent/CommentComponentLayout.styled.ts b/src/components/user/comment/commentComponent/CommentComponentLayout.styled.ts index e9f988c1..711f06de 100644 --- a/src/components/user/comment/commentComponent/CommentComponentLayout.styled.ts +++ b/src/components/user/comment/commentComponent/CommentComponentLayout.styled.ts @@ -1,10 +1,13 @@ import styled from 'styled-components'; -export const Container = styled.div``; +export const Container = styled.div` + display: flex; + flex-direction: column; +`; export const CommentContainer = styled.div` display: flex; - justify-content: space-between; + flex: 1; width: 100%; margin-bottom: 20px; `; diff --git a/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts b/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts index c7f6a584..15e83423 100644 --- a/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts +++ b/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts @@ -16,10 +16,11 @@ export const Container = styled.div<{ $reply: boolean }>` export const Wrapper = styled.div` display: flex; - flex-grow: 1; + flex: 1; `; export const CommentWrapper = styled.div` + flex: 1; margin-top: 4px; `; diff --git a/src/components/user/comment/commentInput/CommentInput.styled.ts b/src/components/user/comment/commentInput/CommentInput.styled.ts index a0123c0f..c6f42e89 100644 --- a/src/components/user/comment/commentInput/CommentInput.styled.ts +++ b/src/components/user/comment/commentInput/CommentInput.styled.ts @@ -4,18 +4,21 @@ import Button from '../../../common/Button/Button'; export const InputContainer = styled.div` display: flex; flex: 1; + margin-left: 10px; `; -export const Input = styled.input` +export const Input = styled.input<{ $isEditMode?: boolean }>` width: 100%; + flex: 1; font-size: 15px; - margin-left: 10px; + margin-left: ${({ $isEditMode }) => ($isEditMode ? '0' : '10px')}; `; export const InputWrapper = styled.div` width: 100%; margin-left: 5px; margin-top: 7px; + flex: 1; `; export const ButtonWrapper = styled.div` @@ -24,11 +27,11 @@ export const ButtonWrapper = styled.div` gap: 0.5rem; margin-top: 3px; `; -export const Line = styled.hr<{ $isFocused: boolean }>` +export const Line = styled.hr<{ $isFocused: boolean; $isEditMode?: boolean }>` opacity: ${({ $isFocused }) => ($isFocused ? 1.0 : 0.2)}; border: ${({ $isFocused }) => ($isFocused ? 2 : 1)}; margin-top: 4px; - margin-left: 10px; + margin-left: ${({ $isEditMode }) => ($isEditMode ? '0' : '10px')}; `; export const ButtonCancel = styled(Button)``; diff --git a/src/components/user/comment/commentInput/CommentInput.tsx b/src/components/user/comment/commentInput/CommentInput.tsx index 91b1faab..42143bbf 100644 --- a/src/components/user/comment/commentInput/CommentInput.tsx +++ b/src/components/user/comment/commentInput/CommentInput.tsx @@ -85,7 +85,7 @@ const CommentInput = ({ return ( - + {!activateEditMode && }
- + {isFocused && ( Date: Tue, 22 Jul 2025 22:55:17 +0900 Subject: [PATCH 7/8] =?UTF-8?q?design=20:=20Funnel=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9D=98=20=EB=8B=A8=EA=B3=84=20=EC=9D=B4=EB=8F=99=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/user/apply/ApplyStep.styled.ts | 10 ++---- src/pages/user/apply/ApplyStep.tsx | 43 ++++++++++-------------- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/pages/user/apply/ApplyStep.styled.ts b/src/pages/user/apply/ApplyStep.styled.ts index 7c401c5b..37cc3c77 100644 --- a/src/pages/user/apply/ApplyStep.styled.ts +++ b/src/pages/user/apply/ApplyStep.styled.ts @@ -1,5 +1,4 @@ import styled from 'styled-components'; -import Button from '../../../components/common/Button/Button'; export const Container = styled.div` max-width: 100%; @@ -46,9 +45,10 @@ export const StepContainer = styled.div` export const StepButton = styled.div` display: flex; - justify-content: left; + justify-content: center; padding-top: 20px; gap: 20px; + width: 100%; `; export const StepLabel = styled.div` @@ -66,9 +66,3 @@ export const StepWrapper = styled.div` display: flex; justify-content: space-between; `; - -export const SubmitButton = styled(Button)` - padding: 15px; - margin: 0 auto; - cursor: pointer; -`; diff --git a/src/pages/user/apply/ApplyStep.tsx b/src/pages/user/apply/ApplyStep.tsx index b049956c..4f54c7aa 100644 --- a/src/pages/user/apply/ApplyStep.tsx +++ b/src/pages/user/apply/ApplyStep.tsx @@ -114,7 +114,13 @@ const Apply = () => { next, } = useMultiStepForm(stepList); - const handleNextStep = async () => { + const handlePrevStep = (e: React.MouseEvent) => { + e.preventDefault(); + prev(); + }; + + const handleNextStep = async (e: React.MouseEvent) => { + e.preventDefault(); const fieldsToValidate = stepFields[currentStepIndex]; const isValid = await trigger(fieldsToValidate); if (isValid) { @@ -165,37 +171,24 @@ const Apply = () => { - {currentStepIndex !== stepList.length - 1 && ( - - )} - - - {isLastStep && ( - - 지원 완료하기 - - )} + {isLastStep ? '지원하기' : '다음'} + + Date: Wed, 23 Jul 2025 17:07:05 +0900 Subject: [PATCH 8/8] =?UTF-8?q?refactor=20:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/admin/customerService/inquiry.api.ts | 9 +- src/assets/chat.svg | 260 ------------------ .../CommentComponent.styled.ts | 3 + .../commentComponent/CommentComponent.tsx | 6 +- .../inputComponent/InputComponent.tsx | 10 +- src/constants/user/projectConstants.ts | 9 +- 6 files changed, 17 insertions(+), 280 deletions(-) delete mode 100644 src/assets/chat.svg diff --git a/src/api/admin/customerService/inquiry.api.ts b/src/api/admin/customerService/inquiry.api.ts index bcdcdb77..6c59cb5b 100644 --- a/src/api/admin/customerService/inquiry.api.ts +++ b/src/api/admin/customerService/inquiry.api.ts @@ -22,8 +22,13 @@ export const getAllInquiries = async ( }; export const getInquiriesPreview = async () => { - const response = await httpClient.get(`/inquiry/preview`); - return response.data.data; + try { + const response = await httpClient.get(`/inquiry/preview`); + return response.data.data; + } catch (e) { + console.error('문의 미리보기 조회 에러', e); + throw e; + } }; export const getInquiryDetail = async (id: string) => { diff --git a/src/assets/chat.svg b/src/assets/chat.svg deleted file mode 100644 index 73f5ff4f..00000000 --- a/src/assets/chat.svg +++ /dev/null @@ -1,260 +0,0 @@ - - - - diff --git a/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts b/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts index 15e83423..ba19888a 100644 --- a/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts +++ b/src/components/user/comment/commentComponent/commentComponent/CommentComponent.styled.ts @@ -42,15 +42,18 @@ export const Comment = styled.span` export const ReplyInputButton = styled.div` display: flex; + margin-left: 7px; margin-top: 11px; cursor: pointer; `; export const Icon = styled.div` + color: ${({ theme }) => theme.color.blue}; margin-left: 11px; `; export const ReplyContent = styled.p` + color: ${({ theme }) => theme.color.blue}; margin-left: 10px; margin-bottom: 10px; `; diff --git a/src/components/user/comment/commentComponent/commentComponent/CommentComponent.tsx b/src/components/user/comment/commentComponent/commentComponent/CommentComponent.tsx index 721403f8..5efb1854 100644 --- a/src/components/user/comment/commentComponent/commentComponent/CommentComponent.tsx +++ b/src/components/user/comment/commentComponent/commentComponent/CommentComponent.tsx @@ -1,11 +1,11 @@ import { Dispatch, SetStateAction } from 'react'; import * as S from './CommentComponent.styled'; -import chat from '../../../../../assets/chat.svg'; import { Link } from 'react-router-dom'; import CommentInput from '../../commentInput/CommentInput'; import type { CommentType } from '../../../../../models/comment'; import { ROUTES } from '../../../../../constants/routes'; import Avatar from '../../../../common/avatar/Avatar'; +import { ChatBubbleBottomCenterTextIcon } from '@heroicons/react/24/outline'; interface CommentComponentProps { item: CommentType; @@ -84,9 +84,9 @@ const CommentComponent = ({ } > - + - 댓글 달기 + 답글 달기 )} diff --git a/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx b/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx index 1ab3287b..64caebe2 100644 --- a/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx +++ b/src/components/user/projectFormComponents/inputComponent/InputComponent.tsx @@ -31,18 +31,14 @@ const Input = ({ const hasError = Boolean(errors?.[name]); const handleInputChange = (e: React.ChangeEvent) => { - const value = e.target.value; + let value = e.target.value; // 숫자 입력 필드인 경우 숫자만 허용 if (name === 'maxVolunteers' || name === 'duration') { - // 숫자가 아닌 문자 제거 - const numericValue = value.replace(/[^0-9]/g, ''); - if (numericValue !== value) { - e.target.value = numericValue; - } + value = value.replace(/[^0-9]/g, ''); // 음수 방지 (0보다 작은 값은 허용하지 않음) - const numValue = Number(numericValue); + const numValue = Number(value); if (numValue < min) { return; } diff --git a/src/constants/user/projectConstants.ts b/src/constants/user/projectConstants.ts index f87f5615..5d673b63 100644 --- a/src/constants/user/projectConstants.ts +++ b/src/constants/user/projectConstants.ts @@ -94,14 +94,7 @@ export const createProjectScheme = z.object({ field: z.number({ message: '진행 방식을 선택 해주세요.' }), duration: z .string({ message: '예상 기간을 입력해주세요.' }) - .min(1, { message: '예상 기간을 입력해주세요.' }) - .refine( - (val) => { - const num = Number(val); - return !isNaN(num) && num >= 1 && num <= 365; - }, - { message: '예상 기간은 1일 이상 365일 이하여야 합니다.' } - ), + .min(1, { message: '예상 기간을 입력해주세요.' }), position: z .array(z.number({ message: '숫자로 입력 되어야 합니다.' })) .min(1, { message: '1개의 분야를 선택해주세요.' }),