Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/GU-99/grow-up-fe into fe…
Browse files Browse the repository at this point in the history
…ature/#62-team-ui
  • Loading branch information
ice-bear98 committed Aug 7, 2024
2 parents 3f3b544 + b2565e5 commit 1566f34
Show file tree
Hide file tree
Showing 22 changed files with 9,720 additions and 669 deletions.
9,007 changes: 9,007 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/components/common/ValidationInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default function ValidationInput({
{isButtonInput && (
<button
type="button"
className="flex h-20 w-75 items-center justify-center rounded bg-sub px-8 font-bold shadow-md"
className="flex h-20 w-75 items-center justify-center rounded bg-sub px-8 font-bold"
onClick={onButtonClick}
>
{buttonLabel}
Expand Down
22 changes: 15 additions & 7 deletions src/components/task/calendar/CustomDateHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useMemo } from 'react';
import { DateTime } from 'luxon';
import { DateHeaderProps } from 'react-big-calendar';
import { LuxonWeekday } from '@constants/date';
import useProjectContext from '@hooks/useProjectContext';
import Validator from '@utils/Validator';

function getTextColor(weekday: LuxonWeekday, isOffRange: boolean) {
if (isOffRange) return 'text-[#999999]';
function getTextColor(weekday: LuxonWeekday, isWithinRange: boolean) {
if (!isWithinRange) return 'text-[#999999]';

switch (weekday) {
case LuxonWeekday.SATURDAY:
Expand All @@ -16,9 +17,16 @@ function getTextColor(weekday: LuxonWeekday, isOffRange: boolean) {
}
}

export default function CustomDateHeader({ date, isOffRange }: DateHeaderProps) {
const { weekday } = useMemo(() => DateTime.fromJSDate(date), [date]);
const textColor = useMemo(() => getTextColor(weekday, isOffRange), [weekday, isOffRange]);
export default function CustomDateHeader({ date, label }: DateHeaderProps) {
const { project } = useProjectContext();

return <div className={`pl-3 text-left ${textColor}`}>{date.getDate()}</div>;
// prettier-ignore
const isWithinDateRange = project.startDate && project.endDate
? Validator.isWithinDateRange(project.startDate, project.endDate, date)
: true;

const { weekday } = DateTime.fromJSDate(date);
const textColor = getTextColor(weekday, isWithinDateRange);

return <div className={`pl-3 text-left ${textColor}`}>{label.padStart(2, '0')}</div>;
}
1 change: 0 additions & 1 deletion src/components/task/kanban/ProjectStatusContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ type TaskStatusContainerProps = {
};

export default function TaskStatusContainer({ statusTask }: TaskStatusContainerProps) {
// const [showStatusModal, setShowStatusModal] = useState(false);
const { showModal, openModal, closeModal } = useModal();
const { statusId, name, color, order, tasks } = statusTask;
const draggableId = useMemo(() => generatePrefixId(statusId, DND_DRAGGABLE_PREFIX.STATUS), [statusId]);
Expand Down
22 changes: 22 additions & 0 deletions src/components/user/authForm/AuthForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { FormEvent, ReactNode } from 'react';

type AuthFormProps = {
children: ReactNode;
onSubmit: (e: FormEvent<HTMLFormElement>) => void;
marginTop: 'mt-34.9' | 'mt-40';
};

export default function AuthForm({ children, onSubmit, marginTop }: AuthFormProps) {
return (
<>
<section className="mt-40 text-large text-main">
Welcome to our site!
<br />
Grow Up your Life with us.
</section>
<form onSubmit={onSubmit} className={`${marginTop} flex h-screen w-300 flex-col justify-center gap-8 py-30`}>
{children}
</form>
</>
);
}
57 changes: 57 additions & 0 deletions src/components/user/authForm/FooterLinks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useNavigate } from 'react-router-dom';

type FooterLinksProps = {
type: 'signIn' | 'searchId' | 'searchPassword';
};

const texts = {
signIn: '로그인',
findId: '아이디 찾기',
findPassword: '비밀번호 찾기',
};

const paths = {
signIn: '/signin',
findId: '/search/id',
findPassword: '/search/password',
};

const links = {
signIn: [
{ text: texts.findId, path: paths.findId },
{ text: texts.findPassword, path: paths.findPassword },
],
searchId: [
{ text: texts.signIn, path: paths.signIn },
{ text: texts.findPassword, path: paths.findPassword },
],
searchPassword: [
{ text: texts.signIn, path: paths.signIn },
{ text: texts.findId, path: paths.findId },
],
};

export default function FooterLinks({ type }: FooterLinksProps) {
const nav = useNavigate();

return (
<>
<div className="flex flex-row justify-center">
{links[type].map((link, index) => (
<div key={link.text} className="flex flex-row">
<button type="button" className="cursor-pointer bg-inherit font-bold" onClick={() => nav(link.path)}>
{link.text}
</button>
{index < links[type].length - 1 && <p className="mx-8">|</p>}
</div>
))}
</div>
<div className="mb-35 mt-15 flex flex-row items-center justify-center gap-8">
<p className="items-center font-bold">회원이 아니신가요?</p>
<button type="button" className="auth-btn" onClick={() => nav('/signup')}>
회원가입
</button>
</div>
</>
);
}
46 changes: 35 additions & 11 deletions src/constants/formValidationRules.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Validator from '@utils/Validator';
import { deepFreeze } from '@utils/deepFreeze';
import { EMAIL_REGEX, PASSWORD_REGEX, PHONE_REGEX } from './regex';
import { EMAIL_REGEX, ID_REGEX, NICKNAME_REGEX, PASSWORD_REGEX, PHONE_REGEX } from './regex';

export const STATUS_VALIDATION_RULES = deepFreeze({
STATUS_NAME: (nameList: string[]) => ({
Expand All @@ -24,29 +24,37 @@ export const STATUS_VALIDATION_RULES = deepFreeze({
duplicatedName: (value: string) => !Validator.isDuplicatedName(colorList, value) || '이미 사용중인 색상입니다.',
},
}),
EMAIL: () => ({
EMAIL: {
required: '이메일 인증을 진행해 주세요.',
pattern: {
value: EMAIL_REGEX,
message: '이메일 형식에 맞지 않습니다.',
},
}),
CERTIFICATION: () => ({ required: '인증번호를 입력해 주세요.' }),
PHONE: () => ({
},
CERTIFICATION: { required: '인증번호를 입력해 주세요.' },
PHONE: {
required: '휴대폰 번호 인증을 진행해 주세요.',
pattern: {
value: PHONE_REGEX,
message: '휴대폰 번호를 정확히 입력해 주세요.',
},
}),
NICKNAME: () => ({
},
NICKNAME: {
required: '닉네임을 입력해 주세요.',
minLength: {
value: 2,
message: '닉네임은 최소 2자 이상이어야 합니다.',
},
maxLength: {
value: 20,
message: '닉네임은 최대 20자까지 입력 가능합니다.',
},
}),
PASSWORD: () => ({
pattern: {
value: NICKNAME_REGEX,
message: '닉네임은 영문, 한글, 숫자만 포함 가능합니다.',
},
},
PASSWORD: {
required: '비밀번호를 입력해 주세요.',
minLength: {
value: 8,
Expand All @@ -60,8 +68,24 @@ export const STATUS_VALIDATION_RULES = deepFreeze({
value: PASSWORD_REGEX,
message: '비밀번호는 영문자, 숫자, 기호를 모두 포함해야 합니다.',
},
}),
PASSWORD_CONFIRM: () => ({
},
PASSWORD_CONFIRM: (password: string) => ({
required: '비밀번호를 한 번 더 입력해 주세요.',
validate: (value: string) => value === password || '비밀번호가 일치하지 않습니다.',
}),
ID: {
required: '아이디를 입력해 주세요.',
minLength: {
value: 2,
message: '아이디는 최소 2자 이상이어야 합니다.',
},
maxLength: {
value: 255,
message: '아이디는 최대 255자 이하여야 합니다.',
},
pattern: {
value: ID_REGEX,
message: '아이디는 영문, 한글, 숫자 및 특수기호(., @, _, +, -)만 포함 가능합니다.',
},
},
});
2 changes: 2 additions & 0 deletions src/constants/regex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export const EMAIL_REGEX = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}(?:\.[a-z]{2,}
export const PASSWORD_REGEX =
/^(?=.*[A-Za-z])(?=.*\d)(?=.*[~`!@#$%^&*()_\-+={[}\]|\\:;"'<,>.?/])[A-Za-z\d~`!@#$%^&*()_\-+={[}\]|\\:;"'<,>.?/]{8,16}$/;
export const PHONE_REGEX = /^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})$/;
export const NICKNAME_REGEX = /^[a-zA-Z0-9가-힣]+$/;
export const ID_REGEX = /^[a-z0-9._+@가-힣-]+(?:@[a-z0-9.-]+\.[a-z]{2,}(?:\.[a-z]{2,}))?$/i;
7 changes: 7 additions & 0 deletions src/customReactBigCalendar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.rbc-off-range-bg {
background: #f4f4f4;
}

.rbc-selected-cell {
background: var(--color-sub);
}
6 changes: 1 addition & 5 deletions src/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@
}

.auth-btn {
@apply flex h-30 items-center justify-center rounded-lg bg-sub px-8 font-bold;
}

.auth-input {
@apply h-30 flex-grow rounded-lg border border-input px-8 text-sm outline-none placeholder:text-emphasis;
@apply flex h-30 cursor-pointer items-center justify-center rounded-lg bg-sub px-8 font-bold;
}
}
8 changes: 8 additions & 0 deletions src/hooks/useProjectContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useOutletContext } from 'react-router-dom';
import { Project } from '@/types/ProjectType';

export type ProjectContext = { project: Project };

export default function useProjectContext() {
return useOutletContext<ProjectContext>();
}
13 changes: 8 additions & 5 deletions src/layouts/page/ProjectLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { useMemo } from 'react';
import { NavLink, Outlet, useParams } from 'react-router-dom';
import { Navigate, NavLink, Outlet, useParams } from 'react-router-dom';
import useModal from '@hooks/useModal';
import ListSidebar from '@components/sidebar/ListSidebar';
import ListProject from '@components/sidebar/ListProject';
import CreateModalTask from '@components/modal/task/CreateModalTask';
import CreateModalProjectStatus from '@components/modal/project-status/CreateModalProjectStatus';
import { ProjectContext } from '@hooks/useProjectContext';
import { PROJECT_DUMMY } from '@mocks/mockData';
import { RiSettings5Fill } from 'react-icons/ri';
import CreateModalTask from '@/components/modal/task/CreateModalTask';

export default function ProjectLayout() {
const { projectId } = useParams();
const { showModal: showTaskModal, openModal: openTaskModal, closeModal: closeTaskModal } = useModal();
const { showModal: showStatusModal, openModal: openStatusModal, closeModal: closeStatusModal } = useModal();
const target = useMemo(
const project = useMemo(
() => PROJECT_DUMMY.find((project) => project.projectId.toString() === projectId),
[projectId],
);

if (!project) return <Navigate to="/error" replace />;

return (
<>
<section className="flex h-full p-15">
Expand All @@ -27,7 +30,7 @@ export default function ProjectLayout() {
<header className="flex h-30 items-center justify-between border-b p-10">
<div>
<small className="mr-5 font-bold text-category">project</small>
<span className="text-emphasis">{target?.name}</span>
<span className="text-emphasis">{project?.name}</span>
</div>
<div className="flex cursor-pointer items-center text-sm text-main">
<RiSettings5Fill /> Project Setting
Expand Down Expand Up @@ -56,7 +59,7 @@ export default function ProjectLayout() {
</button>
</div>
</div>
<Outlet />
<Outlet context={{ project } satisfies ProjectContext} />
</div>
</section>
</section>
Expand Down
28 changes: 14 additions & 14 deletions src/mocks/mockData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export const PROJECT_DUMMY: Project[] = [
teamId: 1,
name: '캘린더 만들기1',
content: '캘린더 만들기 설명1',
startDate: new Date('2022-01-01'),
endDate: new Date('2022-02-14'),
startDate: new Date('2022-01-01 00:00:00'),
endDate: new Date('2022-02-14 00:00:00'),
createAt: new Date('2022-01-01'),
updateAt: new Date('2022-01-01'),
},
Expand All @@ -58,8 +58,8 @@ export const PROJECT_DUMMY: Project[] = [
teamId: 1,
name: '캘린더 만들기2',
content: '캘린더 만들기 설명2',
startDate: new Date('2022-05-12'),
endDate: new Date('2022-07-31'),
startDate: new Date('2022-05-12 00:00:00'),
endDate: new Date('2022-07-31 00:00:00'),
createAt: new Date('2022-05-12'),
updateAt: new Date('2022-06-01'),
},
Expand All @@ -68,8 +68,8 @@ export const PROJECT_DUMMY: Project[] = [
teamId: 1,
name: '캘린더 만들기3',
content: '캘린더 만들기 설명3',
startDate: new Date('2023-02-05'),
endDate: new Date('2023-06-05'),
startDate: new Date('2023-02-05 00:00:00'),
endDate: new Date('2023-06-05 00:00:00'),
createAt: new Date('2023-02-05'),
updateAt: new Date('2023-02-05'),
},
Expand All @@ -78,8 +78,8 @@ export const PROJECT_DUMMY: Project[] = [
teamId: 1,
name: '캘린더 만들기4',
content: '캘린더 만들기 설명4',
startDate: new Date('2023-04-25'),
endDate: new Date('2023-06-05'),
startDate: new Date('2023-04-25 00:00:00'),
endDate: new Date('2023-06-05 00:00:00'),
createAt: new Date('2023-04-25'),
updateAt: new Date('2023-04-25'),
},
Expand All @@ -88,8 +88,8 @@ export const PROJECT_DUMMY: Project[] = [
teamId: 1,
name: '캘린더 만들기5',
content: '캘린더 만들기 설명5',
startDate: new Date('2023-06-05'),
endDate: new Date('2023-09-12'),
startDate: new Date('2023-06-05 00:00:00'),
endDate: new Date('2023-09-12 00:00:00'),
createAt: new Date('2023-06-05'),
updateAt: new Date('2023-06-05'),
},
Expand Down Expand Up @@ -128,8 +128,8 @@ export const PROJECT_DUMMY: Project[] = [
teamId: 1,
name: '캘린더 만들기9',
content: '캘린더 만들기 설명9',
startDate: new Date('2024-01-01'),
endDate: new Date('2024-12-31'),
startDate: new Date('2024-01-01 00:00:00'),
endDate: new Date('2025-01-01 00:00:00'),
createAt: new Date('2024-01-01'),
updateAt: new Date('2024-07-16'),
},
Expand All @@ -138,8 +138,8 @@ export const PROJECT_DUMMY: Project[] = [
teamId: 1,
name: '캘린더 만들기10',
content: '캘린더 만들기 설명10',
startDate: new Date('2024-05-15'),
endDate: new Date('2024-08-31'),
startDate: new Date('2024-05-15 00:00:00'),
endDate: new Date('2024-09-01 00:00:00'),
createAt: new Date('2024-05-15'),
updateAt: new Date('2025-05-15'),
},
Expand Down
Loading

0 comments on commit 1566f34

Please sign in to comment.