├── .babelrc ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.tsx ├── assets │ ├── fonts │ │ ├── Pretendard-Black.woff2 │ │ ├── Pretendard-Bold.woff2 │ │ ├── Pretendard-ExtraBold.woff2 │ │ ├── Pretendard-ExtraLight.woff2 │ │ ├── Pretendard-Light.woff2 │ │ ├── Pretendard-Medium.woff2 │ │ ├── Pretendard-Regular.woff2 │ │ ├── Pretendard-SemiBold.woff2 │ │ └── Pretendard-Thin.woff2 │ ├── icons │ │ ├── Company │ │ │ ├── bag.svg │ │ │ ├── bolt.svg │ │ │ ├── tool.svg │ │ │ └── write.png │ │ ├── Home │ │ │ ├── developer.svg │ │ │ ├── emptyFace.svg │ │ │ ├── graph.svg │ │ │ ├── smileFace.svg │ │ │ ├── web.svg │ │ │ └── wonderFace.svg │ │ ├── Logo │ │ │ ├── bee.svg │ │ │ └── logo.svg │ │ ├── Rank │ │ │ ├── balance.svg │ │ │ ├── career.svg │ │ │ ├── company.svg │ │ │ ├── leftArrow.png │ │ │ ├── money.svg │ │ │ ├── rightArrow.png │ │ │ └── total.svg │ │ ├── Search │ │ │ ├── readingGlasses.svg │ │ │ ├── search1.svg │ │ │ ├── search2.svg │ │ │ └── search3.svg │ │ └── Story │ │ │ ├── blueHeart.svg │ │ │ ├── box.svg │ │ │ ├── check.svg │ │ │ ├── cloud.svg │ │ │ ├── idCard.svg │ │ │ ├── paper.svg │ │ │ ├── printer.svg │ │ │ └── redHeart.png │ └── images │ │ ├── Auth │ │ ├── close.svg │ │ ├── github.svg │ │ └── wave.svg │ │ ├── Register │ │ ├── bigBannerIcon1.svg │ │ ├── bigBannerIcon2.svg │ │ ├── middleBannerIcon.svg │ │ ├── photo.png │ │ ├── smallBannerIcon1.svg │ │ ├── smallBannerIcon2.svg │ │ └── upload.png │ │ ├── Search │ │ ├── semicircle1.svg │ │ ├── semicircle2.svg │ │ └── wave.svg │ │ ├── Story │ │ ├── close.svg │ │ └── wave.svg │ │ └── User │ │ ├── cancel.svg │ │ ├── del.svg │ │ └── edit.svg ├── components │ ├── Alumni │ │ └── Certify │ │ │ ├── index.tsx │ │ │ └── style.ts │ ├── Common │ │ ├── Auth │ │ │ └── SignIn │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ ├── ErrorBoundary │ │ │ └── index.tsx │ │ ├── Footer │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── Header │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── Modal │ │ │ ├── CompanyAddress │ │ │ │ └── index.tsx │ │ │ ├── MyInfo │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── Search │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ ├── NotFound │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── Provider │ │ │ └── index.tsx │ │ ├── Skeleton │ │ │ ├── Common │ │ │ │ └── style.ts │ │ │ ├── CompanyDetail │ │ │ │ ├── Review │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── Home │ │ │ │ ├── Main │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── Recommand │ │ │ │ │ └── index.tsx │ │ │ │ └── UserInfo │ │ │ │ │ └── index.tsx │ │ │ ├── User │ │ │ │ ├── Nav │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── StoryStatus │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ └── ViewAll │ │ │ │ ├── All │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ │ └── Rank │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ ├── Star │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ └── StorySetUp │ │ │ ├── index.tsx │ │ │ └── style.ts │ ├── Company │ │ └── CompanyDetail │ │ │ ├── CompanyDetailItem │ │ │ ├── CompanyDetailInfo │ │ │ │ ├── Content │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── Story │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── UserProfile │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── CompanyStarGrades │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── index.tsx │ │ │ ├── index.tsx │ │ │ └── style.ts │ ├── Home │ │ ├── Main │ │ │ ├── Rank │ │ │ │ ├── RankItem │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── Search │ │ │ │ ├── SearchItem │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ └── index.tsx │ │ │ └── style.ts │ │ ├── Nav │ │ │ ├── ExternalSite │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── UserInfo │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── index.tsx │ │ ├── Recommand │ │ │ ├── RecommandItem │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── index.tsx │ │ └── style.ts │ ├── Story │ │ ├── Company │ │ │ ├── Modify │ │ │ │ ├── ModifyItem │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── Register │ │ │ │ ├── RegisterItem │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── Search │ │ │ │ ├── SearchCompanyModal │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── style.ts │ │ ├── StoryRegister │ │ │ ├── RegisterItem │ │ │ │ ├── PositionList │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── StarGrade │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── stye.ts │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── index.tsx │ │ └── style.ts │ ├── User │ │ ├── Nav │ │ │ ├── NavFooter │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── Profile │ │ │ ├── MyInfo │ │ │ │ ├── NickName │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── index.tsx │ │ ├── Story │ │ │ ├── StoryItem │ │ │ │ ├── CompanyContent │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── CompanyInfo │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.ts │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── index.tsx │ │ ├── StoryStatus │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ ├── index.tsx │ │ └── style.ts │ └── ViewAll │ │ ├── All │ │ ├── AllList │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ └── index.tsx │ │ ├── Rank │ │ ├── RankList │ │ │ ├── index.tsx │ │ │ └── style.ts │ │ └── index.tsx │ │ └── style.ts ├── constants │ ├── Auth │ │ └── auth.constant.ts │ ├── Company │ │ └── company.constant.ts │ ├── ExternalSite │ │ └── externalSite.constant.ts │ ├── Footer │ │ └── footer.constant.ts │ ├── Header │ │ └── header.constant.ts │ ├── Position │ │ └── position.constant.ts │ ├── Router │ │ └── router.constant.ts │ ├── Story │ │ └── story.constant.ts │ └── User │ │ └── user.constants.ts ├── hooks │ ├── Alumni │ │ ├── useAlumniCheck.ts │ │ └── useCertify.ts │ ├── Auth │ │ ├── useLogin.ts │ │ ├── useLogout.ts │ │ ├── useSocialLogin.ts │ │ └── useTokenCheck.ts │ ├── Company │ │ ├── useCompanyModify.ts │ │ ├── useCompanyRegister.ts │ │ ├── useDeleteCompany.ts │ │ └── useSearchCompany.ts │ ├── Header │ │ └── useHideHeader.ts │ ├── Invalidates │ │ └── useQueryInvalidates.ts │ ├── Logging │ │ └── useLogging.ts │ ├── NickName │ │ └── useSetUpNickName.ts │ └── Story │ │ ├── index.tsx │ │ ├── useSetUpStory.ts │ │ ├── useStoryModify.ts │ │ └── useStoryRegister.ts ├── index.tsx ├── libs │ ├── Axios │ │ ├── RollingAxios.ts │ │ ├── requestHandler.ts │ │ └── responseHandler.ts │ ├── Cookie │ │ └── cookie.ts │ └── Token │ │ └── Token.ts ├── pages │ ├── AllPage │ │ └── index.tsx │ ├── AlumniPage │ │ └── CertifyPage │ │ │ └── index.tsx │ ├── AuthPage │ │ └── AuthLoadingPage │ │ │ └── index.tsx │ ├── CompanyPage │ │ └── CompanyDetailPage │ │ │ └── index.tsx │ ├── HomePage │ │ └── index.tsx │ ├── RankPage │ │ └── index.tsx │ ├── StoryPage │ │ ├── ModifyPage │ │ │ └── Company │ │ │ │ └── index.tsx │ │ └── index.tsx │ └── UserPage │ │ └── index.tsx ├── react-app-env.d.ts ├── reportWebVitals.ts ├── router │ └── index.tsx ├── services │ ├── Auth │ │ └── api.ts │ ├── Company │ │ ├── api.ts │ │ ├── mutation.ts │ │ └── queries.ts │ ├── Employment │ │ ├── api.ts │ │ └── queries.ts │ ├── File │ │ ├── api.ts │ │ └── mutations.ts │ ├── Graduate │ │ ├── api.ts │ │ └── mutations.ts │ ├── Logging │ │ ├── api.ts │ │ └── mutations.ts │ ├── Member │ │ ├── api.ts │ │ ├── mutations.ts │ │ └── queries.ts │ ├── News │ │ ├── api.ts │ │ └── queries.ts │ ├── Story │ │ ├── api.ts │ │ ├── mutations.ts │ │ └── queries.ts │ └── queryKey.ts ├── setupTests.ts ├── stores │ ├── auth │ │ └── auth.store.ts │ ├── common │ │ └── common.store.ts │ ├── company │ │ └── company.store.ts │ ├── member │ │ └── member.store.ts │ └── story │ │ └── story.store.ts ├── styles │ ├── GlobalStyles.ts │ ├── common.style.ts │ ├── flex.ts │ └── font.css ├── types │ ├── Auth │ │ └── auth.type.ts │ ├── Company │ │ └── company.type.ts │ ├── Employment │ │ └── employment.type.ts │ ├── Member │ │ └── member.type.ts │ ├── News │ │ └── news.type.ts │ ├── StarGrade │ │ └── starGrade.type.ts │ ├── Story │ │ └── story.type.ts │ ├── common │ │ └── commont.type.ts │ └── logging │ │ └── logging.type.ts └── utils │ ├── Auth │ └── tokenDecode.ts │ ├── Error │ ├── Auth │ │ └── authErrorHandler.ts │ ├── Company │ │ └── companyErrorHanlder.ts │ ├── Employment │ │ └── employmentErrorHanlder.ts │ ├── File │ │ └── fileErrorHanlder.ts │ ├── Member │ │ └── memberErrorHandler.ts │ └── Story │ │ └── storyErrorHanlder.ts │ ├── Logging │ └── changeUrlToLoggingText.ts │ ├── Modal │ └── turnOnOffModal.ts │ ├── Position │ └── searchPosition.ts │ ├── Rank │ ├── getCompanyRankIntroduce.ts │ ├── getRankIcon.ts │ └── getSlideRankBoxWidth.ts │ ├── Rgb │ └── getRgb.ts │ ├── StarRating │ ├── convertRankingObject.ts │ └── tieStarGradeToObject.ts │ ├── Story │ └── storyItemsObject.ts │ └── github │ └── convertToGithubLink.ts ├── tsconfig.json ├── webpack.common.js ├── webpack.dev.js └── webpack.prod.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { "targets": { "browsers": ["last 2 versions", ">= 5% in KR"] } } 6 | ], 7 | "@babel/react" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | config.json 11 | 12 | # production 13 | /build 14 | dist 15 | # misc 16 | .DS_Store 17 | .env 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 이미지 없음 3 |

학생들을 위한 기업정보 공유 서비스, Rolling

4 |
5 | 6 |
7 |
8 | 9 | # [Rolling](https://rolling.stubee.kr)에 대해 정확하게 알려줄게요! 10 | 11 | 학생 구직자들이 취업을 하는데에 있어서 가장 힘든점은 기업정보인데요. 어떤 정보를 모아야할지 몰라서, 물어볼 선배가 없어서 등등의 이유와 입학, 학생관리는 동아리 내에서 운영 중이지만 가장 중요한 취업은 외부 서비스에 의존하고 있었어요. 또한 학생들을 위한 취업플랫폼 서비스는 존재하고 있지 않았기에 이 문제를 해소하고자 롤링을 만들게 되었어요. 12 | 13 | > 현재는 대소고 학생들(재학생, 졸업생) 한정으로만 사용할 수 있어요. 14 | 15 |
16 |
17 | 18 | # 롤링에서 이러한 기능들이 있어요! 19 | 20 | - Github 소셜 로그인을 지원하고 있어요. 21 | - 사감 선생님 이름으로 DGSW 동문인증하여 사용이 가능해요. 22 | - 학생들이 궁금해하는 정보(연봉, 워라벨, 조직문화, 커리어 향상, 총합)를 랭킹으로 보여줘요. 23 | - 졸업생들이 재직 중이거나 퇴직한 회사를 직접 등록하고 리뷰를 달 수 있어요. 24 | - 등록되어있는 회사들을 전체 조회 가능하고 단일 조회 또한 가능해요. 25 | 26 |
27 |
28 | 29 | 30 | # 기술 스택 31 | `React.js`, `TypeScript`, `React-Query`, `webpack`, 32 | `styled-components`, `Recoil`, `Axios` -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 롤링 Rolling 13 | 14 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { QueryClient, QueryClientProvider } from "react-query"; 2 | import { BrowserRouter } from "react-router-dom"; 3 | import { RecoilRoot } from "recoil"; 4 | import Provider from "./components/Common/Provider"; 5 | import Router from "./router"; 6 | import { RollingToastProvider } from "@stubee2/stubee2-rolling-toastify"; 7 | 8 | function App() { 9 | const queryClient: QueryClient = new QueryClient({ 10 | defaultOptions: { 11 | queries: { 12 | useErrorBoundary: true, 13 | }, 14 | }, 15 | }); 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | 31 | export default App; 32 | -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-Black.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-Bold.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-ExtraBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-ExtraBold.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-ExtraLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-ExtraLight.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-Light.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-Medium.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-Regular.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-SemiBold.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/Pretendard-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/fonts/Pretendard-Thin.woff2 -------------------------------------------------------------------------------- /src/assets/icons/Company/write.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/icons/Company/write.png -------------------------------------------------------------------------------- /src/assets/icons/Rank/leftArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/icons/Rank/leftArrow.png -------------------------------------------------------------------------------- /src/assets/icons/Rank/rightArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/icons/Rank/rightArrow.png -------------------------------------------------------------------------------- /src/assets/icons/Search/search1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/Search/search2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/Search/search3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/Story/redHeart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/icons/Story/redHeart.png -------------------------------------------------------------------------------- /src/assets/images/Auth/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/Auth/wave.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/Register/bigBannerIcon1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/images/Register/bigBannerIcon2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/images/Register/middleBannerIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/images/Register/photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/images/Register/photo.png -------------------------------------------------------------------------------- /src/assets/images/Register/smallBannerIcon1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/images/Register/smallBannerIcon2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/images/Register/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StuBee2/Rolling_Frontend/4d6690ac8011407da9e802188c478b309e543797/src/assets/images/Register/upload.png -------------------------------------------------------------------------------- /src/assets/images/Search/semicircle1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/assets/images/Search/semicircle2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/images/Search/wave.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/Story/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/Story/wave.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/User/cancel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/images/User/del.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/images/User/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/Alumni/Certify/index.tsx: -------------------------------------------------------------------------------- 1 | import { useCertify } from "@src/hooks/Alumni/useCertify"; 2 | import * as S from "./style"; 3 | import { Button } from "@stubee2/stubee2-rolling-ui"; 4 | import { tokenDecode } from "@src/utils/Auth/tokenDecode"; 5 | import { useEffect } from "react"; 6 | import { Column } from "@src/styles/flex"; 7 | 8 | const Certify = () => { 9 | const { ...attr } = useCertify(); 10 | const memberRole = tokenDecode("access", "authority"); 11 | 12 | useEffect(() => { 13 | if (memberRole === "MEMBER") { 14 | attr.rollingToast("동문 인증이 이미 되어있습니다.", "info"); 15 | attr.navigate("/"); 16 | } 17 | }, []); 18 | 19 | return ( 20 | 21 | 27 | 28 | That's 동문인증 29 | 30 | 동문인증을 하여 더 다양한 서비스를 즐겨보세요! 31 | 32 | 33 | 34 | 35 | 36 | DGSW 동문 인증 37 | 38 |

39 | 해당 절차는 DGSW 동문 인증하여 서비스를 제공하기 위해 40 | 이루어집니다. 41 |

42 |

동문 인증으로 롤링의 더 많은 기능을 활성화하세요.

43 |
44 | 45 | attr.handleGraduateCertified(e)} 47 | > 48 | 49 | 50 | Q. DGSW 사감선생님 중, 한 분의 성함을 입력해주세요. 51 | 52 | 53 | 58 | 선생님 59 | 60 | 61 | 62 | 65 | 66 |
67 |
68 |
69 |
70 | ); 71 | }; 72 | 73 | export default Certify; 74 | -------------------------------------------------------------------------------- /src/components/Common/Auth/SignIn/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import { useEscCloseModal } from "@stubee2/stubee2-rolling-util"; 3 | import { useSetRecoilState } from "recoil"; 4 | import { SignInModalAtom } from "@src/stores/auth/auth.store"; 5 | import wave from "@src/assets/images/Auth/wave.svg"; 6 | import close from "@src/assets/images/Auth/close.svg"; 7 | import github from "@src/assets/images/Auth/github.svg"; 8 | import { gitSignInUrl } from "@src/constants/Auth/auth.constant"; 9 | import { turnOnOffModal } from "@src/utils/Modal/turnOnOffModal"; 10 | 11 | const SignIn = () => { 12 | const setSignInModal = useSetRecoilState(SignInModalAtom); 13 | useEscCloseModal(setSignInModal); 14 | return ( 15 | turnOnOffModal(setSignInModal, "off")}> 16 | e.stopPropagation()}> 17 | turnOnOffModal(setSignInModal, "off")} 20 | alt="이미지 없음" 21 | /> 22 | 23 | 시작하기 24 | 25 | 26 |

지금 로그인하고 맞춤 롤링 콘텐츠를 활성화하세요.

27 |

수 많은 선배들의 이야기가 롤링에서 펼쳐집니다.

28 |
29 | 30 | (window.location.href = gitSignInUrl)}> 31 | 이미지 없음 32 |

Github 간편 로그인

33 |
34 | 35 | 36 |
37 |
38 | ); 39 | }; 40 | 41 | export default SignIn; 42 | -------------------------------------------------------------------------------- /src/components/Common/ErrorBoundary/index.tsx: -------------------------------------------------------------------------------- 1 | import { Component, ErrorInfo, ReactNode } from "react"; 2 | 3 | interface Props { 4 | children: ReactNode; 5 | fallback: ReactNode; 6 | } 7 | 8 | interface State { 9 | hasError: boolean; 10 | } 11 | 12 | class ErrorBoundary extends Component { 13 | public state: State = { 14 | hasError: false, 15 | }; 16 | 17 | public static getDerivedStateFromError(_: Error): State { 18 | return { hasError: true }; 19 | } 20 | 21 | public componentDidCatch(error: Error, errorInfo: ErrorInfo) { 22 | console.error("Uncaught error:", error, errorInfo); 23 | } 24 | 25 | public render() { 26 | if (this.state.hasError) { 27 | return this.props.fallback; 28 | } 29 | 30 | return this.props.children; 31 | } 32 | } 33 | 34 | export default ErrorBoundary; 35 | -------------------------------------------------------------------------------- /src/components/Common/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import logo from "@src/assets/icons/Logo/logo.svg"; 3 | import { 4 | FOOTER_ITEMS, 5 | FOOTER_MEMBERS_ITEMS, 6 | } from "@src/constants/Footer/footer.constant"; 7 | import { Row } from "@src/styles/flex"; 8 | 9 | export const Footer = () => { 10 | return ( 11 | 12 | 13 | 14 | 15 | (window.location.href = "/")}> 16 | 이미지 없음 17 |

Rolling

18 |
19 | 20 | Rolling은 직업계고 학생들을 돕기 위한 졸업생 취업 정보 리뷰 21 | 서비스입니다. 22 | 23 |
24 | 25 | 26 | {FOOTER_ITEMS.map((item) => ( 27 |
  • window.open(item.link, "_blank")} 30 | > 31 | {item.name} 32 |
  • 33 | ))} 34 |
    35 |
    36 | 37 | 38 | 39 | Team StuBee 40 | 41 | {FOOTER_MEMBERS_ITEMS.map((item) => ( 42 |
  • window.open(item.link, "_blank")} 45 | > 46 | {item.name} 47 |
  • 48 | ))} 49 |
    50 |
    51 |

    52 | 주소: 대구 달성군 구지면 창리로11길 93 53 | (대구소프트웨어마이스터고등학교) 54 |

    55 |
    56 |
    57 |
    58 | ); 59 | }; 60 | 61 | export default Footer; 62 | -------------------------------------------------------------------------------- /src/components/Common/Modal/CompanyAddress/index.tsx: -------------------------------------------------------------------------------- 1 | import { useEscCloseModal } from "@stubee2/stubee2-rolling-util"; 2 | import { Dispatch, SetStateAction } from "react"; 3 | import DaumPostcodeEmbed from "react-daum-postcode"; 4 | import * as S from "../../../Story/Company/style"; 5 | import { turnOnOffModal } from "@src/utils/Modal/turnOnOffModal"; 6 | import { CompanyParam } from "@src/services/Company/api"; 7 | 8 | interface Props { 9 | setIsOpenModal: Dispatch>; 10 | companyInfo: string; 11 | setCompanyInfo: Dispatch>; 12 | } 13 | 14 | const CompanyAddressModal = ({ ...attr }: Props) => { 15 | useEscCloseModal(attr.setIsOpenModal); 16 | 17 | const handleSelectAddress = (data: { address: string }) => { 18 | attr.setCompanyInfo((prev) => ({ 19 | ...prev, 20 | address: data.address, 21 | })); 22 | turnOnOffModal(attr.setIsOpenModal, "off"); 23 | }; 24 | 25 | return ( 26 | turnOnOffModal(attr.setIsOpenModal, "off")} 28 | > 29 | 36 | 37 | ); 38 | }; 39 | 40 | export default CompanyAddressModal; 41 | -------------------------------------------------------------------------------- /src/components/Common/Modal/MyInfo/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const Container = styled.div` 6 | width: 100%; 7 | height: 100vh; 8 | 9 | ${Flex({ alignItems: "center", justifyContent: "center" })} 10 | 11 | position: fixed; 12 | top: 0; 13 | left: 0; 14 | z-index: 10; 15 | `; 16 | 17 | export const Wrapper = styled.div` 18 | width: 1090px; 19 | height: calc(100% - 75px); 20 | 21 | position: absolute; 22 | bottom: 0; 23 | 24 | @media screen and (max-width: 1105px) { 25 | width: 100%; 26 | } 27 | `; 28 | 29 | export const MyInfoBox = styled.div` 30 | width: 272px; 31 | height: 181px; 32 | background-color: ${RollingPalette.text.Dark}; 33 | z-index: 3; 34 | border-radius: 15px; 35 | position: absolute; 36 | top: 0; 37 | right: 5px; 38 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); 39 | `; 40 | 41 | export const ProfileContainer = styled.div` 42 | width: 100%; 43 | height: 52%; 44 | 45 | border-radius: 15px 15px 0 0; 46 | border-bottom: 2px solid rgba(222, 224, 230, 0.3); 47 | 48 | padding-left: 20px; 49 | 50 | img { 51 | width: 51px; 52 | height: 51px; 53 | border-radius: 10px; 54 | } 55 | 56 | ${Flex({ alignItems: "center", columnGap: "10px" })} 57 | `; 58 | 59 | export const Name = styled.p` 60 | color: #ffffff; 61 | font-size: 14px; 62 | font-weight: bold; 63 | `; 64 | 65 | export const GitInfo = styled.div` 66 | color: ${RollingPalette.main.Base}; 67 | cursor: pointer; 68 | 69 | ${Flex({ columnGap: "5px", alignItems: "center" })} 70 | 71 | font-size: 14px; 72 | img { 73 | width: 15px; 74 | height: 15px; 75 | } 76 | `; 77 | 78 | export const MyPageLogout = styled.div` 79 | width: 100%; 80 | height: 48%; 81 | 82 | border-radius: 0 0 15px 15px; 83 | color: #ffffff; 84 | font-size: 14px; 85 | padding-left: 20px; 86 | 87 | ${Flex({ flexDirection: "column", justifyContent: "center", rowGap: "13px" })} 88 | 89 | div { 90 | ${Flex({ columnGap: "7px", alignItems: "center" })} 91 | cursor: pointer; 92 | 93 | img { 94 | width: 17px; 95 | height: 17px; 96 | } 97 | } 98 | `; 99 | -------------------------------------------------------------------------------- /src/components/Common/Modal/Search/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import search1 from "@src/assets/icons/Search/search1.svg"; 3 | import wave from "@src/assets/images/Search/wave.svg"; 4 | import { useSearchCompany } from "@src/hooks/Company/useSearchCompany"; 5 | import { turnOnOffModal } from "@src/utils/Modal/turnOnOffModal"; 6 | import { useEscCloseModal } from "@stubee2/stubee2-rolling-util"; 7 | 8 | const Search = () => { 9 | const { handleKeywordChange, handleKeywordSubmit, keyword, setSearchModal } = 10 | useSearchCompany(); 11 | useEscCloseModal(setSearchModal); 12 | 13 | return ( 14 | turnOnOffModal(setSearchModal, "off")}> 15 | e.stopPropagation()}> 16 | 17 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | ); 33 | }; 34 | 35 | export default Search; 36 | -------------------------------------------------------------------------------- /src/components/Common/NotFound/index.tsx: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | import useHideHeader from "@src/hooks/Header/useHideHeader"; 3 | import * as S from "./style"; 4 | import { Row } from "@src/styles/flex"; 5 | 6 | const NotFound = () => { 7 | const navigate = useNavigate(); 8 | useHideHeader(); 9 | return ( 10 | 16 | 17 | 404 18 |

    페이지를 찾을 수 없습니다.

    19 | navigate("/")}>홈으로 20 |
    21 |
    22 | ); 23 | }; 24 | 25 | export default NotFound; 26 | -------------------------------------------------------------------------------- /src/components/Common/NotFound/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const ErrorBox = styled.div` 6 | width: 50vh; 7 | 8 | margin: 0 10px 0 10px; 9 | font-weight: bold; 10 | 11 | ${Flex({ 12 | flexDirection: "column", 13 | alignItems: "center", 14 | justifyContent: "center", 15 | rowGap: "15px", 16 | })} 17 | `; 18 | 19 | export const ErrorText = styled.p` 20 | font-size: 100px; 21 | `; 22 | 23 | export const GoHomeBtn = styled.button` 24 | width: 100%; 25 | height: 50px; 26 | color: #ffffff; 27 | background-color: ${RollingPalette.main.Dark}; 28 | border-radius: 10px; 29 | outline: none; 30 | border: none; 31 | cursor: pointer; 32 | 33 | transform: scale(1); 34 | transition: all 0.1s ease-in-out; 35 | &:hover { 36 | background-color: rgba(28, 31, 91, 0.91); 37 | transform: scale(0.98); 38 | } 39 | &:active { 40 | background-color: rgba(28, 31, 91, 0.93); 41 | } 42 | `; 43 | -------------------------------------------------------------------------------- /src/components/Common/Provider/index.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from "react"; 2 | import GlobalStyle from "@src/styles/GlobalStyles"; 3 | import Header from "../Header/index"; 4 | import { useRecoilValue } from "recoil"; 5 | import { HideHeader } from "@src/stores/common/common.store"; 6 | 7 | interface Props { 8 | children: ReactNode; 9 | } 10 | 11 | const Provider = ({ children }: Props) => { 12 | const hideHeader = useRecoilValue(HideHeader); 13 | return ( 14 | <> 15 | 16 | {!hideHeader &&
    } 17 | <>{children} 18 | 19 | ); 20 | }; 21 | 22 | export default Provider; 23 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/Common/style.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { skeletonAnimation } from "@stubee2/stubee2-rolling-styled-components-util"; 3 | 4 | export const SkeletonBox = styled.div<{ 5 | width: string; 6 | height: string; 7 | }>` 8 | width: ${({ width }) => width}; 9 | height: ${({ height }) => height}; 10 | border-radius: 5px; 11 | ${skeletonAnimation} 12 | `; 13 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/CompanyDetail/Review/index.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonBox } from "../../Common/style"; 2 | import { Column } from "@src/styles/flex"; 3 | 4 | const StorySkeleton = () => { 5 | return ( 6 | 7 |
    8 | 9 | 10 |
    11 | {Array.from({ length: 10 }).map((_, idx) => ( 12 | 13 | ))} 14 |
    15 | ); 16 | }; 17 | 18 | export default StorySkeleton; 19 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/CompanyDetail/index.tsx: -------------------------------------------------------------------------------- 1 | import { Column, Row } from "@src/styles/flex"; 2 | import { SkeletonBox } from "../Common/style"; 3 | import * as S from "./style"; 4 | 5 | const CompanyDetailSkeleton = () => { 6 | return ( 7 | 8 | 9 |
    10 | 11 |
    12 | 13 |
    14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 | ); 30 | }; 31 | 32 | export default CompanyDetailSkeleton; 33 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/CompanyDetail/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { skeletonAnimation } from "@stubee2/stubee2-rolling-styled-components-util"; 3 | import styled from "styled-components"; 4 | 5 | export const CompanySkeletonContainer = styled.div` 6 | width: 100%; 7 | height: 100%; 8 | display: flex; 9 | 10 | @media screen and (max-width: 1005px) { 11 | flex-direction: column; 12 | row-gap: 2rem; 13 | } 14 | `; 15 | 16 | export const CompanySkeletonStarGrade = styled.div` 17 | width: 250px; 18 | height: 100%; 19 | 20 | ${Flex({ flexDirection: "column", rowGap: "2rem", alignItems: "center" })} 21 | 22 | @media screen and (max-width: 1005px) { 23 | width: 100%; 24 | height: 200px; 25 | flex-direction: row; 26 | row-gap: 0; 27 | column-gap: 3rem; 28 | } 29 | `; 30 | 31 | export const CompanyStarGradeSkeleton = styled.div` 32 | width: 100%; 33 | height: 500px; 34 | border-radius: 10px; 35 | ${skeletonAnimation}; 36 | @media screen and (max-width: 1005px) { 37 | height: 160px; 38 | } 39 | `; 40 | 41 | export const CompanySkeletonContent = styled.div` 42 | width: calc(100% - 250px); 43 | height: 100%; 44 | 45 | ${Flex({ flexDirection: "column", rowGap: "3rem" })} 46 | padding-left: 5rem; 47 | @media screen and (max-width: 1005px) { 48 | width: 100%; 49 | padding-left: 0; 50 | } 51 | `; 52 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/Home/Main/index.tsx: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { SkeletonBox } from "../../Common/style"; 3 | import * as S from "./style"; 4 | import { Column, Flex } from "@src/styles/flex"; 5 | 6 | const MainSkeleton = () => { 7 | return ( 8 | 9 | 10 | 11 | 12 | {Array.from({ length: 9 }).map((_, idx) => ( 13 | 14 | ))} 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default MainSkeleton; 22 | 23 | const Row = styled.div` 24 | width: 100%; 25 | height: 100%; 26 | ${Flex({ flexWrap: "wrap", gap: "1.5rem" })} 27 | `; 28 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/Home/Main/style.ts: -------------------------------------------------------------------------------- 1 | import { skeletonAnimation } from "@stubee2/stubee2-rolling-styled-components-util"; 2 | import styled from "styled-components"; 3 | 4 | export const MainItemSkeletonBox = styled.div` 5 | width: 330px; 6 | height: 300px; 7 | border: 1px solid #ddd; 8 | 9 | border-radius: 10px; 10 | overflow: hidden; 11 | 12 | @media screen and (max-width: 1385px) { 13 | flex-basis: 47%; 14 | height: 340px; 15 | } 16 | @media screen and (max-width: 1105px) { 17 | flex-basis: 31%; 18 | height: 330px; 19 | } 20 | @media screen and (max-width: 900px) { 21 | flex-basis: 48%; 22 | } 23 | @media screen and (max-width: 533px) { 24 | flex-basis: auto; 25 | width: 100%; 26 | height: 380px; 27 | } 28 | 29 | ${skeletonAnimation}; 30 | `; 31 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/Home/Recommand/index.tsx: -------------------------------------------------------------------------------- 1 | import { RecommandItemContainer } from "@src/components/Home/Recommand/RecommandItem/style"; 2 | import { SkeletonBox } from "../../Common/style"; 3 | import { Row } from "@src/styles/flex"; 4 | 5 | const RecommandSkeleton = () => { 6 | return ( 7 | 8 | 13 | {Array.from({ length: 10 }).map((_, idx) => ( 14 | 15 | ))} 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default RecommandSkeleton; 22 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/Home/UserInfo/index.tsx: -------------------------------------------------------------------------------- 1 | import { Column } from "@src/styles/flex"; 2 | import { SkeletonBox } from "../../Common/style"; 3 | 4 | const UserInfoSkeleton = () => { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | 16 | export default UserInfoSkeleton; 17 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/User/Nav/index.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | PageSelectContainer, 3 | PageSelectWrapper, 4 | UserNavBar, 5 | } from "@src/components/User/Nav/style"; 6 | import { SkeletonBox } from "../../Common/style"; 7 | import * as S from "./style"; 8 | import { Column } from "@src/styles/flex"; 9 | 10 | const NavSkeleton = () => { 11 | return ( 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {Array.from({ length: 2 }).map((item, idx) => ( 29 | 30 | ))} 31 | 32 | 33 | 34 | 35 | ); 36 | }; 37 | 38 | export default NavSkeleton; 39 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/User/Nav/style.ts: -------------------------------------------------------------------------------- 1 | import { skeletonAnimation } from "@stubee2/stubee2-rolling-styled-components-util"; 2 | import styled from "styled-components"; 3 | 4 | export const NavProfileLogoSkeleton = styled.div` 5 | width: 115px; 6 | height: 115px; 7 | border-radius: 100%; 8 | ${skeletonAnimation} 9 | `; 10 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/User/StoryStatus/index.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonBox } from "../../Common/style"; 2 | 3 | const StoryStatusSkeleton = () => { 4 | return ; 5 | }; 6 | 7 | export default StoryStatusSkeleton; 8 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/User/index.tsx: -------------------------------------------------------------------------------- 1 | import { Column } from "@src/styles/flex"; 2 | import { SkeletonBox } from "../Common/style"; 3 | 4 | const UserSkeleton = () => { 5 | return ( 6 | 7 | {Array.from({ 8 | length: 5, 9 | }).map((item, idx) => ( 10 | 11 | ))} 12 | 13 | ); 14 | }; 15 | 16 | export default UserSkeleton; 17 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/ViewAll/All/index.tsx: -------------------------------------------------------------------------------- 1 | import { Wrapper } from "@src/components/ViewAll/All/AllList/style"; 2 | import { CompanyContent } from "@src/components/ViewAll/style"; 3 | import { SkeletonBox } from "../../Common/style"; 4 | import * as S from "./style"; 5 | import { Column } from "@src/styles/flex"; 6 | 7 | const AllListSkeleton = () => { 8 | return ( 9 | 10 | 11 | {Array.from({ length: 20 }).map((_, idx) => ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ))} 22 | 23 | 24 | ); 25 | }; 26 | 27 | export default AllListSkeleton; 28 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/ViewAll/All/style.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const AllSkeletonBox = styled.div` 4 | width: 282px; 5 | height: 320px; 6 | 7 | @media screen and (max-width: 985px) { 8 | flex-basis: 31.5%; 9 | } 10 | @media screen and (max-width: 645px) { 11 | flex-basis: 48%; 12 | height: 300px; 13 | } 14 | @media screen and (max-width: 500px) { 15 | flex-basis: 47.6%; 16 | } 17 | `; 18 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/ViewAll/Rank/index.tsx: -------------------------------------------------------------------------------- 1 | import { Wrapper } from "@src/components/ViewAll/Rank/RankList/style"; 2 | import { CompanyContent } from "@src/components/ViewAll/style"; 3 | import { SkeletonBox } from "../../Common/style"; 4 | import * as S from "./style"; 5 | import { Column, Row } from "@src/styles/flex"; 6 | 7 | const RankSkeleton = () => { 8 | return ( 9 | <> 10 | {Array.from({ length: 5 }).map((_, idx) => ( 11 | 12 | 13 | 14 | 15 | {Array.from({ length: 10 }).map((_, idx) => ( 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ))} 26 | 27 | 28 | 29 | ))} 30 | 31 | ); 32 | }; 33 | 34 | export default RankSkeleton; 35 | -------------------------------------------------------------------------------- /src/components/Common/Skeleton/ViewAll/Rank/style.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const RankSkeletonBox = styled.div` 4 | width: 285px; 5 | height: 320px; 6 | 7 | @media screen and (max-width: 985px) { 8 | flex-basis: 31.5%; 9 | } 10 | @media screen and (max-width: 645px) { 11 | flex-basis: 48%; 12 | width: 267px; 13 | height: 300px; 14 | } 15 | @media screen and (max-width: 500px) { 16 | flex-basis: 47.6%; 17 | width: 223px; 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /src/components/Common/Star/index.tsx: -------------------------------------------------------------------------------- 1 | import { StarGradeProps } from "@src/types/StarGrade/starGrade.type"; 2 | import { StarRating } from "@stubee2/stubee2-rolling-ui"; 3 | import * as S from "./style"; 4 | import { Column, Row } from "@src/styles/flex"; 5 | 6 | const Star = ({ rankStatus, fontSize, ...attr }: StarGradeProps) => { 7 | return ( 8 | 9 | {rankStatus.map((item) => ( 10 | 11 | 12 |

    {item.title}

    13 | · {item.star}점 14 |
    15 | 16 | 17 | 18 | 19 |
    20 | ))} 21 |
    22 | ); 23 | }; 24 | 25 | export default Star; 26 | -------------------------------------------------------------------------------- /src/components/Common/Star/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import styled from "styled-components"; 3 | 4 | export const StarContainer = styled.div<{ fontSize?: string }>` 5 | width: 100%; 6 | height: 140px; 7 | 8 | background-color: rgba(242, 244, 245, 1); 9 | border-radius: 10px; 10 | font-size: ${({ fontSize }) => fontSize}; 11 | 12 | ${Flex({ 13 | alignItems: "center", 14 | justifyContent: "space-between", 15 | columnGap: "1.5rem", 16 | })} 17 | 18 | font-size: 16px; 19 | 20 | padding: 0 3rem 0 3rem; 21 | white-space: nowrap; 22 | background-color: red; 23 | 24 | overflow-x: auto; 25 | overflow-y: hidden; 26 | background-color: #f2f4f5; 27 | `; 28 | 29 | export const StarGradeText = styled.p` 30 | font-weight: 800; 31 | `; 32 | 33 | export const StarRatingContainer = styled.p` 34 | text-align: center; 35 | `; 36 | -------------------------------------------------------------------------------- /src/components/Common/StorySetUp/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import { BiDotsVerticalRounded } from "@react-icons/all-files/bi/BiDotsVerticalRounded"; 3 | import { USER_STORY_SETUP_ITEMS } from "@src/constants/User/user.constants"; 4 | import { useSetUpStory } from "@src/hooks/Story/useSetUpStory"; 5 | 6 | interface Props { 7 | storyId: string; 8 | companyId: string; 9 | isCoincideStoryId: boolean; 10 | } 11 | 12 | const StorySetUp = ({ ...attr }: Props) => { 13 | const { ...hooks } = useSetUpStory(); 14 | const { storyId, companyId, isCoincideStoryId } = attr; 15 | 16 | return ( 17 | <> 18 | {hooks.isClickDots && isCoincideStoryId ? ( 19 | <> 20 | {USER_STORY_SETUP_ITEMS.map((item) => ( 21 | 25 | hooks.hanldeStorySetUpClick(item.id, storyId, companyId) 26 | } 27 | alt="이미지 없음" 28 | /> 29 | ))} 30 | 31 | ) : ( 32 | 33 | { 37 | hooks.setIsClickDots(true); 38 | hooks.setModifyStoryId(storyId); 39 | }} 40 | /> 41 | 42 | )} 43 | 44 | ); 45 | }; 46 | 47 | export default StorySetUp; 48 | -------------------------------------------------------------------------------- /src/components/Common/StorySetUp/style.ts: -------------------------------------------------------------------------------- 1 | import { HoverAnimation } from "@src/styles/common.style"; 2 | import styled from "styled-components"; 3 | 4 | export const Icon = styled.img` 5 | cursor: pointer; 6 | width: 30px; 7 | height: 30px; 8 | `; 9 | 10 | export const SetUpIconContainer = styled.div` 11 | width: 30px; 12 | height: 30px; 13 | ${HoverAnimation}; 14 | `; 15 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/CompanyDetailInfo/Content/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import bag from "@src/assets/icons/Company/bag.svg"; 3 | import tool from "@src/assets/icons/Company/tool.svg"; 4 | import { CompanyInfoType } from "@src/types/Company/company.type"; 5 | import logo from "@src/assets/icons/Logo/logo.svg"; 6 | import { getDateText } from "@stubee2/stubee2-rolling-util"; 7 | import { CompanyDetailRegistAt } from "../style"; 8 | import { getRgb } from "@src/utils/Rgb/getRgb"; 9 | import { Column, Row } from "@src/styles/flex"; 10 | 11 | const CompanyDetailContent = ({ ...attr }: CompanyInfoType) => { 12 | return ( 13 | 14 | 15 | 16 | 17 | 기본정보 18 | 19 | 20 | 이 정보는 졸업생들이 작성한 데이터를 기반으로 만들어지고 있어요! 21 | 22 | 23 | 24 | 25 | 26 | {getDateText(new Date(attr.companyCreatedAt))} 작성 27 | 28 | 29 | 30 | 이미지 없음 31 | 32 | {attr.companyName} 33 | 34 | {attr.companyAddress + (" " + (attr.companyAddressEtc || ""))} 35 | 36 | 37 | 38 | 39 | 40 | 이미지 없음 41 |

    {attr.companyDescription}

    42 |
    43 |
    44 | 45 | {/* 아래는 추후에 추가될 기능 */} 46 | {/* 47 | {Array.from({ length: 10 }).map((_, idx) => ( 48 | 이미지 없음 53 | ))} 54 | */} 55 |
    56 | ); 57 | }; 58 | 59 | export default CompanyDetailContent; 60 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/CompanyDetailInfo/Content/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const Image = styled.img` 6 | width: 30px; 7 | height: 30px; 8 | `; 9 | 10 | export const BasicInfo = styled.p` 11 | margin-top: 5px; 12 | font-size: 25px; 13 | font-weight: 700; 14 | `; 15 | 16 | export const SubTitle = styled.p` 17 | color: ${RollingPalette.unEmphasize.Dark}; 18 | font-size: 15px; 19 | font-weight: 600; 20 | `; 21 | 22 | export const InfoContainer = styled.div` 23 | width: 100%; 24 | padding-bottom: 20px; 25 | ${Flex({ flexDirection: "column", rowGap: "15px" })} 26 | border-bottom: 3px solid ${RollingPalette.unEmphasize.Light}; 27 | `; 28 | 29 | export const Info = styled.div<{ backgroundColor: string }>` 30 | width: 100%; 31 | ${Flex({ alignItems: "center", columnGap: "15px" })} 32 | img { 33 | width: 75px; 34 | height: 75px; 35 | border-radius: 5px; 36 | object-fit: contain; 37 | border: 1px solid #dddddd; 38 | background-color: ${({ backgroundColor }) => backgroundColor || "#fff"}; 39 | } 40 | `; 41 | 42 | export const CompanyName = styled.p` 43 | color: #090a0a; 44 | font-size: 25px; 45 | font-weight: 700; 46 | `; 47 | 48 | export const CompanyAddress = styled.p` 49 | color: ${RollingPalette.unEmphasize.Dark}; 50 | font-size: 15px; 51 | font-weight: 500; 52 | `; 53 | 54 | export const Description = styled.div` 55 | width: 100%; 56 | line-height: 25px; 57 | font-size: 16px; 58 | font-weight: 600; 59 | 60 | ${Flex({ columnGap: "5px" })} 61 | 62 | img { 63 | width: 22px; 64 | height: 22px; 65 | } 66 | p { 67 | width: 100%; 68 | font-size: 18px; 69 | max-height: 200px; 70 | white-space: pre-wrap; 71 | overflow-y: auto; 72 | padding-left: 10px; 73 | } 74 | `; 75 | 76 | export const CompanyImgContainer = styled.div` 77 | overflow-x: auto; 78 | padding-bottom: 15px; 79 | ${Flex({ columnGap: "10px" })} 80 | img { 81 | width: 350px; 82 | height: 200px; 83 | object-fit: cover; 84 | border-radius: 5px; 85 | border: 1px solid #dddddd; 86 | } 87 | `; 88 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/CompanyDetailInfo/Story/index.tsx: -------------------------------------------------------------------------------- 1 | import StoryItem from "@src/components/User/Story/StoryItem"; 2 | import { useEffect } from "react"; 3 | import { useInView } from "react-intersection-observer"; 4 | import * as S from "./style"; 5 | import { useGetStoryListCompanyIdQuery } from "@src/services/Story/queries"; 6 | import { Column } from "@src/styles/flex"; 7 | 8 | interface Props { 9 | companyId: string; 10 | } 11 | 12 | const CompanyDetailStory = ({ companyId }: Props) => { 13 | const { data: storyList, fetchNextPage } = useGetStoryListCompanyIdQuery( 14 | { 15 | id: companyId, 16 | }, 17 | { suspense: true } 18 | ); 19 | const [ref, inView] = useInView(); 20 | const storyListData = storyList?.pages[0].data; 21 | 22 | useEffect(() => { 23 | if (inView) { 24 | fetchNextPage(); 25 | } 26 | }, [inView]); 27 | 28 | return ( 29 | 30 | 31 |

    졸업생들의 롤링 Story ·

    32 | {storyListData?.length} 33 |
    34 | 35 | {storyListData?.length!! > 0 ? ( 36 | storyList?.pages.map((list) => 37 | list.data.map((item) => ( 38 | 39 | )) 40 | ) 41 | ) : ( 42 |

    등록된 스토리가 없습니다.

    43 | )} 44 |
    45 |
    46 | 47 | ); 48 | }; 49 | 50 | export default CompanyDetailStory; 51 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/CompanyDetailInfo/Story/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const StoryTitle = styled.div` 6 | font-size: 30px; 7 | font-weight: 700; 8 | ${Flex({ alignItems: "center", columnGap: "5px" })} 9 | `; 10 | 11 | export const StoryCount = styled.p` 12 | color: ${RollingPalette.main.Base}; 13 | `; 14 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/CompanyDetailInfo/UserProfile/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import github from "@src/assets/images/Auth/github.svg"; 3 | import { getDateText } from "@stubee2/stubee2-rolling-util"; 4 | import { convertToGithubLink } from "@src/utils/github/convertToGithubLink"; 5 | import { CompanyDetailRegistAt } from "../style"; 6 | 7 | interface Props { 8 | memberImageUrl: string; 9 | memberNickName: string; 10 | memberSocialLoginId: string; 11 | companyCreatedAt: string; 12 | } 13 | 14 | const CompanyDetailUserProfile = ({ ...attr }: Props) => { 15 | const userName = attr.memberNickName || attr.memberSocialLoginId; 16 | return ( 17 | 18 | 19 | 20 | 이미지 없음 21 | 22 | 23 | 24 | {userName} 25 | 27 | window.open( 28 | convertToGithubLink(attr.memberSocialLoginId), 29 | "_blank" 30 | ) 31 | } 32 | > 33 | 이미지 없음 34 |

    {attr.memberSocialLoginId}

    35 |
    36 |
    37 |
    38 | 39 | 40 | {getDateText(new Date(attr.companyCreatedAt))} 작성 41 | 42 |
    43 | ); 44 | }; 45 | 46 | export default CompanyDetailUserProfile; 47 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/CompanyDetailInfo/UserProfile/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const Container = styled.div` 6 | width: 100%; 7 | height: 50px; 8 | position: relative; 9 | ${Flex({ alignItems: "center", justifyContent: "flex-end" })} 10 | `; 11 | 12 | export const Wrapper = styled.div` 13 | position: absolute; 14 | top: 0; 15 | left: 0; 16 | ${Flex({ alignItems: "center" })} 17 | `; 18 | 19 | export const ImgContainer = styled.div` 20 | width: 130px; 21 | height: 130px; 22 | border-radius: 100%; 23 | 24 | ${Flex({ alignItems: "center", justifyContent: "center" })} 25 | 26 | background-color: #fff; 27 | z-index: 1; 28 | 29 | position: absolute; 30 | left: 0; 31 | border: 1px solid #d9d9d9; 32 | 33 | img { 34 | width: 105px; 35 | height: 105px; 36 | border-radius: 100%; 37 | object-fit: cover; 38 | } 39 | `; 40 | 41 | export const Content = styled.div<{ 42 | nameLength: number; 43 | }>` 44 | width: ${({ nameLength }) => (nameLength >= 13 ? "335px" : "300px")}; 45 | height: 105px; 46 | 47 | padding-right: ${({ nameLength }) => nameLength >= 13 && "15px"}; 48 | background-color: ${RollingPalette.main.Base}; 49 | border-radius: 5px; 50 | 51 | position: absolute; 52 | left: 3.5rem; 53 | 54 | ${Flex({ flexDirection: "column", rowGap: "12px", justifyContent: "center" })} 55 | 56 | padding-left: 5.5rem; 57 | white-space: nowrap; 58 | border: 1px solid #d9d9d9; 59 | `; 60 | 61 | export const NickName = styled.p` 62 | color: #f9fafb; 63 | font-size: 18px; 64 | font-weight: 700; 65 | `; 66 | 67 | export const GithubId = styled.div` 68 | color: ${RollingPalette.unEmphasize.Base}; 69 | font-size: 15px; 70 | font-weight: 500; 71 | 72 | ${Flex({ columnGap: "5px" })} 73 | cursor: pointer; 74 | 75 | img { 76 | width: 20px; 77 | height: 20px; 78 | } 79 | p { 80 | margin-top: 2px; 81 | overflow: hidden; 82 | text-overflow: ellipsis; 83 | } 84 | `; 85 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/CompanyStarGrades/index.tsx: -------------------------------------------------------------------------------- 1 | import bolt from "@src/assets/icons/Company/bolt.svg"; 2 | import { convertStarRatingObject } from "@src/utils/StarRating/convertRankingObject"; 3 | import { StarRating } from "@stubee2/stubee2-rolling-ui"; 4 | import * as S from "./style"; 5 | import logo from "@src/assets/icons/Logo/logo.svg"; 6 | import { CompanyStarGradeInfo } from "@src/types/Company/company.type"; 7 | import { getRgb } from "@src/utils/Rgb/getRgb"; 8 | import { Row } from "@src/styles/flex"; 9 | 10 | interface Props { 11 | starGradeInfo: CompanyStarGradeInfo; 12 | } 13 | 14 | const CompanyStarGrades = ({ starGradeInfo }: Props) => { 15 | const { ...attr } = starGradeInfo; 16 | return ( 17 | 18 | 19 | 22 | 이미지 없음 23 |

    {attr.companyName}

    24 |
    25 | 26 | 27 | 28 | 평균 평점 29 | 30 | 31 | {convertStarRatingObject(attr).map((item) => ( 32 |
  • 33 | 34 | {item.title} 35 | {item.star}점 36 | 37 |
    38 | 43 |
    44 |
  • 45 | ))} 46 |
    47 |
    48 |
    49 |
    50 | ); 51 | }; 52 | 53 | export default CompanyStarGrades; 54 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/CompanyDetailItem/index.tsx: -------------------------------------------------------------------------------- 1 | import { tieStarGradeToObject } from "@src/utils/StarRating/tieStarGradeToObject"; 2 | import CompanyDetailInfo from "./CompanyDetailInfo"; 3 | import CompanyStarGrades from "./CompanyStarGrades"; 4 | import { useGetCompanyInfoIdQuery } from "@src/services/Company/queries"; 5 | 6 | interface Props { 7 | id: string; 8 | } 9 | 10 | const CompanyDetailItem = ({ id }: Props) => { 11 | const { data: companyInfo } = useGetCompanyInfoIdQuery( 12 | { id }, 13 | { suspense: true } 14 | ); 15 | 16 | return ( 17 | <> 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default CompanyDetailItem; 25 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/index.tsx: -------------------------------------------------------------------------------- 1 | import { useAuthTopScroll } from "@stubee2/stubee2-rolling-util"; 2 | import { Suspense } from "react"; 3 | import ErrorBoundary from "../../Common/ErrorBoundary"; 4 | import CompanyDetailSkeleton from "../../Common/Skeleton/CompanyDetail"; 5 | import CompanyDetailItem from "./CompanyDetailItem"; 6 | import * as S from "./style"; 7 | 8 | interface Props { 9 | id: string; 10 | } 11 | 12 | const CompanyDetail = ({ id }: Props) => { 13 | useAuthTopScroll(); 14 | return ( 15 | 16 | 17 | 회사정보를 갖고오지 못했습니다.}> 18 | }> 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | }; 26 | 27 | export default CompanyDetail; 28 | -------------------------------------------------------------------------------- /src/components/Company/CompanyDetail/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import styled from "styled-components"; 3 | 4 | export const Container = styled.div` 5 | width: 100%; 6 | height: 100%; 7 | 8 | ${Flex({ alignItems: "center", justifyContent: "center" })} 9 | zoom: 0.8; 10 | 11 | padding: 90px 15px 15px 15px; 12 | min-width: 500px; 13 | `; 14 | 15 | export const Wrapper = styled.div` 16 | width: 1370px; 17 | height: 100%; 18 | padding-top: 2rem; 19 | display: flex; 20 | 21 | @media screen and (max-width: 1005px) { 22 | ${Flex({ flexDirection: "column", alignItems: "center", rowGap: "3rem" })} 23 | } 24 | 25 | @media screen and (max-width: 500px) { 26 | row-gap: 0rem; 27 | } 28 | overflow-y: auto; 29 | ::-webkit-scrollbar { 30 | display: none; 31 | } 32 | `; 33 | -------------------------------------------------------------------------------- /src/components/Home/Main/Rank/RankItem/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const RankCategoryTitle = styled.div` 6 | font-size: 17px; 7 | font-weight: bold; 8 | color: ${RollingPalette.unEmphasize.Dark}; 9 | 10 | ${Flex({ columnGap: "5px", alignItems: "center" })} 11 | 12 | img { 13 | width: 24px; 14 | height: 24px; 15 | } 16 | `; 17 | 18 | export const MainItemWrap = styled.div` 19 | width: 100%; 20 | height: 100%; 21 | ${Flex({ flexWrap: "wrap", gap: "1.5rem" })} 22 | `; 23 | 24 | export const RankNumber = styled.div` 25 | width: 40px; 26 | height: 40px; 27 | 28 | background-color: ${RollingPalette.main.Dark}; 29 | border-radius: 10px 0 10px 0; 30 | position: absolute; 31 | top: 0; 32 | left: 0; 33 | 34 | ${Flex({ alignItems: "center", justifyContent: "center" })} 35 | 36 | font-size: 20px; 37 | color: #fff; 38 | z-index: 2; 39 | `; 40 | -------------------------------------------------------------------------------- /src/components/Home/Main/Rank/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import graph from "@src/assets/icons/Home/graph.svg"; 3 | import { Suspense, useState } from "react"; 4 | import ErrorBoundary from "@src/components/Common/ErrorBoundary"; 5 | import RankItem from "./RankItem"; 6 | import { COMPANY_RANK_ITMES } from "@src/constants/Company/company.constant"; 7 | import MainSkeleton from "@src/components/Common/Skeleton/Home/Main"; 8 | import { MainContainer, MainTitle, MainWrapper } from "../style"; 9 | import { ViewAll } from "../../style"; 10 | import { useNavigate } from "react-router-dom"; 11 | import { Column, Row } from "@src/styles/flex"; 12 | 13 | const Rank = () => { 14 | const [rankCategorySelect, setRankCategorySelect] = useState("total"); 15 | const navigate = useNavigate(); 16 | 17 | return ( 18 | 19 | 20 | 21 | 22 | 23 | 이미지 없음 24 |

    25 | BEST 기업 랭킹 26 |

    27 |
    28 | 29 | navigate("/ranking")}>전체보기 30 |
    31 | 32 | 33 | {COMPANY_RANK_ITMES.map((item) => ( 34 | setRankCategorySelect(item.categoryName!!)} 37 | isSelect={rankCategorySelect === item.categoryName} 38 | > 39 | {item.name} 40 | 41 | ))} 42 | 43 |
    44 | 45 | 회사 랭킹을 갖고오지 못했습니다.}> 46 | }> 47 | 48 | 49 | 50 |
    51 |
    52 | ); 53 | }; 54 | 55 | export default Rank; 56 | -------------------------------------------------------------------------------- /src/components/Home/Main/Rank/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const RankCategoriesUl = styled.ul` 6 | ${Flex({ alignItems: "center", columnGap: "15px" })} 7 | 8 | overflow-x: hidden; 9 | overflow-y: hidden; 10 | 11 | padding: 20px 0 40px 0; 12 | width: 100%; 13 | height: 40px; 14 | 15 | @media screen and (max-width: 595px) { 16 | overflow-x: auto; 17 | } 18 | `; 19 | 20 | export const RankCategoryLi = styled.li<{ isSelect: boolean }>` 21 | height: 40px; 22 | padding: 0.5rem; 23 | font-size: 17px; 24 | 25 | font-weight: ${({ isSelect }) => isSelect && "800"}; 26 | color: ${({ isSelect }) => isSelect && "#fff"}; 27 | background-color: ${({ isSelect }) => isSelect && RollingPalette.main.Base}; 28 | cursor: pointer; 29 | 30 | ${Flex({ alignItems: "center", justifyContent: "center" })} 31 | border-radius: 10px; 32 | 33 | transform: scale(1); 34 | transition: all 0.1s ease-in-out; 35 | &:hover { 36 | background-color: ${({ isSelect }) => 37 | isSelect ? "rgba(72, 105, 246, 1)" : "#eeeeee"}; 38 | transform: scale(0.98); 39 | } 40 | &:active { 41 | background-color: ${({ isSelect }) => (isSelect ? "#2b3f94" : "#dddddd")}; 42 | } 43 | `; 44 | -------------------------------------------------------------------------------- /src/components/Home/Main/Search/SearchItem/style.ts: -------------------------------------------------------------------------------- 1 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 2 | import styled from "styled-components"; 3 | 4 | export const NoneData = styled.div` 5 | font-size: 18px; 6 | 7 | p { 8 | span { 9 | transition: all 0.1s ease-in-out; 10 | color: ${RollingPalette.main.Base}; 11 | font-weight: 800; 12 | cursor: pointer; 13 | 14 | &:hover { 15 | color: rgba(72, 105, 246, 0.81); 16 | } 17 | } 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /src/components/Home/Main/Search/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "../style"; 2 | import readingGlasses from "@src/assets/icons/Search/readingGlasses.svg"; 3 | import React, { Suspense } from "react"; 4 | import ErrorBoundary from "@src/components/Common/ErrorBoundary"; 5 | import SearchItem from "./SearchItem"; 6 | import MainSkeleton from "@src/components/Common/Skeleton/Home/Main"; 7 | 8 | interface Props { 9 | company: string; 10 | } 11 | 12 | function Search({ company }: Props) { 13 | return ( 14 | 15 | 16 | 17 | 이미지 없음 18 |

    내가 검색한 기업 · {company}

    19 |
    20 | 21 | 검색한 회사를 갖고오지 못했습니다.}> 22 | }> 23 | 24 | 25 | 26 |
    27 |
    28 | ); 29 | } 30 | 31 | export default React.memo(Search); 32 | -------------------------------------------------------------------------------- /src/components/Home/Nav/ExternalSite/index.tsx: -------------------------------------------------------------------------------- 1 | import { EXTERNALSITE_ITEMS } from "@src/constants/ExternalSite/externalSite.constant"; 2 | import * as S from "./style"; 3 | import web from "@src/assets/icons/Home/web.svg"; 4 | 5 | const ExternalSite = () => { 6 | return ( 7 | 8 | 9 | 이미지 없음 10 |

    더 많은 정보를 알고 싶다면?

    11 |
    12 | 13 | 14 | 15 | {EXTERNALSITE_ITEMS.map((item) => ( 16 | window.open(item.link, "_blank")} 19 | > 20 | 이미지 없음 21 |

    {item.name} 바로가기

    22 |
    23 | ))} 24 |
    25 |
    26 |
    27 | ); 28 | }; 29 | 30 | export default ExternalSite; 31 | -------------------------------------------------------------------------------- /src/components/Home/Nav/ExternalSite/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import styled from "styled-components"; 3 | 4 | export const ExternalSiteContainer = styled.div` 5 | margin-top: 10px; 6 | width: 100%; 7 | ${Flex({ flexDirection: "column", rowGap: "1rem" })} 8 | `; 9 | 10 | export const ExternalSiteTitle = styled.div` 11 | font-size: 17px; 12 | font-weight: 600; 13 | 14 | ${Flex({ alignItems: "center", columnGap: "5px" })} 15 | 16 | img { 17 | width: 20px; 18 | height: 20px; 19 | } 20 | `; 21 | 22 | export const ExternalSiteItemContainer = styled.div` 23 | width: 100%; 24 | padding: 0 1rem 1rem 1rem; 25 | border: 1px solid #dddddd; 26 | border-radius: 10px; 27 | background-color: #fff; 28 | `; 29 | 30 | export const ExternalSiteItemWrapper = styled.ul` 31 | margin-top: 15px; 32 | ${Flex({ flexDirection: "column", rowGap: "1rem" })} 33 | `; 34 | 35 | export const ExternalSiteItem = styled.li` 36 | width: 100%; 37 | cursor: pointer; 38 | border-radius: 10px; 39 | 40 | ${Flex({ alignItems: "center", columnGap: "0.7rem" })} 41 | 42 | img { 43 | width: 50px; 44 | height: 50px; 45 | border-radius: 10px; 46 | border: 1px solid #dddddd; 47 | object-fit: cover; 48 | } 49 | 50 | p { 51 | font-size: 16px; 52 | } 53 | 54 | transform: scale(1); 55 | transition: all 0.1s ease-in-out; 56 | cursor: pointer; 57 | &:hover { 58 | background-color: #eeeeee; 59 | transform: scale(0.97); 60 | } 61 | &:active { 62 | background-color: #dddddd; 63 | color: #4869f6; 64 | } 65 | `; 66 | -------------------------------------------------------------------------------- /src/components/Home/Nav/UserInfo/index.tsx: -------------------------------------------------------------------------------- 1 | import ErrorBoundary from "@src/components/Common/ErrorBoundary"; 2 | import * as S from "./style"; 3 | import wonderFace from "@src/assets/icons/Home/wonderFace.svg"; 4 | import { Suspense } from "react"; 5 | import { stringEllipsis } from "@stubee2/stubee2-rolling-util"; 6 | import { useNavigate } from "react-router-dom"; 7 | import UserInfoSkeleton from "@src/components/Common/Skeleton/Home/UserInfo"; 8 | import { tokenDecode } from "@src/utils/Auth/tokenDecode"; 9 | import { useGetMyInfoQuery } from "@src/services/Member/queries"; 10 | import { Column } from "@src/styles/flex"; 11 | 12 | const UserInfo = () => { 13 | return ( 14 | 15 | 내 정보를 갖고오지 못했습니다.}> 16 | }> 17 | 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | function UserInfoItem() { 25 | const navigate = useNavigate(); 26 | const { data: myInfo } = useGetMyInfoQuery({ suspense: true }); 27 | const isNickName = !myInfo?.details.nickName; 28 | const isMember = tokenDecode("access", "authority") === "MEMBER"; 29 | 30 | return ( 31 | <> 32 | 33 | 이미지 없음 34 |
    navigate("/mypage/profile")}> 35 | 36 | {isNickName ? myInfo?.details.name : myInfo?.details.nickName} 37 | 38 | 39 | {stringEllipsis( 40 | myInfo?.details.email!! || "이메일을 설정해주세요", 41 | 22 42 | )} 43 | 44 |
    45 |
    46 | 47 | 48 | 49 | 이미지 없음 50 |

    51 | {isMember 52 | ? "내 기업 스토리가 등록 되어있나요?" 53 | : "동문 인증이 되어 있지 않나요?"} 54 |

    55 |
    56 | 57 | navigate(isMember ? "/story" : "/alumni/certify")} 59 | > 60 | {isMember ? "스토리 등록하러 가기" : "동문인증 하러가기"} 61 | 62 |
    63 | 64 | ); 65 | } 66 | 67 | export default UserInfo; 68 | -------------------------------------------------------------------------------- /src/components/Home/Nav/UserInfo/style.ts: -------------------------------------------------------------------------------- 1 | import { Flex } from "@src/styles/flex"; 2 | import { RollingPalette } from "@stubee2/stubee2-rolling-design-token"; 3 | import styled from "styled-components"; 4 | 5 | export const UserInfoBox = styled.div` 6 | width: 100%; 7 | white-space: nowrap; 8 | ${Flex({ alignItems: "center", columnGap: "10px" })}; 9 | 10 | img { 11 | width: 75px; 12 | height: 75px; 13 | border: 1px solid #d9d9d9; 14 | object-fit: cover; 15 | border-radius: 4rem; 16 | } 17 | 18 | div { 19 | width: calc(100% - 85px); 20 | cursor: pointer; 21 | ${Flex({ flexDirection: "column", rowGap: "8px" })} 22 | } 23 | `; 24 | 25 | export const UserInfoNickName = styled.p` 26 | height: 20px; 27 | font-size: 18px; 28 | 29 | font-weight: 600; 30 | overflow-x: hidden; 31 | text-overflow: ellipsis; 32 | 33 | transition: all 0.1s ease-in-out; 34 | &:hover { 35 | color: ${RollingPalette.main.Base}; 36 | } 37 | `; 38 | 39 | export const UserInfoEmail = styled.p` 40 | font-size: 15px; 41 | `; 42 | 43 | export const RegistTextContainer = styled.div` 44 | width: 100%; 45 | 46 | margin-bottom: 15px; 47 | font-weight: 600; 48 | 49 | ${Flex({ alignItems: "center", columnGap: "5px" })} 50 | 51 | img { 52 | width: 20px; 53 | height: 20px; 54 | } 55 | `; 56 | 57 | export const CompanyRegistBtn = styled.button` 58 | width: 100%; 59 | height: 57px; 60 | 61 | outline: none; 62 | background-color: #fff; 63 | border-radius: 5px; 64 | font-size: 15px; 65 | 66 | color: ${RollingPalette.main.Base}; 67 | border: 2px solid ${RollingPalette.main.Base}; 68 | cursor: pointer; 69 | 70 | transform: scale(1); 71 | transition: all 0.1s ease-in-out; 72 | &:hover { 73 | background-color: rgba(247, 249, 250, 1); 74 | transform: scale(0.985); 75 | } 76 | `; 77 | -------------------------------------------------------------------------------- /src/components/Home/Nav/index.tsx: -------------------------------------------------------------------------------- 1 | import { ACCESS_TOKEN_KEY } from "@src/constants/Auth/auth.constant"; 2 | import Token from "@src/libs/Token/Token"; 3 | import styled from "styled-components"; 4 | import ExternalSite from "./ExternalSite"; 5 | import UserInfo from "./UserInfo"; 6 | import { Flex } from "@src/styles/flex"; 7 | 8 | const Nav = () => { 9 | return ( 10 | 11 | {Token.getToken(ACCESS_TOKEN_KEY) && } 12 | 13 | 14 | ); 15 | }; 16 | 17 | export const NavContainer = styled.div` 18 | width: 290px; 19 | height: 100%; 20 | 21 | ${Flex({ flexDirection: "column" })} 22 | row-gap: calc(2rem - 10px); 23 | 24 | position: sticky; 25 | top: calc(90px + 2rem); 26 | 27 | @media screen and (max-width: 1105px) { 28 | display: none; 29 | } 30 | `; 31 | 32 | export default Nav; 33 | -------------------------------------------------------------------------------- /src/components/Home/Recommand/RecommandItem/index.tsx: -------------------------------------------------------------------------------- 1 | import { useInView } from "react-intersection-observer"; 2 | import logo from "@src/assets/icons/Logo/logo.svg"; 3 | import * as S from "./style"; 4 | import { useNavigate } from "react-router-dom"; 5 | import { useEffect } from "react"; 6 | import { getRgb } from "@src/utils/Rgb/getRgb"; 7 | import { useGetAllCompanyListQuery } from "@src/services/Company/queries"; 8 | import { Row } from "@src/styles/flex"; 9 | 10 | const RecommandItem = () => { 11 | const { data, fetchNextPage } = useGetAllCompanyListQuery({ suspense: true }); 12 | const companyList = data?.pages; 13 | const [ref, inView] = useInView(); 14 | const navigate = useNavigate(); 15 | 16 | useEffect(() => { 17 | if (inView) { 18 | fetchNextPage(); 19 | } 20 | }, [inView]); 21 | 22 | return ( 23 | <> 24 | {companyList!![0].data.length!! > 0 ? ( 25 | 26 | 31 | {companyList?.map((data) => 32 | data.data.map((item) => ( 33 | navigate(`/company/${item.companyId.id}`)} 36 | > 37 | 38 | 이미지 없음 42 | 43 |

    {item.companyDetails.name}

    44 |
    45 | )) 46 | )} 47 |
    48 | 49 | 50 | ) : ( 51 |

    졸업생들이 추천하는 회사가 없습니다.

    52 | )} 53 | 54 | ); 55 | }; 56 | 57 | export default RecommandItem; 58 | -------------------------------------------------------------------------------- /src/components/Home/Recommand/RecommandItem/style.ts: -------------------------------------------------------------------------------- 1 | import { StopDrag } from "@src/styles/common.style"; 2 | import { Flex } from "@src/styles/flex"; 3 | import styled from "styled-components"; 4 | 5 | export const RecommandItemContainer = styled.div` 6 | width: 100%; 7 | height: 100%; 8 | 9 | display: flex; 10 | overflow-y: hidden; 11 | overflow-x: auto; 12 | `; 13 | 14 | export const RecommandItemBox = styled.div` 15 | width: 250px; 16 | height: 200px; 17 | 18 | ${Flex({ flexDirection: "column", justifyContent: "center", rowGap: "5px" })} 19 | 20 | p { 21 | text-align: center; 22 | font-size: 17px; 23 | font-weight: bold; 24 | margin-top: 5px; 25 | } 26 | 27 | @media screen and (max-width: 1010px) { 28 | width: 220px; 29 | } 30 | `; 31 | 32 | export const ImageContainer = styled.div<{ rgb: string }>` 33 | width: 100%; 34 | height: 167px; 35 | 36 | border-radius: 10px; 37 | border: 1px solid #ddd; 38 | cursor: pointer; 39 | 40 | ${Flex({ justifyContent: "center" })} 41 | overflow: hidden; 42 | background-color: ${({ rgb }) => rgb || "#fff"}; 43 | zoom: 0.85; 44 | 45 | img { 46 | max-width: 100%; 47 | max-height: 100%; 48 | } 49 | 50 | ${StopDrag} 51 | `; 52 | -------------------------------------------------------------------------------- /src/components/Home/Recommand/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import developer from "@src/assets/icons/Home/developer.svg"; 3 | import RecommandItem from "./RecommandItem"; 4 | import ErrorBoundary from "@src/components/Common/ErrorBoundary"; 5 | import { Suspense } from "react"; 6 | import RecommandSkeleton from "@src/components/Common/Skeleton/Home/Recommand"; 7 | import { useNavigate } from "react-router-dom"; 8 | import { ViewAll } from "../style"; 9 | import { Row } from "@src/styles/flex"; 10 | 11 | const Recommand = () => { 12 | const navigate = useNavigate(); 13 | 14 | return ( 15 | 16 | 17 | 18 | 이미지 없음 19 |

    졸업생들이 추천해요!

    20 |
    21 | 22 | navigate("/all")}>전체보기 23 |
    24 | 25 | 26 | 회사 정보를 가지고 오지 못했습니다.}> 27 | }> 28 | 29 | 30 | 31 | 32 |
    33 | ); 34 | }; 35 | 36 | export default Recommand; 37 | -------------------------------------------------------------------------------- /src/components/Home/Recommand/style.ts: -------------------------------------------------------------------------------- 1 | import { FadeInAnimation } from "@src/styles/common.style"; 2 | import { Flex } from "@src/styles/flex"; 3 | import styled from "styled-components"; 4 | 5 | export const RecommandContainer = styled.div` 6 | width: 100%; 7 | ${Flex({ flexDirection: "column" })} 8 | 9 | @media screen and (max-width: 710px) { 10 | width: 99%; 11 | } 12 | `; 13 | 14 | export const SeniorRecommand = styled.div` 15 | font-size: 22px; 16 | font-weight: bold; 17 | 18 | ${Flex({ alignItems: "center", columnGap: "5px" })} 19 | 20 | img { 21 | width: 27px; 22 | height: 27px; 23 | } 24 | `; 25 | 26 | export const RecommandWrapper = styled.div` 27 | width: 100%; 28 | height: 240px; 29 | 30 | display: flex; 31 | ${FadeInAnimation}; 32 | `; 33 | -------------------------------------------------------------------------------- /src/components/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import * as S from "./style"; 2 | import Rank from "./Main/Rank"; 3 | import Nav from "./Nav"; 4 | import Footer from "../Common/Footer"; 5 | import Recommand from "./Recommand"; 6 | import { useRecoilValue } from "recoil"; 7 | import { SearchCompanyAtom } from "@src/stores/company/company.store"; 8 | import Search from "./Main/Search"; 9 | import { useAuthTopScroll } from "@stubee2/stubee2-rolling-util"; 10 | import { Row } from "@src/styles/flex"; 11 | 12 | const Home = () => { 13 | const searchCompany = useRecoilValue(SearchCompanyAtom); 14 | useAuthTopScroll(); 15 | return ( 16 | 17 | 18 | 19 | {searchCompany ? : } 20 |