Skip to content
Merged
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
Binary file modified src/assets/images/growth-character/growth-character1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/images/growth-character/growth-character2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/images/growth-character/growth-character3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/images/growth-character/growth-character4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/images/growth-character/growth-character5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/images/growth-character/growth-character6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 27 additions & 28 deletions src/components/calendar/AclInfoButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ export default function AclInfoButton({

const { mutateAsync: insertCalendar } = useInsertCalendar({
onSuccess: async () => {
await queryClient.invalidateQueries({
queryKey: ['useGetCalendarList'],
});
await queryClient.invalidateQueries({ queryKey: ['useGetCalendarList'] });
await queryClient.invalidateQueries({
queryKey: ['useGetCalendarAcl', courseId],
});
Expand All @@ -44,46 +42,47 @@ export default function AclInfoButton({
useEffect(() => {
if (isError && error.response?.status === 403) {
queryClient.setQueryData(['useGetCalendarAcl', courseId], {
status: 'forbidden',
status: 'Forbidden',
});
}
}, [isError, error, queryClient, courseId]);

const alertText = {
notFoundCalendar: {
const alertList: {
type: 'notFoundCalendar' | 'hasNotAcl' | 'hasAclButNotInMyCalendarList';
text: string;
subText: string;
condition: boolean;
}[] = [
{
type: 'notFoundCalendar',
text: '캘린더에 오류가 발생했습니다.',
subText: '생성되었던 해당 캘린더가 유실되었습니다.',
condition: typeof aclList === 'string' && aclList === 'Not Found',
},
hasNotAcl: {
{
type: 'hasNotAcl',
text: '아직 캘린더 권한이 없는 상태입니다.',
subText:
'잠시만 기다려주시면 관리자가 확인 후 권한을 곧 부여해드리겠습니다.',
condition: typeof aclList === 'string' && aclList === 'Forbidden',
},
notInMyCalendar: {
{
type: 'hasAclButNotInMyCalendarList',
text: '캘린더 권한이 있지만 나의 캘린더 목록에는 없는 상태입니다.',
subText: '나의 캘린더 목록에 추가하셔야 캘린더 일정을 볼 수 있습니다.',
condition: !!aclList?.length && typeof aclList === 'object',
},
};
];

// 캘린더를 찾지 못했을때
const notFoundCalendar =
aclList === 'Not Found' &&
typeof aclList === 'string' &&
'notFoundCalendar';
// 권한 없음
const hasNotAcl = !aclList?.length && 'hasNotAcl';
// 권한이 있지만 내 캘린더 목록에 추가하지 않아 캘린더 데이터를 못가져올 때
const hasAclButNotInMyCalendarList =
!!aclList?.length && typeof aclList === 'object' && 'notInMyCalendar';
const activeAlert =
alertList.find(alertItem => alertItem.condition) || alertList[0];

const onInfoClick = () => {
const { text, subText, type } = activeAlert;

alert({
...alertText[
notFoundCalendar ||
hasNotAcl ||
hasAclButNotInMyCalendarList ||
'hasNotAcl'
],
text,
subText,
subTextColor: 'green',
children: (
<div className="flex gap-4">
Expand All @@ -93,7 +92,7 @@ export default function AclInfoButton({
onClick={hideDialog}
type="button"
/>
{hasAclButNotInMyCalendarList && (
{type === 'hasAclButNotInMyCalendarList' && (
<SquareButton
name="나의 캘린더에 추가"
onClick={() => {
Expand All @@ -109,11 +108,11 @@ export default function AclInfoButton({
};

return (
(notFoundCalendar || hasNotAcl || hasAclButNotInMyCalendarList) &&
activeAlert &&
!isLoading && (
<button type="button" onClick={onInfoClick} className="group text-[15px]">
<BiInfoCircle
className={`inline size-[20px] ${!hasAclButNotInMyCalendarList ? 'text-red-400' : 'text-mainGreen'}`}
className={`inline size-[20px] ${activeAlert.type !== 'hasAclButNotInMyCalendarList' ? 'text-red-400' : 'text-mainGreen'}`}
/>
</button>
)
Expand Down
3 changes: 2 additions & 1 deletion src/components/calendar/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ export default function Calendar({
({ id, start, end, title }) => (
<SmallCalendarBottomEvent
key={id}
date={`${formatDate(start, 'MM.dd HH:mm')} ~ ${formatDate(end, 'HH:mm')}`}
date={formatDate(start, 'MM.dd')}
time={`${formatDate(start, 'HH:mm')} ~ ${formatDate(end, 'HH:mm')}`}
title={title}
/>
),
Expand Down
13 changes: 9 additions & 4 deletions src/components/calendar/SmallCalendarBottomEvent.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
interface SmallCalendarBottomEventProps {
title: string;
date: string;
time: string;
}

export default function SmallCalendarBottomEvent({
date,
title,
time,
}: SmallCalendarBottomEventProps) {
return (
<li className="line-clamp-1 flex items-center">
<span className="min-w-[142px] tracking-tight text-mainGray-active">
{date}
</span>
<li className="line-clamp-1 flex w-full items-center">
<div className="min-w-[154px]">
<span className="inline-block w-[50px] text-justify text-mainGray-active">
{date}
</span>
<span className="text-mainGray-active">{time}</span>
</div>
<span className="ml-1.5 mr-2 text-mainGray-active">|</span>
<span className="truncate tracking-tight">{title}</span>
</li>
Expand Down
6 changes: 2 additions & 4 deletions src/components/common/TitleLinkWithRoleTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@ export default function TitleLinkWithRoleTag({
title,
}: TitleLinkWithRoleTagProps) {
return (
<Link to={to} className="flex h-7 w-full items-center gap-1.5">
<Link to={to} className="flex h-7 items-center gap-1.5">
<Tag
size="medium"
roleKey={roleType}
text={rolesObj[roleType]}
className="!rounded-md !px-[10px] py-1.5 font-medium"
/>
<p className="overflow-hidden text-ellipsis whitespace-nowrap text-sm">
{title}
</p>
<p className="line-clamp-1 text-sm">{title}</p>
</Link>
);
}
20 changes: 11 additions & 9 deletions src/components/lounge/LoungeApplicationInfoTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,17 @@ export default function LoungeApplicationInfoTemplate({
type: '직무',
data: position && (
<ul className="flex w-full flex-1 flex-wrap gap-1">
{position?.map(({ id, name }) => (
<Tag
key={id}
text={name}
color="black"
size="big"
className="whitespace-nowrap rounded bg-black !px-2 !font-normal text-white"
/>
))}
{position
?.sort((a, b) => a.name.localeCompare(b.name))
.map(({ id, name }) => (
<Tag
key={id}
text={name}
color="black"
size="big"
className="whitespace-nowrap rounded bg-black !px-2 !font-normal text-white"
/>
))}
</ul>
),
},
Expand Down
65 changes: 31 additions & 34 deletions src/components/lounge/layout/LoungeSideView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,38 @@ export default function LoungeSideView() {
const { data: endingTomorrowProjectList } = useGetEndingTomorrowProjects();

return (
<div className="flex flex-col gap-10">
<div className="max-h-[90vh] min-h-60 overflow-y-scroll rounded-[20px] bg-white px-5 py-6">
<Title as="h2" title="마감 하루전!" className="mb-3" highlight="마감" />
<div className="max-h-[90vh] min-h-60 overflow-y-scroll rounded-[20px] bg-white px-5 py-6">
<Title as="h2" title="마감 하루전!" className="mb-3" highlight="마감" />

{endingTomorrowProjectList &&
endingTomorrowProjectList?.length !== 0 ? (
<ul className="flex flex-col gap-3.5">
{endingTomorrowProjectList?.map(project => (
<li
key={project.projectId}
className="border-t pt-3.5 first:border-t-0"
>
<Link to={`/lounge/post/${project.projectId}`}>
<h2 className="line-clamp-3 text-darkGray-hover">
{project.title}
</h2>
<div className="mt-2 flex items-center gap-2">
<UserImage
className="size-[22px]"
imageNameSegment={project.imgUrl}
/>
<span className="tracking-tight">
@ {project.userNickname}
</span>
</div>
</Link>
</li>
))}
</ul>
) : (
<span className="inline-block w-full pt-14 text-center text-mainGray-active">
곧 마감하는 프로젝트가 없어요!
</span>
)}
</div>
{endingTomorrowProjectList && endingTomorrowProjectList?.length !== 0 ? (
<ul className="flex flex-col gap-3.5">
{endingTomorrowProjectList?.map(project => (
<li
key={project.projectId}
className="border-t pt-3.5 first:border-t-0"
>
<Link to={`/lounge/post/${project.projectId}`}>
<h2 className="line-clamp-3 text-darkGray-hover">
{project.title}
</h2>
<div className="mt-2 flex items-center gap-2">
<UserImage
className="size-[22px]"
imageNameSegment={project.imgUrl}
/>
<span className="tracking-tight">
@ {project.userNickname}
</span>
</div>
</Link>
</li>
))}
</ul>
) : (
<span className="inline-block w-full pt-14 text-center text-mainGray-active">
곧 마감하는 프로젝트가 없어요!
</span>
)}
</div>
);
}
18 changes: 1 addition & 17 deletions src/components/lounge/layout/LoungeTabNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,18 @@ export default function LoungeTabNavigation() {
const [searchParams, setSearchParams] = useSearchParams();
const pType = searchParams.get('pType');

const modifyProjectId = searchParams.get('modifyProject');

const handleChangeValue = useCallback(
(type: string) => {
updateQueryParams(searchParams, setSearchParams, 'pType', type);
},
[searchParams, setSearchParams],
);

const handleChange = () => {
if (!modifyProjectId) {
updateQueryParams(searchParams, setSearchParams, 'pType', 'EDIT');
}
};

return (
<TabNavigation
selectValue={pType ?? 'ALL'}
tabList={loungeTabList}
onChangeValue={handleChangeValue}
>
<div
className={`box-border cursor-pointer justify-center whitespace-pre ${pType === 'EDIT' ? 'border-b-2 border-black' : 'text-mainGray'}`}
>
<button type="button" onClick={handleChange} className="px-4 pb-[19px]">
{modifyProjectId ? '모집수정' : '모집하기'}
</button>
</div>
</TabNavigation>
/>
);
}
9 changes: 9 additions & 0 deletions src/components/notice/NoticePostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { useCallback } from 'react';

import { Link } from 'react-router-dom';

import { useNoticeIncrementViewCount } from '@/services/post/noticeMutations';

import { noticeCategoryDisplay, rolesObj } from '@/constants';
import { useHandleScrap } from '@/hooks';
import { NoticeDisplay } from '@/types';
Expand Down Expand Up @@ -29,10 +31,17 @@ export default function NoticePostCard({ notice }: NoticePostCardProps) {
invalidateQueryKeys: [{ queryKey: ['useGetInfiniteNoticeList'] }],
});

const { mutateAsync: postViewCount } = useNoticeIncrementViewCount();

const onViewCount = useCallback(async () => {
await postViewCount({ noticeId: notice.noticeId });
}, [notice.noticeId, postViewCount]);

return (
<Link
to={`/notice/post/${notice.postId}`}
className="flex w-full flex-col rounded-2xl bg-white p-4 px-6 py-4"
onClick={onViewCount}
>
<div className="flex w-full items-center justify-between">
<Tag
Expand Down
12 changes: 7 additions & 5 deletions src/components/notice/form/ControllerTargetCourses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {

import { useCalendarList, useDialogContext } from '@/hooks';
import { Option } from '@/types';
import { isSuperAdmin } from '@/utils';
import { Controller, useFormContext } from 'react-hook-form';

import MultiSelectDropdown from '@/components/common/dropdown/MultiSelectDropdown';
Expand Down Expand Up @@ -39,7 +40,9 @@ export default function ControllerTargetCourses() {
if (isNotCreatedCalendarCourseTitle.length > 0) {
return alert({
text: `${isNotCreatedCalendarCourseTitle.join(', ')} 캘린더가 아직 생성되어 있지 않습니다!`,
subText: '일정 관리 페이지에서 캘린더를 먼저 생성해주세요.',
subText: isSuperAdmin(userProfile?.role)
? '교육과정 캘린더를 먼저 생성해주세요.'
: '교육과정 캘린더가 먼저 생성되어 있어야 합니다. 관리자가 생성중이니 잠시만 기다려주세요.',
subTextColor: 'green',
className: '!max-w-[500px]',
buttonList: [
Expand All @@ -52,7 +55,7 @@ export default function ControllerTargetCourses() {
name: '바로 이동하기',
onClick: () => {
hideDialog();
navigate('/admin');
navigate('/admin/course');
},
},
],
Expand All @@ -68,8 +71,7 @@ export default function ControllerTargetCourses() {
if (hasNotAclCourse.length > 0) {
return alert({
text: `<${hasNotAclCourse.join(', ')}> 교육과정을 선택할 수 없습니다.`,
subText:
'나의 캘린더 목록에 추가되지 않았거나 캘린더 권한이 부여되지 않았습니다. 일정관리페이지에서 확인 후 조치를 취하실 수 있습니다.',
subText: `나의 캘린더 목록에 추가하지 않았거나 캘린더 권한이 부여되지 않았습니다.${isSuperAdmin(userProfile?.role) ? '' : ' 일정관리 페이지에서 캘린더 상태를 확인하실 수 있으며 권한이 없는 경우 관리자가 부여중이니 잠시만 기다려주세요.'}`,
subTextColor: 'green',
className: '!max-w-[500px]',
buttonList: [
Expand All @@ -79,7 +81,7 @@ export default function ControllerTargetCourses() {
onClick: hideDialog,
},
{
name: '바로 이동하기',
name: '일정관리 페이지 이동',
onClick: () => {
hideDialog();
navigate('/schedule');
Expand Down
6 changes: 5 additions & 1 deletion src/components/notice/form/NoticeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export default function NoticeForm() {
});

const {
reset,
handleSubmit,
control,
formState: { isDirty, isSubmitted },
Expand All @@ -95,7 +96,10 @@ export default function NoticeForm() {
if (isTrainee(role)) {
navigate(-1);
}
}, [navigate, role]);
if (!postId) {
reset(defaultNoticeFormValues);
}
}, [navigate, role, postId, reset]);

return (
<>
Expand Down
Loading
Loading