diff --git a/public/WinterIntrenBanner.webp b/public/WinterIntrenBanner.webp deleted file mode 100644 index 01cfd6f..0000000 Binary files a/public/WinterIntrenBanner.webp and /dev/null differ diff --git a/src/apis/applications/index.ts b/src/apis/applications/index.ts index c0ffead..65c1083 100644 --- a/src/apis/applications/index.ts +++ b/src/apis/applications/index.ts @@ -36,7 +36,7 @@ export function useApplyToCompany(recruitmentId: string) { case 404: append({ title: "", - message: "모집의뢰서가 존재하지 않습니다.", + message: "모집 기간이 아니거나 모집의뢰서가 존재하지 않습니다.", type: "RED", }); break; @@ -85,28 +85,14 @@ export function useReapply(applicationId: string | null) { message: "승인요청 또는 반려상태가 아닙니다.", type: "RED", }); - case 401: - append({ - title: "", - message: "3학년이 아닌 학생은 지원할 수 없습니다.", - type: "RED", - }); break; case 404: append({ title: "", - message: "모집의뢰서가 존재하지 않습니다.", + message: "지원서가 존재하지 않습니다.", type: "RED", }); break; - case 409: - append({ - title: "", - message: - "이미 해당 모집의뢰에 지원했거나 승인된 지원요청이 존재합니다.", - type: "RED", - }); - default: break; } diff --git a/src/apis/auth/index.ts b/src/apis/auth/index.ts index f5a8c7a..1be8eff 100644 --- a/src/apis/auth/index.ts +++ b/src/apis/auth/index.ts @@ -6,8 +6,8 @@ import { AuthCode, IAuthorizationResponse, SendAuthCodeType } from "./type"; const router = "/auth"; export const useReissueToken = async (refresh_token: string) => { - const response = await axios.put( - `${process.env.NEXT_PUBLIC_BASE_URL}${router}/reissue?platform_type=WEB`, + const response = await axios.put( + `${process.env.NEXT_PUBLIC_BASE_URL}${router}/reissue?platform-type=WEB`, null, { headers: { diff --git a/src/apis/axios.ts b/src/apis/axios.ts index 5fcee55..6d34e56 100644 --- a/src/apis/axios.ts +++ b/src/apis/axios.ts @@ -45,9 +45,11 @@ instance.interceptors.response.use( const accessExpired = new Date(res.access_expires_at); const refreshExpired = new Date(res.refresh_expires_at); cookies.set("access_token", res.access_token, { + path: '/', expires: accessExpired, }); cookies.set("refresh_token", res.refresh_token, { + path: '/', expires: refreshExpired, }); if (config!.headers) { diff --git a/src/apis/bookmarks/type.ts b/src/apis/bookmarks/type.ts index 3841856..899891e 100644 --- a/src/apis/bookmarks/type.ts +++ b/src/apis/bookmarks/type.ts @@ -3,7 +3,8 @@ export interface BookmarkResponseType { } export interface BookmarkItemsType { - company_name: string; - recruitment_id: number; - created_at: string; -} + "company_logo_url": string; + "company_name": string; + "recruitment_id": number; + "created_at": string; +} \ No newline at end of file diff --git a/src/apis/companies/index.ts b/src/apis/companies/index.ts index 293c0d1..d5c1140 100644 --- a/src/apis/companies/index.ts +++ b/src/apis/companies/index.ts @@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/react-query"; import { useToastStore } from "@team-return/design-system"; import { instance } from "../axios"; import { GetNumberOfPagesType } from "../recruitments/type"; -import { CompaniesDetailsType, CompaniesListResponseType } from "./type"; +import { CompaniesDetailsType, CompaniesListResponseType, GetCompaniesForReviewingResponse } from "./type"; const router = "/companies"; @@ -56,3 +56,13 @@ export const useGetNumberOfCompaniesListPages = (queryString: string) => { ); return data; }; + +export const useGetCompaniesForReviewing = () => { + return useQuery( + ["getCompaniesForReviewing"], + async () => { + const {data} = await instance.get(`${router}/review`); + return data; + } + ) +} \ No newline at end of file diff --git a/src/apis/companies/type.ts b/src/apis/companies/type.ts index 0c1c16d..e704c65 100644 --- a/src/apis/companies/type.ts +++ b/src/apis/companies/type.ts @@ -32,10 +32,20 @@ export interface CompaniesDetailsTable { fax: string | null; email: string; representative_name: string; + representative_phone_no: string; founded_at: string; worker_number: number; take: number; attachments: any[]; service_name: string; business_area: string; -} \ No newline at end of file +} + +export interface CompaniesForReviewType { + id: number, + name: string, +} + +export interface GetCompaniesForReviewingResponse { + companies : CompaniesForReviewType[] +} diff --git a/src/apis/file/index.ts b/src/apis/file/index.ts index 276a63f..7599b1f 100644 --- a/src/apis/file/index.ts +++ b/src/apis/file/index.ts @@ -30,12 +30,23 @@ export const useCreatePresignedURL = () => { }); }, onError: (error: AxiosError) => { - if (error.response) - append({ - title: "", - message: "파일 업로드에 실패했습니다.", - type: "RED", - }); + switch (error.response?.status) { + case 400 : { + append({ + title: '', + message: '잘못된 파일 확장자입니다.', + type: 'RED', + }) + } + break; + default : { + append({ + title: "", + message: "파일 업로드에 실패했습니다.", + type: "RED", + }); + } + } }, } ); diff --git a/src/apis/recruitments/type.ts b/src/apis/recruitments/type.ts index 3d1c16c..2c8d8d9 100644 --- a/src/apis/recruitments/type.ts +++ b/src/apis/recruitments/type.ts @@ -1,3 +1,4 @@ +import { instance } from "../axios"; export interface RecruitmentsListResponseType { recruitments: RecruitmentsListType[]; } @@ -17,13 +18,15 @@ export interface RecruitmentsDetailType extends RecruitmentsDetailTable { company_id: number; company_profile_url: string; company_name: string; + bookmarked: boolean; + recruitment_id: number; + is_applicable: boolean; } export interface RecruitmentsDetailTable { areas: AreasType[]; required_grade: number | null; - start_time: string; - end_time: string; + working_hours: string; required_licenses: string[] | []; hiring_progress: HiringProgressType[]; train_pay: number; @@ -36,10 +39,15 @@ export interface RecruitmentsDetailTable { etc: string | null; } +interface CodeType { + id: number; + name: string; +} + export interface AreasType { id: number; - job: string[]; - tech: string[]; + job: CodeType[]; + tech: CodeType[]; hiring: number; major_task: string; preferential_treatment: string | null; diff --git a/src/apis/reviews/index.ts b/src/apis/reviews/index.ts index 6635fdd..60ea24d 100644 --- a/src/apis/reviews/index.ts +++ b/src/apis/reviews/index.ts @@ -1,8 +1,11 @@ -import { useQuery } from "@tanstack/react-query"; +import { MutationOptions, useMutation, UseMutationOptions, useQuery } from "@tanstack/react-query"; +import { useToastStore } from "@team-return/design-system"; +import { AxiosError, AxiosResponse } from "axios"; import { instance } from "../axios"; import { getReviewDetailResponseProps, - getReviewListResponseProps + getReviewListResponseProps, + createReviewRequestType, } from "./type"; const router = "/reviews"; @@ -24,3 +27,47 @@ export const useGetReviewDetails = (reviewId: string) => { return data; }); }; + +export const useCreateReviews = (options: Omit, unknown, createReviewRequestType, unknown>, "mutationFn">) => { + const { append } = useToastStore(); + return useMutation( + async (body: createReviewRequestType) => + await instance.post(`${router}`, body), + { + ...options, + onError: (err: AxiosError) => { + const { response } = err; + switch (response?.status) { + case 400: { + append({ + title: "", + message: "입력값은 비어있으면 안됩니다.", + type: "RED", + }); + break; + } + case 404: { + switch ((response as AxiosResponse<{ message: string }>).data.message) { + case "Code Not Found": { + append({ + title: "", + message: "질문 분야가 누락되었습니다.", + type: "RED", + }); + break; + } + case 'ApplicationEntity Not Found': { + append({ + title: '', + message: '해당 기업에는 후기를 작성할 수 없습니다.', + type: 'RED', + }) + } + } + + } + } + }, + } + ); +}; diff --git a/src/apis/reviews/type.ts b/src/apis/reviews/type.ts index dcfe322..8e80a40 100644 --- a/src/apis/reviews/type.ts +++ b/src/apis/reviews/type.ts @@ -18,3 +18,14 @@ export interface getReviewDetailProps { answer: string; area: string; } + +export interface qnaElementsType { + question: string; + answer: string; + code_id: number; +} + +export interface createReviewRequestType { + company_id: number; + qna_elements: qnaElementsType[] +} \ No newline at end of file diff --git a/src/app/companies/reviews/create/page.tsx b/src/app/companies/reviews/create/page.tsx new file mode 100644 index 0000000..fc36510 --- /dev/null +++ b/src/app/companies/reviews/create/page.tsx @@ -0,0 +1,90 @@ +"use client"; + +import { useState } from "react"; +import ReviewForm from "@/components/company/ReviewForm"; +import FillBtn from "@/components/common/Button/FillBtn"; +import { useRouter, useSearchParams } from "next/navigation"; +import { useCreateReviews } from "@/apis/reviews"; +import { qnaElementsType } from "@/apis/reviews/type"; + +export default function CreateReviews() { + const router = useRouter(); + const params = useSearchParams(); + const companyId = Number(params.get('id')) + const [qnaElements, setQnaElements] = useState([ + { question: "", answer: "", code_id: 0 }, + ]); + const mutateOption = { + onSuccess: () => { + router.push(`/companies/reviews/?id=${companyId}`) + } + } + const { mutate: createReviews } = useCreateReviews(mutateOption); + + const handleClickCreateRevies = () => { + createReviews({ + company_id:companyId, + qna_elements: qnaElements + }) + } + + const handleChange = ( + index: number, + name: keyof qnaElementsType, + value: string | number + ) => { + setQnaElements(prev => { + const newReviews = [...prev]; + if (typeof value === "number") { + newReviews[index].code_id = value; + } else if (name !== "code_id") { + newReviews[index][name] = value; + } + return newReviews; + }); + }; + + const removeReviewList = (index: number) => { + setQnaElements(prev=>{ + let newReviews = [...prev]; + newReviews = newReviews.filter((_,idx)=>idx !== index); + return newReviews; + }) + } + + return ( +
+

+ 후기작성 +

+ {qnaElements + .map((qnaElement, idx) => ( + + ))} +
+ { + setQnaElements(prev => ([ + ...prev, + { question: "", answer: "", code_id: 0 } + ])); + }} + > + 면접질문 추가 + +
+ { + router.back(); + }} + > + 이전으로 + + 완료 +
+
+
+ ); +} diff --git a/src/app/companies/reviews/page.tsx b/src/app/companies/reviews/page.tsx index fe30be7..fec1e50 100644 --- a/src/app/companies/reviews/page.tsx +++ b/src/app/companies/reviews/page.tsx @@ -4,7 +4,7 @@ export default function Reviews() { return (

- 면접 후기 + 면접후기


diff --git a/src/app/employmentStatus/page.tsx b/src/app/employmentStatus/page.tsx new file mode 100644 index 0000000..44fefb6 --- /dev/null +++ b/src/app/employmentStatus/page.tsx @@ -0,0 +1,12 @@ +export default function EmploymentStatus() { + return ( +
+
+
+

2023학년도 DSM의 취업률을 확인해 보세요

+

현재 100%의 학생들이 취업에 성공했어요!

+
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index dccc27e..a4780a8 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -53,6 +53,10 @@ input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; } +textarea { + resize: none; +} + table { width: 100%; border: none; @@ -91,5 +95,18 @@ table { background-color: white; padding-left: 40px; padding-right: 40px; + position: relative; + } + & .file { + display: flex; + gap: 10px; + flex-wrap: wrap; + } + & .easteregg { + position: absolute; + height: 20px; + width: 100%; + left: 0px; + backdrop-filter: blur(20px); } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index dba1239..8f76b8a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,11 @@ +"use client"; + import Header from "@/components/common/Header"; import Provider from "@/components/Provider"; import SEOConfig from "@/components/SEO"; import localFont from "@next/font/local"; +import { usePathname } from "next/navigation"; +import { useEffect } from "react"; import "./globals.css"; const pretendard = localFont({ @@ -27,6 +31,20 @@ export default function RootLayout({ }: { children: React.ReactNode; }) { + const pathname = usePathname(); + + useEffect(() => { + if ( + pathname.toString().indexOf("/apply") !== -1 || + pathname.toString().indexOf("/account") !== -1 || + pathname.toString().indexOf("/employmentStatus") !== -1 + ) { + document.querySelector("body")!.style.backgroundColor = "#fafafa"; + } else { + document.querySelector("body")!.style.backgroundColor = "#ffffff"; + } + }, [pathname]); + return ( @@ -37,7 +55,7 @@ export default function RootLayout({ } > -
+ {pathname.toString().indexOf("/account") === -1 &&
} {children} diff --git a/src/app/mypage/page.tsx b/src/app/mypage/page.tsx index 5e633aa..34b309e 100644 --- a/src/app/mypage/page.tsx +++ b/src/app/mypage/page.tsx @@ -1,10 +1,12 @@ import AppliedCompaniesList from "@/components/mypage/AppliedCompaniesList"; import DetailProfile from "@/components/mypage/DetailProfile"; +import CompaniesForReviewing from "@/components/mypage/CompaniesForReviewing"; export default function MyPage() { return (
+
); diff --git a/src/app/recruitments/apply/page.tsx b/src/app/recruitments/apply/page.tsx index 60c998d..e7fbd8b 100644 --- a/src/app/recruitments/apply/page.tsx +++ b/src/app/recruitments/apply/page.tsx @@ -133,6 +133,7 @@ export default function Apply() {

제출서류 : {recruitmentsDetial?.submit_document}

+ -
+
+
+

+ ※ 파일 첨부 시 파일 확장자를 확인해 주시기 바랍니다. +

+

+ pdf, ppt, pptx, hwp, zip, txt, mp4, png, jpg, svg +

+
{ setIsClickedApplyBtn(true); @@ -204,6 +213,7 @@ export default function Apply() {
+ { onUploadFile(fileList); diff --git a/src/app/recruitments/detail/page.tsx b/src/app/recruitments/detail/page.tsx index 89d4233..aea4026 100644 --- a/src/app/recruitments/detail/page.tsx +++ b/src/app/recruitments/detail/page.tsx @@ -9,10 +9,19 @@ import { useRouter, useSearchParams } from "next/navigation"; export default function RecruitmentsDetailPage() { const param = useSearchParams(); const navigator = useRouter(); - const { data: RecruitmentsDetial } = useGetRecruitmentsDetail(param.get("id")!); + const { data: RecruitmentsDetial } = useGetRecruitmentsDetail( + param.get("id")! + ); if (RecruitmentsDetial) { - const { company_id, company_name, company_profile_url, ...rest } = - RecruitmentsDetial; + const { + company_id, + company_name, + company_profile_url, + bookmarked, + recruitment_id, + is_applicable, + ...rest + } = RecruitmentsDetial; return (
@@ -20,14 +29,18 @@ export default function RecruitmentsDetailPage() { company_name={company_name} company_profile_url={company_profile_url} company_id={company_id} + bookmarked={bookmarked} + recruitmentId={recruitment_id} > - { - navigator.push(`/recruitments/apply/?id=${param.get("id")}`); - }} - > - 지원하기 - + {is_applicable && ( + { + navigator.push(`/recruitments/apply/?id=${param.get("id")}`); + }} + > + 지원하기 + + )}
diff --git a/src/components/BookmarkCard.tsx b/src/components/BookmarkCard.tsx index db262a0..8a3f06a 100644 --- a/src/components/BookmarkCard.tsx +++ b/src/components/BookmarkCard.tsx @@ -1,10 +1,20 @@ -import { useGetBookmarks } from "@/apis/bookmarks"; +import { useGetBookmarks, useSetBookmarks } from "@/apis/bookmarks"; import { Icon } from "@team-return/design-system"; import Link from "next/link"; import HoverPrefetchLink from "./common/HoverPrefetchLink"; +import Image from "next/image"; +import { useEffect, useState } from "react"; +import { BookmarkItemsType } from "@/apis/bookmarks/type"; export default function BookmarkCard() { const { data: bookmarks } = useGetBookmarks(); + const { mutate: SetBookmarksMutate } = useSetBookmarks(); + + const [localBookmarks, setLocalBookmarks] = useState(bookmarks?.bookmarks || []) + + useEffect(()=>{ + if(bookmarks) setLocalBookmarks(bookmarks.bookmarks); + },[bookmarks?.bookmarks]) return (
@@ -17,17 +27,26 @@ export default function BookmarkCard() {
)} - {bookmarks?.bookmarks.map(({ company_name, recruitment_id }) => ( + {localBookmarks.map(({ company_name, recruitment_id, company_logo_url }) => (
+
+ 기업로고 +

{company_name}

-
diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx index 6217cce..dc2154b 100644 --- a/src/components/Carousel.tsx +++ b/src/components/Carousel.tsx @@ -6,13 +6,8 @@ import CircleBtn from "./CircleBtn"; //======================================================================================================= import PopularCompanyBanner from "@public/PopularCompanyBanner.webp"; -import WinterIntrenBanner from "@public/WinterIntrenBanner.webp"; import { useRouter } from "next/navigation"; const BannerList = [ - { - img: WinterIntrenBanner, - url: "/recruitments/?page=1&winter_intern=true", - }, { img: PopularCompanyBanner, url: "/companies/detail/?id=9", diff --git a/src/components/account/login/loginStateManagement.tsx b/src/components/account/login/loginStateManagement.tsx index 2b4ec4e..87380af 100644 --- a/src/components/account/login/loginStateManagement.tsx +++ b/src/components/account/login/loginStateManagement.tsx @@ -1,20 +1,21 @@ "use client"; -import React from "react"; +import { useLogin } from "@/apis/user"; import { RequestBody } from "@/apis/user/type"; import LoginInputs from "@/components/account/login/loginInputsComponents"; import SubmitBtn from "@/components/account/login/submitBtn"; -import { useCallback, useState } from "react"; -import { useLogin } from "@/apis/user"; import useForm from "@/hook/useForm"; +import { CheckPasswordFormat } from "@/util/passwordFormat"; +import { useCallback, useState } from "react"; export default function LoginStateMenagement() { const [isChecked, setIsChecked] = useState(false); + const passwordFormat = CheckPasswordFormat(); const { state: inputStates, onChange: handleChange } = useForm({ account_id: "", password: "", }); - const { mutate: loginClick } = useLogin(inputStates, isChecked); + const { mutate: login } = useLogin(inputStates, isChecked); const allIsInputState = useCallback( (): boolean => inputStates.account_id !== "" && inputStates.password !== "", [inputStates] @@ -25,13 +26,17 @@ export default function LoginStateMenagement() { { + passwordFormat(inputStates.password, login); + }} /> { + passwordFormat(inputStates.password, login); + }} />
); diff --git a/src/components/account/singup/signupPages/FirstSignupPage.tsx b/src/components/account/singup/signupPages/FirstSignupPage.tsx index 447a9de..cf5b6af 100644 --- a/src/components/account/singup/signupPages/FirstSignupPage.tsx +++ b/src/components/account/singup/signupPages/FirstSignupPage.tsx @@ -4,6 +4,7 @@ import { useCheckAuthCode, useSendAuthCode } from "@/apis/auth"; import LargeBtn from "@/components/common/Button/LargeBtn"; import TextFiled from "@/components/common/TextFiled"; import useSignUpContext from "@/hook/useSignupContext"; +import { CheckPasswordFormat } from "@/util/passwordFormat"; import { theme, useToastStore } from "@team-return/design-system"; import { useRouter } from "next/navigation"; import React from "react"; @@ -11,6 +12,7 @@ import React from "react"; function FirstSignupPage() { const { signupState, handleChange } = useSignUpContext(); const { email, auth_code, password, passwordCheck } = signupState; + const passwordFormat = CheckPasswordFormat(); const { append } = useToastStore(); const navigator = useRouter(); const { mutate: SandAuthCodeAPI } = useSendAuthCode(); @@ -26,6 +28,18 @@ function FirstSignupPage() { } ); + const nextBtnClick = () => { + if (password === passwordCheck) { + CheckAuthCodeAPI(); + } else { + append({ + title: "", + message: "비밀번호가 일치하지 않습니다.", + type: "RED", + }); + } + }; + return (
@@ -71,6 +85,8 @@ function FirstSignupPage() { height={48} label="비밀번호" placeholder="비밀번호를 입력해주세요" + type="password" + customType="Password" />
{ - if (password === passwordCheck) { - CheckAuthCodeAPI(); - } else { - append({ - title: "", - message: "비밀번호가 일치하지 않습니다.", - type: "RED", - }); - } + passwordFormat(password, nextBtnClick); }} />
diff --git a/src/components/common/Button/FillBtn.tsx b/src/components/common/Button/FillBtn.tsx new file mode 100644 index 0000000..76f7fb6 --- /dev/null +++ b/src/components/common/Button/FillBtn.tsx @@ -0,0 +1,20 @@ +import React from "react"; + +interface Propstype extends React.ButtonHTMLAttributes { + backgroundColor?: string +} + +export default function FillBtn({ children, backgroundColor, style, ...rest }: Propstype) { + return ( + + ); +} diff --git a/src/components/common/Button/SendBtn.tsx b/src/components/common/Button/SendBtn.tsx deleted file mode 100644 index 5773760..0000000 --- a/src/components/common/Button/SendBtn.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; - -function SendBtn() { - return ( - <> - <> - - ); -} - -export default React.memo(SendBtn); diff --git a/src/components/common/DropDown.tsx b/src/components/common/DropDown.tsx index 54ffa72..c80088b 100644 --- a/src/components/common/DropDown.tsx +++ b/src/components/common/DropDown.tsx @@ -19,7 +19,7 @@ interface PropsType { function DropDown({ title, items, onClickItem, selected }: PropsType) { const { toggleDropdown, DropDownComponent, closeDropDown } = useDropDown(); - const selectedItemLabel = items.find((item) => item.code === selected); + const selectedItemLabel = items.find((item) => item.code === selected.toString()); return (
{ - if ( - pathname.toString().indexOf("/apply") !== -1 || - pathname.toString().indexOf("/account") !== -1 - ) { - document.querySelector("body")!.style.backgroundColor = "#fafafa"; - } else { - document.querySelector("body")!.style.backgroundColor = "#ffffff"; - } - }, [pathname]); - - if (pathname.toString().indexOf("/account") !== -1) { - return null; - } - const { data: profile } = useMyProfile(); return ( diff --git a/src/components/common/TextFiled.tsx b/src/components/common/TextFiled.tsx index 40f4a8a..2bcb7bf 100644 --- a/src/components/common/TextFiled.tsx +++ b/src/components/common/TextFiled.tsx @@ -43,7 +43,7 @@ function TextFiled({

{label}

)}
{isLoading && } - {companyList?.companies - .filter((_, idx) => idx < maxLength) - .map(({ logo_url, name, take, has_recruitment, id }, index) => ( - -
-
- {name} + {companyList?.companies.length === 0 ? ( +

⚠ 기업이 없습니다.

+ ) : ( + companyList?.companies + .filter((_, idx) => idx < maxLength) + .map(({ logo_url, name, take, has_recruitment, id }, index) => ( + +
+
+ {name} +
+
+

+ {name} +

+

+ 연매출 {take}억원 +

+ {has_recruitment && ( +
+ +
+ )} +
-
-

- {name} -

-

- 연매출 {take}억원 -

- {has_recruitment && ( -
- -
- )} -
-
- - ))} + + )) + )}
); } diff --git a/src/components/company/CompanyTable.tsx b/src/components/company/CompanyTable.tsx index e1a352f..0c5a0ed 100644 --- a/src/components/company/CompanyTable.tsx +++ b/src/components/company/CompanyTable.tsx @@ -1,10 +1,12 @@ import { CompaniesDetailsTable } from "@/apis/companies/type"; import { pon_number_regex } from "@/util/regex"; import React from "react"; +import FilePreview from "../recruitments/apply/FilePreview"; function CompanyTable({ ...rest }: CompaniesDetailsTable) { const { representative_name, + representative_phone_no, worker_number, company_introduce, main_zip_code, @@ -34,6 +36,12 @@ function CompanyTable({ ...rest }: CompaniesDetailsTable) { 대표 {representative_name} + + 대표 번호 + + {pon_number_regex(representative_phone_no) || "-"} + + 직원 수 {worker_number} 명 @@ -102,7 +110,20 @@ function CompanyTable({ ...rest }: CompaniesDetailsTable) { 첨부파일 - 첨부파일 + + {attachments.length === 0 + ? "-" + : attachments.map(fileUrl => ( + { + window.open( + `${process.env.NEXT_PUBLIC_IMAGE_URL}/${fileUrl}` + ); + }} + /> + ))} + diff --git a/src/components/company/CompanyTitle.tsx b/src/components/company/CompanyTitle.tsx index b817fac..8fe7b98 100644 --- a/src/components/company/CompanyTitle.tsx +++ b/src/components/company/CompanyTitle.tsx @@ -4,7 +4,10 @@ import Image from "next/image"; import { useRouter } from "next/navigation"; import { getCompanyKebabItems } from "@/util/object/kebabMenuItems"; import { KebabItemType } from "@/util/type/kebabMenu"; +import { useSetBookmarks } from "@/apis/bookmarks"; import KebabMenu from "../common/Dropdown/KebabMenu"; +import { Icon } from "@team-return/design-system"; +import { useState } from "react"; interface PropsType { business_number?: string; @@ -14,6 +17,8 @@ interface PropsType { onClickInterview?: () => void; children?: React.ReactNode; company_id?: number; + bookmarked?: boolean; + recruitmentId?: number; } export default function CompanyTitle({ @@ -24,11 +29,17 @@ export default function CompanyTitle({ onClickInterview, children, company_id, + bookmarked, + recruitmentId }: PropsType) { const kebabItems: KebabItemType[] = getCompanyKebabItems( onClickRecruitments, onClickInterview ); + const { mutate: SetBookmarksMutate } = useSetBookmarks(); + const [localBookmarked, setLocalBookmarked] = useState( + bookmarked || false + ); const navigator = useRouter(); @@ -45,7 +56,26 @@ export default function CompanyTitle({ />
-

{company_name}

+
+

{company_name}

+ { + recruitmentId && ( + + ) + } + +
{business_number && (

사업자 번호 : {business_number} diff --git a/src/components/company/ReviewForm.tsx b/src/components/company/ReviewForm.tsx new file mode 100644 index 0000000..9aa5b1c --- /dev/null +++ b/src/components/company/ReviewForm.tsx @@ -0,0 +1,101 @@ +import React from "react"; +import { useGetCode } from "@/apis/code"; +import DropDown from "@/components/common/DropDown"; +import TextFiled from "@/components/common/TextFiled"; +import useForm from "@/hook/useForm"; +import { useRef, useState } from "react"; +import { theme } from "@team-return/design-system"; +import { qnaElementsType } from "@/apis/reviews/type"; + +interface PropsType { + question: string; + answer: string; + code_id: number; + index: number; + onChange: (idx: number, name: keyof qnaElementsType, value: string) => void; + setState: React.Dispatch>; + removeReviews: (index:number) => void; +} + +export default function ReviewForm({ + question, + answer, + code_id, + index, + onChange, + setState: setQnaElements, + removeReviews +}: PropsType) { + const textarea = useRef(null); + + const { data: codes } = useGetCode("JOB"); + + const [isFocus, setIsFocus] = useState(false); + + const jobCodeDropdownItems = codes?.codes.map(item => ({ + code: item.code.toString(), + label: item.keyword, + })); + + const handleResizeHeight = () => { + if (textarea?.current) { + textarea.current.style.height = "auto"; + textarea.current.style.height = textarea.current.scrollHeight + "px"; + } + }; + return ( +

+
+ { + onChange(index, "question", e.target.value); + }} + className="flex-1" + /> +
+

+ 질문 분야 +

+ { + setQnaElements(prev => { + const updatedElements = [...prev]; + updatedElements[index].code_id = Number(itemCode); + return updatedElements; + }); + }} + selected={code_id} + /> +
+
+

답변

+