diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..75798ff --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["prettier"], + "parserOptions": { + "project": "./tsconfig.json" + }, + "rules": { + "react/react-in-jsx-scope": "off", + "react/require-default-props": "off" + } +} \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..73854ce --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "printWidth": 80, + "trailingComma": "all", + "singleQuote": true, + "tabWidth": 2, + "semi": true, + "jsxSingleQuote": false, + "quoteProps": "as-needed", + "bracketSpacing": true, + "jsxBracketSameLine": false, + "arrowParens": "avoid" +} \ No newline at end of file diff --git a/public/about-us/we/aboutus_0.jpeg b/public/about-us/we/aboutus_0.jpeg new file mode 100644 index 0000000..554db1e Binary files /dev/null and b/public/about-us/we/aboutus_0.jpeg differ diff --git a/public/about-us/we/aboutus_1.jpeg b/public/about-us/we/aboutus_1.jpeg new file mode 100644 index 0000000..b463c4a Binary files /dev/null and b/public/about-us/we/aboutus_1.jpeg differ diff --git a/public/about-us/we/image 24.png b/public/about-us/we/image 24.png new file mode 100644 index 0000000..843f693 Binary files /dev/null and b/public/about-us/we/image 24.png differ diff --git a/public/about-us/we/image 25.png b/public/about-us/we/image 25.png new file mode 100644 index 0000000..f46ee33 Binary files /dev/null and b/public/about-us/we/image 25.png differ diff --git a/src/api/domain/Auth.ts b/src/api/domain/Auth.ts index 1ab834e..c9b6708 100644 --- a/src/api/domain/Auth.ts +++ b/src/api/domain/Auth.ts @@ -19,7 +19,9 @@ export class Auth { return this.request.post('/auth/register/code', data); } - public async verifyCode(data: VerifyCodeRequestDto): Promise { + public async verifyCode( + data: VerifyCodeRequestDto, + ): Promise { return this.request.post('/auth/register/code/verify', data); } diff --git a/src/api/domain/Member.ts b/src/api/domain/Member.ts index 4b10a47..0ae0bbf 100644 --- a/src/api/domain/Member.ts +++ b/src/api/domain/Member.ts @@ -11,11 +11,15 @@ export class Member { return this.request.put('/member/me/info', data); } - public async updateMyPassword(data: UpdateMyPasswordRequestDto): Promise { + public async updateMyPassword( + data: UpdateMyPasswordRequestDto, + ): Promise { return this.request.patch('/member/me/password', data); } - public async updateMyAvatar(avatar: File): Promise { + public async updateMyAvatar( + avatar: File, + ): Promise { const data = new FormData(); data.append('avatar', avatar); @@ -34,11 +38,15 @@ export class MemberAdmin { return this.request.get('/admin/member/waiting'); } - public async approveWaitingMember(data: ApproveWaitingMemberRequestDto): Promise { + public async approveWaitingMember( + data: ApproveWaitingMemberRequestDto, + ): Promise { return this.request.post('/admin/member/waiting/approve', data); } - public async rejectWaitingMember(data: RejectWaitingMemberRequestDto): Promise { + public async rejectWaitingMember( + data: RejectWaitingMemberRequestDto, + ): Promise { return this.request.post('/admin/member/waiting/reject', data); } @@ -52,11 +60,15 @@ export class MemberAdmin { return this.request.get('/admin/member?page=' + data.page); } - public async searchMembers(data: SearchMembersRequestDto): Promise { + public async searchMembers( + data: SearchMembersRequestDto, + ): Promise { return this.request.get('/admin/member/search?query=' + data.query); } - public async updateMemberRole(data: UpdateMemberRoleRequestDto): Promise { + public async updateMemberRole( + data: UpdateMemberRoleRequestDto, + ): Promise { return this.request.patch('/admin/member/role', data); } @@ -118,7 +130,8 @@ export interface EachGetMembersResponseDto { role: RoleString; } -export interface EachGetMembersForAdminResponseDto extends EachGetMembersResponseDto { +export interface EachGetMembersForAdminResponseDto + extends EachGetMembersResponseDto { email: string; studentId: string; fee: boolean; @@ -192,7 +205,9 @@ export const RoleKoreanMap: Record = { export const RoleKorean = Object.values(RoleKoreanMap); export const RoleKoreanToRole = (role: string): Role => { - const key = Object.keys(RoleKoreanMap).find((key) => RoleKoreanMap[key as RoleString] === role); + const key = Object.keys(RoleKoreanMap).find( + key => RoleKoreanMap[key as RoleString] === role, + ); return Role[key as RoleString]; }; diff --git a/src/api/domain/activity/Project.ts b/src/api/domain/activity/Project.ts index cae36b7..dbcee56 100644 --- a/src/api/domain/activity/Project.ts +++ b/src/api/domain/activity/Project.ts @@ -3,19 +3,27 @@ import { MemberType, WinkApiRequest } from '@/api'; export class Project { constructor(private readonly request: WinkApiRequest) {} - public async getProject(data: GetProjectRequestDto): Promise { - return this.request.get('/activity/project/detail?projectId=' + data.projectId); + public async getProject( + data: GetProjectRequestDto, + ): Promise { + return this.request.get( + '/activity/project/detail?projectId=' + data.projectId, + ); } public async getProjectsPage(): Promise { return this.request.get('/activity/project/max'); } - public async getProjects(data: GetProjectsRequestDto): Promise { + public async getProjects( + data: GetProjectsRequestDto, + ): Promise { return this.request.get('/activity/project?page=' + data.page); } - public async searchProjects(data: SearchProjectsRequestDto): Promise { + public async searchProjects( + data: SearchProjectsRequestDto, + ): Promise { return this.request.get('/activity/project/search?query=' + data.query); } } @@ -23,7 +31,9 @@ export class Project { export class ProjectAdmin { constructor(private readonly request: WinkApiRequest) {} - public async createProject(data: CreateProjectRequestDto): Promise { + public async createProject( + data: CreateProjectRequestDto, + ): Promise { return this.request.put('/admin/activity/project', data); } diff --git a/src/api/domain/activity/Social.ts b/src/api/domain/activity/Social.ts index 40fffd9..f67b52a 100644 --- a/src/api/domain/activity/Social.ts +++ b/src/api/domain/activity/Social.ts @@ -3,19 +3,27 @@ import { WinkApiRequest } from '@/api'; export class Social { constructor(private readonly request: WinkApiRequest) {} - public async getSocial(data: GetSocialRequestDto): Promise { - return this.request.get('/activity/social/detail?socialId=' + data.socialId); + public async getSocial( + data: GetSocialRequestDto, + ): Promise { + return this.request.get( + '/activity/social/detail?socialId=' + data.socialId, + ); } public async getSocialsPage(): Promise { return this.request.get('/activity/social/max'); } - public async getSocials(data: GetSocialsRequestDto): Promise { + public async getSocials( + data: GetSocialsRequestDto, + ): Promise { return this.request.get('/activity/social?page=' + data.page); } - public async searchSocials(data: SearchSocialsRequestDto): Promise { + public async searchSocials( + data: SearchSocialsRequestDto, + ): Promise { return this.request.get('/activity/social/search?query=' + data.query); } } @@ -23,7 +31,9 @@ export class Social { export class SocialAdmin { constructor(private readonly request: WinkApiRequest) {} - public async createSocial(data: CreateSocialRequestDto): Promise { + public async createSocial( + data: CreateSocialRequestDto, + ): Promise { return this.request.put('/admin/activity/social', data); } diff --git a/src/api/domain/activity/Study.ts b/src/api/domain/activity/Study.ts index 459fc30..8be2ed9 100644 --- a/src/api/domain/activity/Study.ts +++ b/src/api/domain/activity/Study.ts @@ -11,11 +11,15 @@ export class Study { return this.request.get('/activity/study/max'); } - public async getStudies(data: GetStudiesRequestDto): Promise { + public async getStudies( + data: GetStudiesRequestDto, + ): Promise { return this.request.get('/activity/study?page=' + data.page); } - public async searchStudies(data: SearchStudiesRequestDto): Promise { + public async searchStudies( + data: SearchStudiesRequestDto, + ): Promise { return this.request.get('/activity/study/search?query=' + data.query); } } @@ -23,7 +27,9 @@ export class Study { export class StudyAdmin { constructor(private readonly request: WinkApiRequest) {} - public async createCategory(data: CreateCategoryRequestDto): Promise { + public async createCategory( + data: CreateCategoryRequestDto, + ): Promise { return this.request.put('/admin/activity/study/category', data); } @@ -35,7 +41,9 @@ export class StudyAdmin { return this.request.delete('/admin/activity/study/category', data); } - public async createStudy(data: CreateStudyRequestDto): Promise { + public async createStudy( + data: CreateStudyRequestDto, + ): Promise { return this.request.put('/admin/activity/study', data); } diff --git a/src/api/request/WinkApiRequest.ts b/src/api/request/WinkApiRequest.ts index 5877924..191b178 100644 --- a/src/api/request/WinkApiRequest.ts +++ b/src/api/request/WinkApiRequest.ts @@ -65,9 +65,12 @@ export class WinkApiRequest { private async refresh(): Promise { try { - const { accessToken, refreshToken } = await this.post('/auth/refresh', { - refreshToken: this.refreshToken, - }); + const { accessToken, refreshToken } = await this.post( + '/auth/refresh', + { + refreshToken: this.refreshToken, + }, + ); this.setToken(accessToken, refreshToken); diff --git a/src/app/about-us/_components/ActivicyCard/index.tsx b/src/app/about-us/_components/ActivicyCard/index.tsx new file mode 100644 index 0000000..8e7e601 --- /dev/null +++ b/src/app/about-us/_components/ActivicyCard/index.tsx @@ -0,0 +1,26 @@ +// components/CardLayout.js +import Image from 'next/image'; + +const ActivityCard = ({ imageSrc, title, description, isImageRight }) => { + return ( +
+
+ {title} +
+
+

{title}

+

{description}

+
+
+ ); +}; + +export default ActivityCard; diff --git a/src/app/about-us/member/page.tsx b/src/app/about-us/member/page.tsx index db501ea..191cf5a 100644 --- a/src/app/about-us/member/page.tsx +++ b/src/app/about-us/member/page.tsx @@ -16,21 +16,25 @@ const MEMBERS = [ description: '비품 및 회비 관리, 도서 신청 및 대출 관리', filter: (member: EachGetMembersResponseDto) => member.role === 'TREASURY_HEAD' || member.role === 'TREASURY_ASSISTANT', - sort: (a: EachGetMembersResponseDto) => (a.role === 'TREASURY_HEAD' ? -1 : 1), + sort: (a: EachGetMembersResponseDto) => + a.role === 'TREASURY_HEAD' ? -1 : 1, }, { title: '홍보부', description: '동아리 홍보 및 홍보물 제작, SNS 관리', filter: (member: EachGetMembersResponseDto) => - member.role === 'PUBLIC_RELATIONS_HEAD' || member.role === 'PUBLIC_RELATIONS_ASSISTANT', - sort: (a: EachGetMembersResponseDto) => (a.role === 'PUBLIC_RELATIONS_HEAD' ? -1 : 1), + member.role === 'PUBLIC_RELATIONS_HEAD' || + member.role === 'PUBLIC_RELATIONS_ASSISTANT', + sort: (a: EachGetMembersResponseDto) => + a.role === 'PUBLIC_RELATIONS_HEAD' ? -1 : 1, }, { title: '기획부', description: '동아리 행사 기획 및 진행, 회의록 작성', filter: (member: EachGetMembersResponseDto) => member.role === 'PLANNING_HEAD' || member.role === 'PLANNING_ASSISTANT', - sort: (a: EachGetMembersResponseDto) => (a.role === 'PLANNING_HEAD' ? -1 : 1), + sort: (a: EachGetMembersResponseDto) => + a.role === 'PLANNING_HEAD' ? -1 : 1, }, ]; @@ -51,7 +55,12 @@ const AboutUsMemberPage = () => { return (
- cloud + cloud

NEW WAVE IN US

@@ -71,8 +80,12 @@ const AboutUsMemberPage = () => {
{members - .filter((member) => member.role === 'PRESIDENT' || member.role === 'VICE_PRESIDENT') - .sort((a) => (a.role === 'PRESIDENT' ? -1 : 1)) + .filter( + member => + member.role === 'PRESIDENT' || + member.role === 'VICE_PRESIDENT', + ) + .sort(a => (a.role === 'PRESIDENT' ? -1 : 1)) .map(({ _id, name, avatar, description, link, role }) => ( {
{MEMBERS.map(({ title, description, filter, sort }) => (
-

<{title}>

-

{description}

+

+ <{title}> +

+

+ {description} +

{members @@ -119,7 +136,7 @@ const AboutUsMemberPage = () => {
{members - .filter((member) => member.role === 'MEMBER') + .filter(member => member.role === 'MEMBER') .sort((a, b) => a.name.localeCompare(b.name)) .map(({ _id, name, avatar, description, link }) => ( { return ( @@ -10,7 +18,10 @@ const AboutUsWePage = () => {

- 나만의 서비스. 기획. 개발 + + + 나만의 서비스. 기획. 개발 +
우리 안의 새로운 물결 WINK

@@ -19,8 +30,77 @@ const AboutUsWePage = () => { 지원하기 {'>'}

+
+
+

+ 자꾸만 눈이가는 +
+ 멋진 모습 +

+
+ thumbnail +
+
+
+
+ thumbnail +
+

+ 국민대학교 소프트웨어융합대학의 +
+ 유일무이 웹 학술 동아리 +
+ 친목부터 대외활동까지 한 번에 챙겨요 +

+
+
+
+
+
+

+ 안녕하세요. 우리는 WINK 입니다. +

+
+ thumbnail +
-
+

+ 우리는 어떤 길을
걸어왔을까요?{' '} +

+
+ +
+
+ +
+
+ +
+
+ +
+
+
); }; diff --git a/src/app/activity/history/page.tsx b/src/app/activity/history/page.tsx index 27d4b9e..e09745a 100644 --- a/src/app/activity/history/page.tsx +++ b/src/app/activity/history/page.tsx @@ -44,15 +44,17 @@ const ActivityHistoryPage = () => { const toggleItem = (id: string) => { console.log(id); - setOpenItems((prev) => - prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id], + setOpenItems(prev => + prev.includes(id) ? prev.filter(item => item !== id) : [...prev, id], ); }; return (
-

WINK, 우리들의 파도

+

+ WINK, 우리들의 파도 +

행사 / 세미나 / 대회 활동 기록을 년도 별로 볼 수 있습니다.

@@ -61,7 +63,7 @@ const ActivityHistoryPage = () => {
- {timelineData.map((yearData) => ( + {timelineData.map(yearData => (
{yearData.year} @@ -76,8 +78,12 @@ const ActivityHistoryPage = () => { > - {item.date} - {item.title} + + {item.date} + + + {item.title} + {openItems.includes(`${yearData.year}-${index}`) ? ( diff --git a/src/app/activity/project/[id]/page.tsx b/src/app/activity/project/[id]/page.tsx index 8507bd0..45539f2 100644 --- a/src/app/activity/project/[id]/page.tsx +++ b/src/app/activity/project/[id]/page.tsx @@ -17,7 +17,9 @@ const ActivityProjectViewPage = ({ params }: ActivityProjectViewPageProps) => { useEffect(() => { const fetchProject = async () => { - const { project } = await WinkApi.Activity.Project.getProject({ projectId: params.id }); + const { project } = await WinkApi.Activity.Project.getProject({ + projectId: params.id, + }); setProject(project); }; @@ -36,11 +38,13 @@ const ActivityProjectViewPage = ({ params }: ActivityProjectViewPageProps) => {
{project.author.name} - {formatDate(project.createdAt)} + + {formatDate(project.createdAt)} +
- {project.tags.map((tag) => ( + {project.tags.map(tag => ( { ))}
- {}} readonly={true} /> + {}} + readonly={true} + />
); diff --git a/src/app/activity/project/page.tsx b/src/app/activity/project/page.tsx index 29d7720..57694fd 100644 --- a/src/app/activity/project/page.tsx +++ b/src/app/activity/project/page.tsx @@ -28,7 +28,7 @@ const ActivityProjectPage = () => { const { projects } = await WinkApi.Activity.Project.getProjects({ page, }); - setProjects((prev) => [...prev, ...projects]); + setProjects(prev => [...prev, ...projects]); }; (async () => { @@ -40,8 +40,12 @@ const ActivityProjectPage = () => { <>
-

WINK, 우리들의 파도

-

나날히 성장해 가는 우리

+

+ WINK, 우리들의 파도 +

+

+ 나날히 성장해 가는 우리 +

{/* Carousel 영역 */} @@ -74,7 +78,7 @@ const ActivityProjectPage = () => { {page < maxPage && (
@@ -105,7 +119,7 @@ const ActivityStudyPage = () => { transition={{ duration: 0.2, ease: 'easeInOut' }} className="absolute z-10 w-full mt-1 bg-white border rounded-md shadow-lg overflow-y-auto" > - {categories.map((category) => ( + {categories.map(category => (
{
- {filteredStudies.slice(4).map(({ _id, image, link, title, content, author }) => ( - - ))} + {filteredStudies + .slice(4) + .map(({ _id, image, link, title, content, author }) => ( + + ))}
@@ -141,7 +157,7 @@ const ActivityStudyPage = () => {
diff --git a/src/app/admin/activity/project/page.tsx b/src/app/admin/activity/project/page.tsx index 467bcb5..98179c4 100644 --- a/src/app/admin/activity/project/page.tsx +++ b/src/app/admin/activity/project/page.tsx @@ -45,7 +45,9 @@ const AdminActivityProjectPage = () => { async function fetchProjects() { if (query) { - const { projects } = await WinkApi.Activity.Project.searchProjects({ query }); + const { projects } = await WinkApi.Activity.Project.searchProjects({ + query, + }); setProjects(projects); } else { const { projects } = await WinkApi.Activity.Project.getProjects({ page }); @@ -56,7 +58,9 @@ const AdminActivityProjectPage = () => { const handleDelete = async () => { if (!deleteModal) return; - await WinkApi.Activity.ProjectAdmin.deleteProject({ projectId: deleteModal._id }); + await WinkApi.Activity.ProjectAdmin.deleteProject({ + projectId: deleteModal._id, + }); await fetchProjects(); toast.warn(`"${deleteModal.title}" 프로젝트가 삭제되었습니다.`); @@ -69,7 +73,11 @@ const AdminActivityProjectPage = () => { <div className="flex justify-end mb-4 space-x-4"> - <SearchBar value={query} placeholder="제목을 검색해주세요." onChange={setQuery} /> + <SearchBar + value={query} + placeholder="제목을 검색해주세요." + onChange={setQuery} + /> <IconButton icon={<FaEdit />} @@ -94,20 +102,27 @@ const AdminActivityProjectPage = () => { </div> </div> - {projects.map((project) => ( - <div key={project._id} className="grid grid-cols-12 gap-2 border-b border-gray-200"> + {projects.map(project => ( + <div + key={project._id} + className="grid grid-cols-12 gap-2 border-b border-gray-200" + > <Link href={`/activity/project/${project._id}`} className="py-4 px-4 col-span-7 text-sm truncate" > {project.title} </Link> - <div className="py-4 px-4 col-span-3 text-sm">{formatDate(project.createdAt)}</div> + <div className="py-4 px-4 col-span-3 text-sm"> + {formatDate(project.createdAt)} + </div> <div className="col-span-1 flex items-center justify-center space-x-8"> <FaEdit size={18} className="cursor-pointer" - onClick={() => router.push(`/admin/activity/project/editor/${project._id}`)} + onClick={() => + router.push(`/admin/activity/project/editor/${project._id}`) + } /> </div> <div className="col-span-1 flex items-center justify-center space-x-8"> @@ -140,7 +155,9 @@ const AdminActivityProjectPage = () => { </div> </Modal> - {!query && maxPage > 0 && <TablePaging page={page} setPage={setPage} maxPage={maxPage} />} + {!query && maxPage > 0 && ( + <TablePaging page={page} setPage={setPage} maxPage={maxPage} /> + )} </div> ); }; diff --git a/src/app/admin/activity/social/editor/[id]/page.tsx b/src/app/admin/activity/social/editor/[id]/page.tsx index 3ce07c7..dae60d4 100644 --- a/src/app/admin/activity/social/editor/[id]/page.tsx +++ b/src/app/admin/activity/social/editor/[id]/page.tsx @@ -15,7 +15,9 @@ interface AdminActivitySocialEditorPageProps { params: { id: string }; } -const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPageProps) => { +const AdminActivitySocialEditorPage = ({ + params, +}: AdminActivitySocialEditorPageProps) => { const router = useRouter(); const [title, setTitle] = React.useState<string>(''); const [contents, setContents] = React.useState<Content[]>([ @@ -28,7 +30,9 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage useEffect(() => { if (params.id !== 'new') { (async () => { - const { social } = await WinkApi.Activity.Social.getSocial({ socialId: params.id }); + const { social } = await WinkApi.Activity.Social.getSocial({ + socialId: params.id, + }); setTitle(social.title); setContents(social.contents); @@ -36,12 +40,15 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage } }, []); - const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>, index: number) => { + const handleImageUpload = async ( + e: React.ChangeEvent<HTMLInputElement>, + index: number, + ) => { const file = e.target.files?.[0]; if (file) { const { link } = await WinkApi.Activity.CommonAdmin.upload(file); - setContents((prev) => { + setContents(prev => { prev[index].image = link; return [...prev]; }); @@ -81,7 +88,9 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage icon={<FaPlus />} text="페이지 추가" className="bg-green-500 hover:bg-green-600 border-0 text-white" - onClick={() => setContents((prev) => [...prev, { content: '', image: '' }])} + onClick={() => + setContents(prev => [...prev, { content: '', image: '' }]) + } /> <IconButton @@ -89,7 +98,7 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage text="페이지 삭제" disabled={contents.length === 1} className="bg-red-500 hover:bg-red-600 border-0 text-white disabled:bg-gray-300" - onClick={() => setContents((prev) => prev.slice(0, -1))} + onClick={() => setContents(prev => prev.slice(0, -1))} /> <IconButton @@ -107,7 +116,7 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage value={title} placeholder="친목 활동을 입력해주세요." className="px-3 py-4 border-border rounded focus:outline-none focus:ring-1 focus:ring-wink-300 placeholder-gray-600 p-2 text-sm border" - onChange={(e) => setTitle(e.target.value)} + onChange={e => setTitle(e.target.value)} /> </div> @@ -117,7 +126,7 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage id={`fileInput-${i}`} type="file" accept="image/*" - onChange={(e) => handleImageUpload(e, i)} + onChange={e => handleImageUpload(e, i)} className="hidden" /> @@ -143,7 +152,10 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage document.getElementById(`fileInput-${i}`)?.click(); }} > - <label htmlFor="fileInput" className="flex flex-col items-center justify-center"> + <label + htmlFor="fileInput" + className="flex flex-col items-center justify-center" + > <FaUpload className="text-4xl text-gray-400 mb-1" size={24} /> <span className="text-gray-600">Upload Image</span> </label> @@ -153,8 +165,8 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage <div className="mt-2"> <Editor content={content.content} - setContent={(value) => - setContents((prev) => { + setContent={value => + setContents(prev => { prev[i].content = value; return [...prev]; }) @@ -162,7 +174,9 @@ const AdminActivitySocialEditorPage = ({ params }: AdminActivitySocialEditorPage /> </div> - {i !== contents.length - 1 && <div className="border-b border-gray-200 my-4" />} + {i !== contents.length - 1 && ( + <div className="border-b border-gray-200 my-4" /> + )} </div> ))} </div> diff --git a/src/app/admin/activity/social/page.tsx b/src/app/admin/activity/social/page.tsx index d898d3a..f16dc31 100644 --- a/src/app/admin/activity/social/page.tsx +++ b/src/app/admin/activity/social/page.tsx @@ -44,7 +44,9 @@ const AdminActivitySocialPage = () => { async function fetchSocials() { if (query) { - const { socials } = await WinkApi.Activity.Social.searchSocials({ query }); + const { socials } = await WinkApi.Activity.Social.searchSocials({ + query, + }); setSocials(socials); } else { const { socials } = await WinkApi.Activity.Social.getSocials({ page }); @@ -55,7 +57,9 @@ const AdminActivitySocialPage = () => { const handleDelete = async () => { if (!deleteModal) return; - await WinkApi.Activity.SocialAdmin.deleteSocial({ socialId: deleteModal._id }); + await WinkApi.Activity.SocialAdmin.deleteSocial({ + socialId: deleteModal._id, + }); await fetchSocials(); toast.warn(`"${deleteModal.title}" 친목 활동이 삭제되었습니다.`); @@ -68,7 +72,11 @@ const AdminActivitySocialPage = () => { <Title title="Activity" subtitle="친목 활동" /> <div className="flex justify-end mb-4 space-x-4"> - <SearchBar value={query} placeholder="제목을 검색해주세요." onChange={setQuery} /> + <SearchBar + value={query} + placeholder="제목을 검색해주세요." + onChange={setQuery} + /> <IconButton icon={<FaEdit />} @@ -93,15 +101,24 @@ const AdminActivitySocialPage = () => { </div> </div> - {socials.map((social) => ( - <div key={social._id} className="grid grid-cols-12 gap-2 border-b border-gray-200"> - <div className="py-4 px-4 col-span-7 text-sm truncate">{social.title}</div> - <div className="py-4 px-4 col-span-3 text-sm">{formatDate(social.createdAt)}</div> + {socials.map(social => ( + <div + key={social._id} + className="grid grid-cols-12 gap-2 border-b border-gray-200" + > + <div className="py-4 px-4 col-span-7 text-sm truncate"> + {social.title} + </div> + <div className="py-4 px-4 col-span-3 text-sm"> + {formatDate(social.createdAt)} + </div> <div className="col-span-1 flex items-center justify-center space-x-8"> <FaEdit size={18} className="cursor-pointer" - onClick={() => router.push(`/admin/activity/social/editor/${social._id}`)} + onClick={() => + router.push(`/admin/activity/social/editor/${social._id}`) + } /> </div> <div className="col-span-1 flex items-center justify-center space-x-8"> @@ -134,7 +151,9 @@ const AdminActivitySocialPage = () => { </div> </Modal> - {!query && maxPage > 0 && <TablePaging page={page} setPage={setPage} maxPage={maxPage} />} + {!query && maxPage > 0 && ( + <TablePaging page={page} setPage={setPage} maxPage={maxPage} /> + )} </div> ); }; diff --git a/src/app/admin/activity/study/category/page.tsx b/src/app/admin/activity/study/category/page.tsx index ef79391..d92ce15 100644 --- a/src/app/admin/activity/study/category/page.tsx +++ b/src/app/admin/activity/study/category/page.tsx @@ -5,7 +5,13 @@ import { FaEdit } from 'react-icons/fa'; import { FaTrashCan } from 'react-icons/fa6'; import { toast } from 'react-toastify'; -import { FormContainer, IconButton, Modal, TextField, Title } from '@/component'; +import { + FormContainer, + IconButton, + Modal, + TextField, + Title, +} from '@/component'; import { useForm } from '@/hook'; @@ -16,13 +22,20 @@ import * as yup from 'yup'; type Inputs = 'category'; const AdminActivityStudyCategoryPage = () => { - const [categories, setCategories] = useState<EachGetCategoriesResponseDto[]>([]); + const [categories, setCategories] = useState<EachGetCategoriesResponseDto[]>( + [], + ); const [createModal, setCreateModal] = useState<boolean>(false); - const [modifyModal, setModifyModal] = useState<EachGetCategoriesResponseDto | null>(null); - const [deleteModal, setDeleteModal] = useState<EachGetCategoriesResponseDto | null>(null); - - const { values, setValues, errors, setErrors, onChange, validate } = useForm<Inputs, string>( + const [modifyModal, setModifyModal] = + useState<EachGetCategoriesResponseDto | null>(null); + const [deleteModal, setDeleteModal] = + useState<EachGetCategoriesResponseDto | null>(null); + + const { values, setValues, errors, setErrors, onChange, validate } = useForm< + Inputs, + string + >( yup.object({ category: yup.string().required('카테고리 이름을 입력해주세요.'), }), @@ -77,7 +90,9 @@ const AdminActivityStudyCategoryPage = () => { const handleDelete = async () => { if (!deleteModal) return; - await WinkApi.Activity.StudyAdmin.deleteCategory({ categoryId: deleteModal._id }); + await WinkApi.Activity.StudyAdmin.deleteCategory({ + categoryId: deleteModal._id, + }); await fetchCategories(); toast.warn(`"${deleteModal.name}" 카테고리가 삭제되었습니다.`); @@ -113,10 +128,15 @@ const AdminActivityStudyCategoryPage = () => { </div> </div> - {categories.map((category) => ( - <div key={category._id} className="grid grid-cols-12 gap-2 border-b border-gray-200"> + {categories.map(category => ( + <div + key={category._id} + className="grid grid-cols-12 gap-2 border-b border-gray-200" + > <div className="py-4 px-4 col-span-8 text-sm">{category.name}</div> - <div className="py-4 px-4 col-span-2 text-sm">{category.dependencies}개</div> + <div className="py-4 px-4 col-span-2 text-sm"> + {category.dependencies}개 + </div> <div className="col-span-1 flex items-center justify-center space-x-8"> <FaEdit size={18} @@ -206,7 +226,8 @@ const AdminActivityStudyCategoryPage = () => { {deleteModal && deleteModal.dependencies > 0 && ( <p className="mt-2"> 이 카테고리를 삭제하면{' '} - <strong>{deleteModal.dependencies}개의 스터디가 모두 삭제</strong>됩니다. + <strong>{deleteModal.dependencies}개의 스터디가 모두 삭제</strong> + 됩니다. </p> )} <div className="flex justify-end mt-4"> diff --git a/src/app/admin/activity/study/page.tsx b/src/app/admin/activity/study/page.tsx index b2a1cea..d881e86 100644 --- a/src/app/admin/activity/study/page.tsx +++ b/src/app/admin/activity/study/page.tsx @@ -38,7 +38,10 @@ const AdminActivityStudyPage = () => { const [createModal, setCreateModal] = useState<boolean>(false); const [deleteModal, setDeleteModal] = useState<StudyType | null>(null); - const { values, setValues, errors, setErrors, onChange, validate } = useForm<Inputs, string>( + const { values, setValues, errors, setErrors, onChange, validate } = useForm< + Inputs, + string + >( yup.object({ link: yup .string() @@ -109,7 +112,11 @@ const AdminActivityStudyPage = () => { <Title title="Activity" subtitle="스터디" /> <div className="flex justify-end mb-4 space-x-4"> - <SearchBar value={query} placeholder="제목을 검색해주세요." onChange={setQuery} /> + <SearchBar + value={query} + placeholder="제목을 검색해주세요." + onChange={setQuery} + /> <IconButton icon={<FaEdit />} @@ -134,15 +141,25 @@ const AdminActivityStudyPage = () => { </div> </div> - {studies.map((study) => ( - <div key={study._id} className="grid grid-cols-12 gap-2 border-b border-gray-200"> - <div className="py-4 px-4 col-span-2 text-sm truncate">{study.category.name}</div> + {studies.map(study => ( + <div + key={study._id} + className="grid grid-cols-12 gap-2 border-b border-gray-200" + > + <div className="py-4 px-4 col-span-2 text-sm truncate"> + {study.category.name} + </div> - <Link href={study.link} className="py-4 px-4 col-span-6 text-sm truncate"> + <Link + href={study.link} + className="py-4 px-4 col-span-6 text-sm truncate" + > {study.title} </Link> - <div className="py-4 px-4 col-span-3 text-sm">{formatDate(study.uploadedAt)}</div> + <div className="py-4 px-4 col-span-3 text-sm"> + {formatDate(study.uploadedAt)} + </div> <div className="col-span-1 flex items-center justify-center space-x-8"> <FaTrashCan @@ -207,7 +224,9 @@ const AdminActivityStudyPage = () => { </div> </Modal> - {!query && maxPage > 0 && <TablePaging page={page} setPage={setPage} maxPage={maxPage} />} + {!query && maxPage > 0 && ( + <TablePaging page={page} setPage={setPage} maxPage={maxPage} /> + )} </div> ); }; diff --git a/src/app/admin/member/list/page.tsx b/src/app/admin/member/list/page.tsx index 04e840b..b30888c 100644 --- a/src/app/admin/member/list/page.tsx +++ b/src/app/admin/member/list/page.tsx @@ -14,7 +14,9 @@ import { } from '@/api'; const AdminMemberListPage = () => { - const [members, setMembers] = useState<EachGetMembersForAdminResponseDto[]>([]); + const [members, setMembers] = useState<EachGetMembersForAdminResponseDto[]>( + [], + ); const [page, setPage] = useState<number>(1); const [maxPage, setMaxPage] = useState<number>(0); const [query, setQuery] = useState<string>(''); @@ -42,7 +44,10 @@ const AdminMemberListPage = () => { } } - const handleRoleChange = async (member: EachGetMembersForAdminResponseDto, rawRole: string) => { + const handleRoleChange = async ( + member: EachGetMembersForAdminResponseDto, + rawRole: string, + ) => { await WinkApi.MemberAdmin.updateMemberRole({ memberId: member._id, role: RoleKoreanToRole(rawRole), @@ -52,11 +57,16 @@ const AdminMemberListPage = () => { toast.success(`${member.name}님의 역할을 "${rawRole}"로 변경하였습니다.`); }; - const handleFeeChange = async (member: EachGetMembersForAdminResponseDto, fee: boolean) => { + const handleFeeChange = async ( + member: EachGetMembersForAdminResponseDto, + fee: boolean, + ) => { await WinkApi.MemberAdmin.updateMemberFee({ memberId: member._id, fee }); await fetchMembers(); - toast.success(`${member.name}님의 회비 정보를 "${fee ? '납부' : '미납부'}"로 변경하였습니다.`); + toast.success( + `${member.name}님의 회비 정보를 "${fee ? '납부' : '미납부'}"로 변경하였습니다.`, + ); }; return ( @@ -64,7 +74,11 @@ const AdminMemberListPage = () => { <Title title="Member" subtitle="회원 정보 수정" /> <div className="flex justify-end mb-4"> - <SearchBar value={query} placeholder="이름을 검색해주세요." onChange={setQuery} /> + <SearchBar + value={query} + placeholder="이름을 검색해주세요." + onChange={setQuery} + /> </div> <div className="min-w-full grid grid-cols-6 gap-2 border-b"> @@ -85,8 +99,11 @@ const AdminMemberListPage = () => { </div> </div> - {members.map((member) => ( - <div key={member._id} className="grid grid-cols-6 gap-2 border-b border-gray-200"> + {members.map(member => ( + <div + key={member._id} + className="grid grid-cols-6 gap-2 border-b border-gray-200" + > <div className="py-4 px-4 col-span-1 text-sm">{member.name}</div> <div className="py-4 px-4 col-span-1 text-sm">{member.studentId}</div> <div className="py-4 px-4 col-span-2 text-sm">{member.email}</div> @@ -94,20 +111,22 @@ const AdminMemberListPage = () => { <Dropdown value={RoleKoreanMap[member.role]} options={RoleKorean} - onChange={(value) => handleRoleChange(member, value)} + onChange={value => handleRoleChange(member, value)} /> </div> <div className="py-4 px-4 col-span-1 text-sm"> <Dropdown value={member.fee ? '납부' : '미납부'} options={['납부', '미납부']} - onChange={(value) => handleFeeChange(member, value === '납부')} + onChange={value => handleFeeChange(member, value === '납부')} /> </div> </div> ))} - {!query && maxPage > 0 && <TablePaging page={page} setPage={setPage} maxPage={maxPage} />} + {!query && maxPage > 0 && ( + <TablePaging page={page} setPage={setPage} maxPage={maxPage} /> + )} </div> ); }; diff --git a/src/app/admin/member/waiting/page.tsx b/src/app/admin/member/waiting/page.tsx index 4d7fb0b..7955655 100644 --- a/src/app/admin/member/waiting/page.tsx +++ b/src/app/admin/member/waiting/page.tsx @@ -8,7 +8,9 @@ import { SearchBar, Title } from '@/component'; import { EachGetWaitingMembersResponseDto, WinkApi } from '@/api'; const AdminMemberWaitingPage = () => { - const [members, setMembers] = useState<EachGetWaitingMembersResponseDto[]>([]); + const [members, setMembers] = useState<EachGetWaitingMembersResponseDto[]>( + [], + ); const [query, setQuery] = useState<string>(''); useEffect(() => { @@ -41,7 +43,11 @@ const AdminMemberWaitingPage = () => { <Title title="Member" subtitle="회원가입 승인" /> <div className="flex justify-end mb-4"> - <SearchBar value={query} placeholder="이름을 검색해주세요." onChange={setQuery} /> + <SearchBar + value={query} + placeholder="이름을 검색해주세요." + onChange={setQuery} + /> </div> <div className="min-w-full grid grid-cols-5 gap-2 border-b"> @@ -59,8 +65,11 @@ const AdminMemberWaitingPage = () => { </div> </div> - {members.map((member) => ( - <div key={member._id} className="grid grid-cols-5 gap-2 border-b border-gray-200"> + {members.map(member => ( + <div + key={member._id} + className="grid grid-cols-5 gap-2 border-b border-gray-200" + > <div className="py-4 px-4 col-span-1 text-sm">{member.name}</div> <div className="py-4 px-4 col-span-1 text-sm">{member.studentId}</div> <div className="py-4 px-4 col-span-2 text-sm">{member.email}</div> diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx index fe58ba9..41603a4 100644 --- a/src/app/auth/login/page.tsx +++ b/src/app/auth/login/page.tsx @@ -6,7 +6,13 @@ import { toast } from 'react-toastify'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; -import { Button, Fields, FormContainer, TextField, WebInKookmin } from '@/component'; +import { + Button, + Fields, + FormContainer, + TextField, + WebInKookmin, +} from '@/component'; import { useForm } from '@/hook'; @@ -21,7 +27,10 @@ const LoginPage = () => { const { values, errors, validate, onChange } = useForm<Inputs, string>( yup.object({ - email: yup.string().required('이메일을 입력해주세요.').email('이메일 형식이 아닙니다.'), + email: yup + .string() + .required('이메일을 입력해주세요.') + .email('이메일 형식이 아닙니다.'), password: yup.string().required('비밀번호를 입력해주세요.'), }), ); diff --git a/src/app/auth/signup/page.tsx b/src/app/auth/signup/page.tsx index e1802d4..60c5c26 100644 --- a/src/app/auth/signup/page.tsx +++ b/src/app/auth/signup/page.tsx @@ -6,7 +6,13 @@ import { toast } from 'react-toastify'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; -import { Button, Fields, FormContainer, TextField, WebInKookmin } from '@/component'; +import { + Button, + Fields, + FormContainer, + TextField, + WebInKookmin, +} from '@/component'; import { useForm } from '@/hook'; @@ -28,12 +34,19 @@ const SignUpPage = () => { const [isSendCode, setSendCode] = useState(false); - const { values, setValues, errors, validate, onChange } = useForm<Inputs, string>( + const { values, setValues, errors, validate, onChange } = useForm< + Inputs, + string + >( yup.object({ studentId: yup .string() .required('학번을 입력해주세요.') - .test('is-number', '학번은 숫자로만 입력해주세요.', (value) => !isNaN(Number(value))) + .test( + 'is-number', + '학번은 숫자로만 입력해주세요.', + value => !isNaN(Number(value)), + ) .length(8, '학번은 8자리 입니다.'), name: yup .string() @@ -45,11 +58,18 @@ const SignUpPage = () => { .string() .required('이메일을 입력해주세요.') .email('이메일 형식이 아닙니다.') - .matches(/^[a-zA-Z0-9._%+-]+@kookmin\.ac\.kr$/i, '국민대학교 이메일 형식이어야 합니다.'), + .matches( + /^[a-zA-Z0-9._%+-]+@kookmin\.ac\.kr$/i, + '국민대학교 이메일 형식이어야 합니다.', + ), verifyCode: yup .string() .required('인증 코드를 입력해주세요.') - .test('is-number', '인증 코드는 숫자로만 입력해주세요.', (value) => !isNaN(Number(value))) + .test( + 'is-number', + '인증 코드는 숫자로만 입력해주세요.', + value => !isNaN(Number(value)), + ) .length(6, '인증 코드는 6자리 입니다.'), verifyToken: yup.string().required('인증 토큰을 입력해주세요.'), password: yup @@ -138,7 +158,7 @@ const SignUpPage = () => { code: values.verifyCode, }); - setValues((prev) => ({ ...prev, verifyToken })); + setValues(prev => ({ ...prev, verifyToken })); toast.success('인증 코드가 확인되었습니다.'); } @@ -166,9 +186,12 @@ const SignUpPage = () => { <WebInKookmin /> <div className="flex flex-col items-center justify-center gap-2.5"> - <p className="text-xl font-normal">국민대학교 소프트웨어융합대학 유일무이 Web 동아리</p> + <p className="text-xl font-normal"> + 국민대학교 소프트웨어융합대학 유일무이 Web 동아리 + </p> <p className="text-lg text-zinc-500 font-normal"> - 부원 확인을 위하여 회원 가입 요청 후 승인 까지 수 일이 소요될 수 있습니다. + 부원 확인을 위하여 회원 가입 요청 후 승인 까지 수 일이 소요될 수 + 있습니다. </p> </div> @@ -181,7 +204,7 @@ const SignUpPage = () => { onEnter={onSignUpButtonClick} > {fields - .filter((options) => !options.hidden) + .filter(options => !options.hidden) .map(({ id, button, ...rest }) => ( <div key={id} className="flex items-center gap-2.5"> <TextField id={id} {...rest} /> diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e126966..068a514 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -21,7 +21,7 @@ const HIDE_FOOTER_PATHS = ['/auth', '/admin']; const RootLayout = ({ children }: RootLayoutProps) => { const pathname = usePathname(); - const hideFooter = HIDE_FOOTER_PATHS.some((path) => pathname.startsWith(path)); + const hideFooter = HIDE_FOOTER_PATHS.some(path => pathname.startsWith(path)); return ( <html lang="ko"> diff --git a/src/app/recruit/page.tsx b/src/app/recruit/page.tsx index 02d0638..6c9bad0 100644 --- a/src/app/recruit/page.tsx +++ b/src/app/recruit/page.tsx @@ -27,7 +27,12 @@ const RecruitPage = () => { </div> <div className="absolute w-28 top-1/4 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-6xl animate-rocket"> - <Image src={rocketImage} alt={'recruit-rocket'} width={150} height={170} /> + <Image + src={rocketImage} + alt={'recruit-rocket'} + width={150} + height={170} + /> </div> </div> @@ -59,20 +64,26 @@ const RecruitPage = () => { <div> <h1 className="text-3xl font-bold text-center mb-2">모집 대상</h1> <p className="text-center mb-8"> - 함께 활동을 적극적으로 진행할 준비가 되어 있는 웹에 진심인 국민대학교 학생을 모두 - 환영합니다. + 함께 활동을 적극적으로 진행할 준비가 되어 있는 웹에 진심인 국민대학교 + 학생을 모두 환영합니다. </p> <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8"> <div className="bg-white w-64 border border-zinc-500 rounded-2xl p-4"> <h2 className="mb-2 font-semibold text-wink-500">Frontend</h2> <p className="mb-2 font-semibold">프론트엔드 개발자</p> - <p>React.js, Vue.js, Next.js, JavaScript 사용에 능한 프론트엔드 개발자를 환영합니다.</p> + <p> + React.js, Vue.js, Next.js, JavaScript 사용에 능한 프론트엔드 + 개발자를 환영합니다. + </p> </div> <div className="bg-white w-64 border border-zinc-500 rounded-2xl p-4"> <h2 className="mb-2 font-semibold text-wink-500">Backend</h2> <p className="mb-2 font-semibold">백엔드 개발자</p> - <p>Spring Boot, ExpressJS, NestJS 사용에 능한 백엔드 개발자를 환영합니다.</p> + <p> + Spring Boot, ExpressJS, NestJS 사용에 능한 백엔드 개발자를 + 환영합니다. + </p> </div> <div className="bg-white w-64 border border-zinc-500 rounded-2xl p-4"> <h2 className="mb-2 font-semibold text-wink-500">Design/PM</h2> @@ -83,18 +94,26 @@ const RecruitPage = () => { </div> <div className="w-full bg-wink-50/50"> - <h2 className="text-3xl font-bold text-center mt-12 mb-6">자주 묻는 질문</h2> + <h2 className="text-3xl font-bold text-center mt-12 mb-6"> + 자주 묻는 질문 + </h2> <div className="flex flex-col space-y-4 items-center pb-24"> <div className="bg-white w-carousel border border-zinc-500 rounded-2xl p-4"> - <h2 className="mb-2 font-semibold">Q. 타과생도 지원할 수 있나요?</h2> + <h2 className="mb-2 font-semibold"> + Q. 타과생도 지원할 수 있나요? + </h2> <p>A. ㅐㅐㅐㅐㅐㅐㅐㅐ.</p> </div> <div className="bg-white w-carousel border border-zinc-500 rounded-2xl p-4"> - <h2 className="mb-2 font-semibold">Q. 프로젝트 경험이 없어도 괜찮나요?</h2> + <h2 className="mb-2 font-semibold"> + Q. 프로젝트 경험이 없어도 괜찮나요? + </h2> <p>A. ㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇ.</p> </div> <div className="bg-white w-carousel border border-zinc-500 rounded-2xl p-4"> - <h2 className="mb-2 font-semibold">Q. 면접 때 기술 많이 물어보나요?</h2> + <h2 className="mb-2 font-semibold"> + Q. 면접 때 기술 많이 물어보나요? + </h2> <p>A. 지원자 님의 지원서와 학년을 모두 고려하여 질문 드립니다.</p> </div> </div> diff --git a/src/component/AdminSideBar.tsx b/src/component/AdminSideBar.tsx index 268fef4..0d9350e 100644 --- a/src/component/AdminSideBar.tsx +++ b/src/component/AdminSideBar.tsx @@ -35,7 +35,9 @@ export const AdminSideBar: React.FC = () => { <div key={title}> <h2 className="flex items-center justify-between text-lg font-semibold px-6 py-3 border-b"> <span>{title}</span> - <span className="text-sm font-normal text-gray-500">{description}</span> + <span className="text-sm font-normal text-gray-500"> + {description} + </span> </h2> <ul className="mt-2"> {items.map(({ title, href }) => ( diff --git a/src/component/Button.tsx b/src/component/Button.tsx index 79b4ac1..b5c5b94 100644 --- a/src/component/Button.tsx +++ b/src/component/Button.tsx @@ -4,7 +4,11 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { label: string; } -export const Button: React.FC<ButtonProps> = ({ className, label, ...rest }) => { +export const Button: React.FC<ButtonProps> = ({ + className, + label, + ...rest +}) => { return ( <button className={`text-white bg-wink-500 hover:bg-wink-600 rounded focus:outline-none focus:ring-2 focus:ring-wink-300 ${className}`} diff --git a/src/component/Carousel.tsx b/src/component/Carousel.tsx index c9d0b17..f2498b7 100644 --- a/src/component/Carousel.tsx +++ b/src/component/Carousel.tsx @@ -72,9 +72,14 @@ export const Carousel: React.FC<CarouselProps> = ({ cards }: CarouselProps) => { backgroundImage: `url(${card.image})`, backgroundSize: 'cover', backgroundPosition: 'center', - filter: currentIndex !== index && card.image ? 'brightness(0.5) blur(2px)' : 'none', + filter: + currentIndex !== index && card.image + ? 'brightness(0.5) blur(2px)' + : 'none', boxShadow: - currentIndex === index && card.image ? '0 4px 8px rgba(0, 0, 0, 0.5)' : 'none', + currentIndex === index && card.image + ? '0 4px 8px rgba(0, 0, 0, 0.5)' + : 'none', }} /> ))} @@ -84,7 +89,9 @@ export const Carousel: React.FC<CarouselProps> = ({ cards }: CarouselProps) => { {/* 클릭한 카드의 정보 표시 */} {cards.length > 0 && currentIndex !== null && ( <div className="flex flex-col items-center pt-32 pb-12"> - <h2 className="font-bold text-3xl mb-2">{cards[currentIndex].title}</h2> + <h2 className="font-bold text-3xl mb-2"> + {cards[currentIndex].title} + </h2> <p className="font-medium text-slate-500 text-xl max-w-md truncate"> {cheerio.load(cards[currentIndex].content).root().text()} </p> diff --git a/src/component/Dropdown.tsx b/src/component/Dropdown.tsx index 9b37e00..ec9161c 100644 --- a/src/component/Dropdown.tsx +++ b/src/component/Dropdown.tsx @@ -9,7 +9,11 @@ interface DropdownProps { onChange: (value: string) => void; } -export const Dropdown: React.FC<DropdownProps> = ({ value, options, onChange }) => { +export const Dropdown: React.FC<DropdownProps> = ({ + value, + options, + onChange, +}) => { const [isOpen, setIsOpen] = useState(false); return ( @@ -30,7 +34,7 @@ export const Dropdown: React.FC<DropdownProps> = ({ value, options, onChange }) transition={{ duration: 0.2, ease: 'easeInOut' }} className="absolute z-10 w-full mt-1 bg-white border rounded-md shadow-lg overflow-y-auto" > - {options.map((option) => ( + {options.map(option => ( <div key={option} className="px-3 py-2 text-sm cursor-pointer hover:bg-gray-100" diff --git a/src/component/Editor.tsx b/src/component/Editor.tsx index 0dd7384..58745ea 100644 --- a/src/component/Editor.tsx +++ b/src/component/Editor.tsx @@ -10,7 +10,11 @@ interface EditorProps { readonly?: boolean; } -export const Editor: React.FC<EditorProps> = ({ content, setContent, readonly }) => { +export const Editor: React.FC<EditorProps> = ({ + content, + setContent, + readonly, +}) => { const editor = useRef(null); const config = useMemo( @@ -51,7 +55,7 @@ export const Editor: React.FC<EditorProps> = ({ content, setContent, readonly }) ref={editor} value={content} config={readonly ? readonlyConfig : config} - onChange={(newContent) => setContent(newContent)} + onChange={newContent => setContent(newContent)} /> ); }; diff --git a/src/component/Footer.tsx b/src/component/Footer.tsx index 4b85319..6d37ef4 100644 --- a/src/component/Footer.tsx +++ b/src/component/Footer.tsx @@ -34,14 +34,14 @@ const LINKS: Link[] = [ export const Footer: React.FC = () => { return ( - <div className="flex flex-col py-20 items-center"> - <div className="flex gap-1 mb-7"> + <footer className="flex flex-col py-20 items-center justify-center w-full bg-white mt-auto"> + <div className="flex justify-center gap-1 mb-7"> <Image src={logo} alt={'logo'} width={36} /> <p className="text-lg text-slate-400">WINK</p> </div> - <ul className="flex list-none gap-5 mb-7"> - {LINKS.map((link) => ( + <ul className="flex justify-center list-none gap-5 mb-7"> + {LINKS.map(link => ( <Link key={link.id} href={link.href}> <Image className="h-14" src={link.icon} alt={link.id} /> </Link> @@ -49,9 +49,13 @@ export const Footer: React.FC = () => { </ul> <div className="flex flex-col gap-7"> - <h3 className="text-xl text-slate-400">서울 성북구 정릉로 77 미래관 605-1</h3> - <p className="text-xl text-gray-500">© WINK 2024 All rights reserved.</p> + <h3 className="flex justify-center text-md text-slate-400"> + 서울 성북구 정릉로 77 미래관 605-1 + </h3> + <p className="text-md text-gray-500"> + © WINK 2024 All rights reserved. + </p> </div> - </div> + </footer> ); }; diff --git a/src/component/FormContainer.tsx b/src/component/FormContainer.tsx index f0f54c1..ce690e5 100644 --- a/src/component/FormContainer.tsx +++ b/src/component/FormContainer.tsx @@ -24,7 +24,10 @@ export const FormContainer: React.FC<FormContainerProps> = ({ ); }; -export type Fields<T extends string> = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'id'> & { +export type Fields<T extends string> = Omit< + React.InputHTMLAttributes<HTMLInputElement>, + 'id' +> & { id: T; button?: React.ReactNode; }; diff --git a/src/component/Header.tsx b/src/component/Header.tsx index feda9e9..4a555fe 100644 --- a/src/component/Header.tsx +++ b/src/component/Header.tsx @@ -82,12 +82,21 @@ export const Header: React.FC = () => { <header className="fixed top-0 z-50 bg-white w-full h-14 flex items-center justify-center border-b"> <div className="w-page flex justify-between p-4 lg:p-6"> <Link href={'/'} replace> - <Image className="object-contain h-6 mt-1" src={logo} alt="logo" height={24} priority /> + <Image + className="object-contain h-6 mt-1" + src={logo} + alt="logo" + height={24} + priority + /> </Link> <nav className="flex justify-center items-center capitalize"> <ul className="flex justify-center items-center list-none gap-8"> - {ITEMS.filter((item) => !item.hide).map((item) => ( - <div key={item.title} className={item.mobileHide ? 'hidden sm:block' : ''}> + {ITEMS.filter(item => !item.hide).map(item => ( + <div + key={item.title} + className={item.mobileHide ? 'hidden sm:block' : ''} + > <li className="font-medium text-sm relative cursor-pointer"> <div className={`flex items-center gap-1 ${pathname.startsWith(item.href) ? 'text-wink-500' : ''}`} @@ -111,7 +120,7 @@ export const Header: React.FC = () => { transition={{ duration: 0.2 }} className="absolute -left-1/4 w-28 top-full transform bg-white font-normal shadow-md rounded-md py-2 mt-4.5" > - {item.dropdown.map((subItem) => ( + {item.dropdown.map(subItem => ( <li key={subItem.href} className={`px-4 py-2 hover:bg-gray-100 ${pathname.startsWith(subItem.href) ? 'text-wink-500' : ''}`} diff --git a/src/component/IconButton.tsx b/src/component/IconButton.tsx index 47bcde9..08d8cea 100644 --- a/src/component/IconButton.tsx +++ b/src/component/IconButton.tsx @@ -1,6 +1,7 @@ import React from 'react'; -interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { +interface IconButtonProps + extends React.ButtonHTMLAttributes<HTMLButtonElement> { icon: React.ReactNode; text?: string; className?: string; diff --git a/src/component/ProfileCard.tsx b/src/component/ProfileCard.tsx index 760a0b3..4808ceb 100644 --- a/src/component/ProfileCard.tsx +++ b/src/component/ProfileCard.tsx @@ -57,12 +57,14 @@ export const ProfileCard: React.FC<ProfileCardProps> = ({ /> <div className="flex flex-col"> <h2 className="text-lg font-bold mt-1.5">{name}</h2> - {description && <p className="w-44 text-gray-600 truncate">{description}</p>} + {description && ( + <p className="w-44 text-gray-600 truncate">{description}</p> + )} </div> </div> <div className="flex justify-around border-t border-wink-400 py-3 px-5"> - {URL.map((url) => ( + {URL.map(url => ( <Link key={url.name} href={url.url || ''} diff --git a/src/component/SearchBar.tsx b/src/component/SearchBar.tsx index c588c5c..a6f53db 100644 --- a/src/component/SearchBar.tsx +++ b/src/component/SearchBar.tsx @@ -7,7 +7,11 @@ interface SearchBarProps { onChange: (value: string) => void; } -export const SearchBar: React.FC<SearchBarProps> = ({ value, placeholder, onChange }) => { +export const SearchBar: React.FC<SearchBarProps> = ({ + value, + placeholder, + onChange, +}) => { const onProxyChange = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); diff --git a/src/component/StudyCard.tsx b/src/component/StudyCard.tsx index 58c2ba4..8316b39 100644 --- a/src/component/StudyCard.tsx +++ b/src/component/StudyCard.tsx @@ -10,7 +10,13 @@ interface StudyCardProps { author: string; } -export const StudyCard: React.FC<StudyCardProps> = ({ image, link, title, content, author }) => { +export const StudyCard: React.FC<StudyCardProps> = ({ + image, + link, + title, + content, + author, +}) => { return ( <a href={link} @@ -21,10 +27,16 @@ export const StudyCard: React.FC<StudyCardProps> = ({ image, link, title, conten {/* 스터디 제목 및 설명 */} <div className="flex flex-col gap-2.5 my-4"> <h2 className="font-bold text-xl max-w-screen-sm truncate">{title}</h2> - <p className="font-regular text-base text-slate-500 max-w-screen-sm truncate">{content}</p> + <p className="font-regular text-base text-slate-500 max-w-screen-sm truncate"> + {content} + </p> <div className="flex flex-row justify-between"> - <p className="font-regular text-base max-w-screen-sm truncate">{link}</p> - <p className="font-regular text-base text-slate-500 max-w-screen-sm truncate">{author}</p> + <p className="font-regular text-base max-w-screen-sm truncate"> + {link} + </p> + <p className="font-regular text-base text-slate-500 max-w-screen-sm truncate"> + {author} + </p> </div> </div> diff --git a/src/component/TablePaging.tsx b/src/component/TablePaging.tsx index 4cb5c0c..28862cb 100644 --- a/src/component/TablePaging.tsx +++ b/src/component/TablePaging.tsx @@ -6,7 +6,11 @@ interface TablePagingProps { maxPage: number; } -export const TablePaging: React.FC<TablePagingProps> = ({ page, setPage, maxPage }) => { +export const TablePaging: React.FC<TablePagingProps> = ({ + page, + setPage, + maxPage, +}) => { const getPaginationRange = (current: number, max: number) => { if (max <= 5) return Array.from({ length: max }, (_, i) => i + 1); if (current === 1 || current == 2) return [1, 2, 3, 4, 5]; @@ -20,25 +24,27 @@ export const TablePaging: React.FC<TablePagingProps> = ({ page, setPage, maxPage return ( <div className="mt-4 flex justify-center items-center space-x-2"> <button - onClick={() => setPage((prev) => Math.max(prev - 1, 1))} + onClick={() => setPage(prev => Math.max(prev - 1, 1))} disabled={page === 1} className="px-3 py-1 rounded-md transition duration-300 bg-white text-wink-500 hover:bg-wink-100 disabled:opacity-50" > < </button> - {paginationRange.map((number) => ( + {paginationRange.map(number => ( <button key={number} onClick={() => setPage(number)} className={`px-3 py-1 rounded-md transition duration-300 ${ - page === number ? 'bg-wink-500 text-white' : 'bg-white text-wink-500 hover:bg-wink-100' + page === number + ? 'bg-wink-500 text-white' + : 'bg-white text-wink-500 hover:bg-wink-100' }`} > {number} </button> ))} <button - onClick={() => setPage((prev) => Math.min(prev + 1, maxPage))} + onClick={() => setPage(prev => Math.min(prev + 1, maxPage))} disabled={page === maxPage} className="px-3 py-1 rounded-md transition duration-300 bg-white text-wink-500 hover:bg-wink-100 disabled:opacity-50" > diff --git a/src/component/TextField.tsx b/src/component/TextField.tsx index 9ed4c3f..f7a064a 100644 --- a/src/component/TextField.tsx +++ b/src/component/TextField.tsx @@ -18,7 +18,7 @@ export const TextField: React.FC<TextFieldProps> = ({ id, ...rest }) => { id={id} value={values[id]} onChange={onChange} - onKeyDown={(e) => { + onKeyDown={e => { if (e.key === 'Enter' && onEnter) { onEnter(); } diff --git a/src/hook/useForm.tsx b/src/hook/useForm.tsx index d2e5bbb..8ab9856 100644 --- a/src/hook/useForm.tsx +++ b/src/hook/useForm.tsx @@ -41,8 +41,8 @@ export const useForm = <K extends string, V>( await schema.validate(values, { abortEarly: false }); } catch (error) { if (error instanceof yup.ValidationError) { - error.inner.forEach((err) => { - setErrors((prev) => ({ + error.inner.forEach(err => { + setErrors(prev => ({ ...prev, [err.path as K]: err.message, })); @@ -60,10 +60,12 @@ export const useForm = <K extends string, V>( schema .validateAt(id as K, { [id]: value }) - .then(() => setErrors((prev) => ({ ...prev, [id as K]: '' }))) - .catch((error) => setErrors((prev) => ({ ...prev, [id as K]: error.message }))); + .then(() => setErrors(prev => ({ ...prev, [id as K]: '' }))) + .catch(error => + setErrors(prev => ({ ...prev, [id as K]: error.message })), + ); - setValues((prev) => ({ ...prev, [id as K]: value })); + setValues(prev => ({ ...prev, [id as K]: value })); }; return { diff --git a/src/store/useApplicationState.ts b/src/store/useApplicationState.ts index 957271f..1d5b4c7 100644 --- a/src/store/useApplicationState.ts +++ b/src/store/useApplicationState.ts @@ -7,9 +7,9 @@ interface ApplicationState { setRefreshing: (refreshing: boolean) => void; } -export const useApplicationState = create<ApplicationState>((set) => ({ +export const useApplicationState = create<ApplicationState>(set => ({ loaded: false, - setLoaded: (loaded) => set({ loaded }), + setLoaded: loaded => set({ loaded }), refreshing: false, - setRefreshing: (refreshing) => set({ refreshing }), + setRefreshing: refreshing => set({ refreshing }), })); diff --git a/src/store/useMemberStore.ts b/src/store/useMemberStore.ts index e34a1dc..eda58a4 100644 --- a/src/store/useMemberStore.ts +++ b/src/store/useMemberStore.ts @@ -7,7 +7,7 @@ interface MemberState { setMember: (member: MemberType | null) => void; } -export const useMemberStore = create<MemberState>((set) => ({ +export const useMemberStore = create<MemberState>(set => ({ member: null, setMember: (member: MemberType | null) => set(() => ({