diff --git a/apps/web/.env.development b/apps/web/.env.development index 299e6d4..9921337 100644 --- a/apps/web/.env.development +++ b/apps/web/.env.development @@ -1,3 +1,2 @@ NEXT_PUBLIC_DOMAIN=http://localhost:3000 -NEXT_PUBLIC_API_URL=https://dev-api.vook.app -NEXT_PUBLIC_GOOGLE_LOGIN_URL=https://dev-api.vook.app/oauth2/authorization/google +NEXT_PUBLIC_API_URL=https://dev-api.vook.app \ No newline at end of file diff --git a/apps/web/.env.production b/apps/web/.env.production index 058991a..36d3d65 100644 --- a/apps/web/.env.production +++ b/apps/web/.env.production @@ -1,3 +1,3 @@ NEXT_PUBLIC_DOMAIN=https://vook.app NEXT_PUBLIC_API_URL=https://api.vook.app -NEXT_PUBLIC_GOOGLE_LOGIN_URL=https://api.vook.app/oauth2/authorization/google +NEXT_PUBLIC_GOOGLE_LOGIN_URL=https://api.vook.app/oauth2/authorization/google \ No newline at end of file diff --git a/apps/web/.env.staging b/apps/web/.env.staging index 65984a4..c4aceb8 100644 --- a/apps/web/.env.staging +++ b/apps/web/.env.staging @@ -1,3 +1,3 @@ NEXT_PUBLIC_DOMAIN=https://stag.vook.app NEXT_PUBLIC_API_URL=https://stag-api.vook.app -NEXT_PUBLIC_GOOGLE_LOGIN_URL=https://stag-api.vook.app/oauth2/authorization/google +NEXT_PUBLIC_GOOGLE_LOGIN_URL=https://stag-api.vook.app/oauth2/authorization/google \ No newline at end of file diff --git a/apps/web/package.json b/apps/web/package.json index 3952183..c7e1d84 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -22,6 +22,7 @@ "@vook-client/api": "*", "@vook-client/design-system": "*", "dayjs": "^1.11.11", + "framer-motion": "^11.3.2", "js-cookie": "^3.0.5", "next": "^14.1.1", "react": "^18.2.0", diff --git a/apps/web/public/image/Excel.png b/apps/web/public/image/Excel.png new file mode 100644 index 0000000..d4053f1 Binary files /dev/null and b/apps/web/public/image/Excel.png differ diff --git a/apps/web/public/image/File.png b/apps/web/public/image/File.png new file mode 100644 index 0000000..501526d Binary files /dev/null and b/apps/web/public/image/File.png differ diff --git a/apps/web/public/image/Folder.png b/apps/web/public/image/Folder.png new file mode 100644 index 0000000..e3405dd Binary files /dev/null and b/apps/web/public/image/Folder.png differ diff --git a/apps/web/public/image/Jira.png b/apps/web/public/image/Jira.png new file mode 100644 index 0000000..b89e19c Binary files /dev/null and b/apps/web/public/image/Jira.png differ diff --git a/apps/web/public/image/Notion.png b/apps/web/public/image/Notion.png new file mode 100644 index 0000000..0b21a35 Binary files /dev/null and b/apps/web/public/image/Notion.png differ diff --git a/apps/web/public/image/Pen.png b/apps/web/public/image/Pen.png new file mode 100644 index 0000000..76ee0b5 Binary files /dev/null and b/apps/web/public/image/Pen.png differ diff --git a/apps/web/public/image/Star.png b/apps/web/public/image/Star.png new file mode 100644 index 0000000..3fc20ed Binary files /dev/null and b/apps/web/public/image/Star.png differ diff --git a/apps/web/public/image/spredadSheet.png b/apps/web/public/image/spredadSheet.png new file mode 100644 index 0000000..7892894 Binary files /dev/null and b/apps/web/public/image/spredadSheet.png differ diff --git a/apps/web/src/app/(afterLogin)/layout.css.ts b/apps/web/src/app/(afterLogin)/layout.css.ts index 4595844..b7ffa44 100644 --- a/apps/web/src/app/(afterLogin)/layout.css.ts +++ b/apps/web/src/app/(afterLogin)/layout.css.ts @@ -7,12 +7,11 @@ export const mainArea = style({ minHeight: `calc(100vh - ${HEADER_HEIGHT}px)`, - padding: 40, - // paddingBottom: 400, - marginTop: HEADER_HEIGHT, marginLeft: SIDE_BAR_WIDTH, + padding: '40px', + display: 'flex', flexDirection: 'column', }) diff --git a/apps/web/src/app/(afterLogin)/layout.tsx b/apps/web/src/app/(afterLogin)/layout.tsx index b6475c1..ed7de26 100644 --- a/apps/web/src/app/(afterLogin)/layout.tsx +++ b/apps/web/src/app/(afterLogin)/layout.tsx @@ -9,6 +9,7 @@ import { Header } from '@/components/Header' import { UserProvider } from '@/store/user' import { getQueryClient } from '@/utils/react-query' import { SilentRefresh } from '@/components/SilentRefresh/SilentRefresh' +import { SearchBox, SearchHistoryProvider } from '@/components/SearchBox' import { mainArea } from './layout.css' @@ -43,7 +44,11 @@ const Layout = async ({ children }: PropsWithChildren) => {
-
+
+ + + +
{children} diff --git a/apps/web/src/app/(afterLogin)/page.tsx b/apps/web/src/app/(afterLogin)/page.tsx deleted file mode 100644 index 15d3b75..0000000 --- a/apps/web/src/app/(afterLogin)/page.tsx +++ /dev/null @@ -1,48 +0,0 @@ -'use client' - -import { Button, Text } from '@vook-client/design-system' -import { useVacabularyInfoQuery } from '@vook-client/api' - -import { useModal } from '@/hooks/useModal' -import { ModalTypes } from '@/hooks/useModal/useModal' -import { WarnBox } from '@/components/common/Common' - -import { workspaceContainer, workspaceHeader } from './layout.css' -import WorkspaceList from './workspace/page' - -const Home = () => { - const { toggleModal, setModal } = useModal() - const { data: response } = useVacabularyInfoQuery() - - if (response == null) { - return null - } - const isDisabled = response?.result.length >= 3 - return ( -
-
- - MY WORKSPACE - - -
- - {isDisabled && 용어집은 3개까지만 생성 가능합니다.} - - -
- ) -} - -export default Home diff --git a/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.css.ts b/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.css.ts index eb9d2ab..4a3b445 100644 --- a/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.css.ts +++ b/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.css.ts @@ -42,3 +42,16 @@ export const highlightHit = style({ export const highlight = style({ backgroundColor: vars.colors.yellow, }) + +export const dropboxItem = style({ + display: 'flex', + alignItems: 'center', + width: 174, + gap: 10, +}) + +export const headerIconContainer = style({ + display: 'flex', + alignItems: 'center', + gap: 2, +}) diff --git a/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.tsx b/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.tsx index d4d89e3..0a17732 100644 --- a/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.tsx +++ b/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/Term.tsx @@ -8,26 +8,22 @@ import { termSort, useDeleteTermMutation, useGetTermQuery, + GetTermResponse, + TermSortValues, } from '@vook-client/api' import { useQueryClient } from '@tanstack/react-query' import { usePathname, useSearchParams } from 'next/navigation' import clsx from 'clsx' -import { - GetTermResponse, - TermSortValues, -} from 'node_modules/@vook-client/api/src/services/term/model' import { useToast } from '@/hooks/useToast' import { useVocabularyStore } from '@/store/term' import { useModal } from '@/hooks/useModal' import { ModalTypes } from '@/hooks/useModal/useModal' +import { LoadingComponent, NoneDataComponent } from '@/components/common' import { - LoadingComponent, - NoneDataComponent, -} from '../../../../../../components/common/Common' - -import { + dropboxItem, + headerIconContainer, highlight, highlightHit, termContainer, @@ -37,8 +33,6 @@ import { textContainer, } from './Term.css' -import { dropboxItem } from 'src/app/(afterLogin)/workspace/VocabularyItem.css' - const TextContainer = ({ length }: { length?: number }) => (
👀 용어목록 @@ -51,9 +45,11 @@ const TextContainer = ({ length }: { length?: number }) => ( const SortableListHeader = ({ handleSort, response, + sorts, }: { response: GetTermResponse handleSort: (sort: TermSort) => void + sorts: TermSortValues[] }) => { const { checkList, handleCheckList } = useVocabularyStore() @@ -74,14 +70,28 @@ const SortableListHeader = ({ kind="title" onClick={() => handleSort(termSort.Term)} > - 용어 +
+ 용어 + {sorts.includes(termSort.Term.Asc) && } + {sorts.includes(termSort.Term.Desc) && ( + + )} +
handleSort(termSort.Synonym)} > - 동의어 +
+ 동의어 + {sorts.includes(termSort.Synonym.Asc) && ( + + )} + {sorts.includes(termSort.Synonym.Desc) && ( + + )} +
handleSort(termSort.Meaning)} > - 뜻 +
+ 뜻 + {sorts.includes(termSort.Meaning.Asc) && ( + + )} + {sorts.includes(termSort.Meaning.Desc) && ( + + )} +
handleSort(termSort.CreatedAt)} > - 생성일자 +
+ 생성일자 + {sorts.includes(termSort.CreatedAt.Asc) && ( + + )} + {sorts.includes(termSort.CreatedAt.Desc) && ( + + )} +
@@ -293,7 +319,11 @@ export const Term = () => { {response?.result.length ? ( <> - + {response?.result.map((termData) => ( { + const cookieStore = cookies() + const isAuthorization = headers().get('X-AuthConfirm') + + if (isAuthorization !== 'confirmed') { + redirect('/login') + } + + const access = cookieStore.get('access')?.value || '' + const refresh = cookieStore.get('refresh')?.value || '' + + if (!access && !refresh) { + redirect('/login') + } + + const queryClient = getQueryClient() + queryClient.setQueryData(['access'], access) + queryClient.setQueryData(['refresh'], refresh) + + const user = await userService.userInfo(queryClient) + + if (user.result.status !== UserStatus.Registered) { + redirect('/signup') + } + + const dehydrateState = dehydrate(queryClient) + + return ( + {children} + ) +} + +export default Layout diff --git a/apps/web/src/app/(afterLogin)/workspace/page.tsx b/apps/web/src/app/(afterLogin)/workspace/page.tsx index 81ef666..e165233 100644 --- a/apps/web/src/app/(afterLogin)/workspace/page.tsx +++ b/apps/web/src/app/(afterLogin)/workspace/page.tsx @@ -3,6 +3,7 @@ import React, { useState } from 'react' import { useRouter } from 'next/navigation' import { useVacabularyInfoQuery } from '@vook-client/api' +import { Button, Text } from '@vook-client/design-system' import { useModal } from '@/hooks/useModal' import { ModalTypes } from '@/hooks/useModal/useModal' @@ -11,18 +12,25 @@ import { VocabularyDeleteModal, VocabularyEditModal, } from '@/modals/VocabularyModal/VocabularyModal' -import { LoadingComponent, NoneDataComponent } from '@/components/common/Common' +import { + LoadingComponent, + NoneDataComponent, + WarnBox, +} from '@/components/common/Common' import { workspaceInnerAlignRow } from '../layout.css' -import { VocabularyItem } from './VocabularyItem' +import { VocabularyItem } from './_components/VocabularyItem' +import { workspaceContainer, workspaceHeader } from './layout.css' export interface VocabularyModalDataType { uid: string defaultValue: string } -const WorkspaceList = () => { +const Home = () => { + const { toggleModal, setModal } = useModal() + const { data: response, isLoading } = useVacabularyInfoQuery() const { open, type } = useModal() @@ -41,9 +49,31 @@ const WorkspaceList = () => { name: vocabulary.name, createdAt: new Date(vocabulary.createdAt), })) - + if (response == null) { + return null + } + const isDisabled = response?.result.length >= 3 return ( - <> +
+
+ + MY WORKSPACE + + +
+ + {isDisabled && 용어집은 3개까지만 생성 가능합니다.} {vocabularyData.length > 0 ? (
{vocabularyData.map((vocabulary) => { @@ -74,8 +104,8 @@ const WorkspaceList = () => { defaultValue={modalData.defaultValue} /> )} - +
) } -export default WorkspaceList +export default Home diff --git a/apps/web/src/app/(beforeLogin)/auth/token/page.tsx b/apps/web/src/app/(beforeLogin)/auth/token/page.tsx index 973ff81..d693004 100644 --- a/apps/web/src/app/(beforeLogin)/auth/token/page.tsx +++ b/apps/web/src/app/(beforeLogin)/auth/token/page.tsx @@ -42,7 +42,7 @@ const AuthCallbackPage = ({ const isRegistered = userInfo.result.status === UserStatus.Registered if (isRegistered) { - router.push('/') + router.push('/workspace') const sendToken = () => { window.postMessage( diff --git a/apps/web/src/app/(beforeLogin)/terms/privacy/page.tsx b/apps/web/src/app/(beforeLogin)/terms/privacy/page.tsx index 5c4ab37..16514ee 100644 --- a/apps/web/src/app/(beforeLogin)/terms/privacy/page.tsx +++ b/apps/web/src/app/(beforeLogin)/terms/privacy/page.tsx @@ -296,7 +296,7 @@ const PrivacyTermPage = () => {
- 개인정보 관리책임자 • 성명 : 박재은 • 연락처 : pitapan1248@gmail.com + 개인정보 관리책임자 • 성명 : 박재은 • 연락처 : vook.help@gmail.com
diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/DetailBanner.css.ts b/apps/web/src/app/(landing)/_components/DetailBanner/DetailBanner.css.ts new file mode 100644 index 0000000..7844c8c --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/DetailBanner.css.ts @@ -0,0 +1,79 @@ +import { style } from '@vanilla-extract/css' +import { vars } from '@vook-client/design-system' + +export const detailBannerSection = style({ + display: 'flex', + flexDirection: 'column', + width: 1180, + gap: 22, + margin: 'auto', +}) + +export const extensionSection = style({ + position: 'relative', + display: 'flex', + flexDirection: 'column', + gap: 24, + padding: 60, + background: vars.colors['component-normal'], + width: '100%', + borderRadius: 30, + border: `1px solid ${vars.colors['semantic-line-normal']}`, + overflow: 'clip', +}) + +export const workspaceSection = style({ + position: 'relative', + display: 'flex', + flexDirection: 'column', + gap: 24, + padding: 60, + background: vars.colors['component-normal'], + width: '100%', + height: 680, + borderRadius: 30, + overflow: 'clip', +}) + +export const displaySection = style({ + width: '100%', + height: 680, + borderRadius: 30, + background: 'linear-gradient(0deg, #B4B4F3 0%, #5D5CE5 100%)', + outline: `1px solid ${vars.colors['semantic-line-normal']}`, + overflow: 'clip', +}) + +export const displayContainer = style({ + background: '#fff', + borderTop: `8px solid ${vars.colors['palette-gray-800']}`, + borderLeft: `8px solid ${vars.colors['palette-gray-800']}`, + borderTopLeftRadius: 30, + borderBottomLeftRadius: 3, + marginLeft: 100, + marginTop: 100, + height: 580, + paddingLeft: 40, + paddingTop: 40, + display: 'flex', + flexDirection: 'column', + gap: 30, +}) + +export const displayTermHeader = style({ + display: 'flex', + background: vars.colors['component-alternative'], + borderTopLeftRadius: 8, + borderBottomLeftRadius: 8, + marginTop: 20, +}) + +export const displayTermHeaderItem = style({ + padding: '16px 12px', +}) + +export const displayTermItem = style({ + display: 'flex', + padding: '8px 0 9px 0', + borderBottom: `1px solid ${vars.colors['semantic-line-alternative']}`, +}) diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/DetailBanner.tsx b/apps/web/src/app/(landing)/_components/DetailBanner/DetailBanner.tsx new file mode 100644 index 0000000..8dbd365 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/DetailBanner.tsx @@ -0,0 +1,134 @@ +import React from 'react' +import { Text } from '@vook-client/design-system' + +import { + detailBannerSection, + displayContainer, + displaySection, + displayTermHeader, + displayTermHeaderItem, + displayTermItem, + extensionSection, + workspaceSection, +} from './DetailBanner.css' +import { BannerIcons } from './Icons' +import { DeviceScreen } from './_components' +import CardSection from './_components/CardSection' + +const TableItem = ({ term, synom }: { term: string; synom: string }) => ( +
+
+ +
+
+ + {term} + +
+
+ + {synom} + +
+
+) + +export const DetailBanner = () => { + return ( +
+
+ + + Chrome Extension + + + 드래그 한 번으로 뜻 확인 + + +
+ + +
+ +
+
+ + + My Workspace + + + 주제별로 깔끔하게 관리 + + +
+
+
+
+ + 비개발자를 위한 용어집 + +
+
+
+ + 👀 용어 목록 + + + 12 + +
+
+
+ +
+
+ + 용어 + +
+
+ + 동의어 + +
+
+ + + + + +
+
+
+
+
+ ) +} diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/Icons/Icon.css.ts b/apps/web/src/app/(landing)/_components/DetailBanner/Icons/Icon.css.ts new file mode 100644 index 0000000..86fa30f --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/Icons/Icon.css.ts @@ -0,0 +1,19 @@ +import { style } from '@vanilla-extract/css' + +export const IconBox = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: 25, + height: 25, +}) + +export const LogoCircleBox = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: 20.89, + height: 20.89, + borderRadius: 21, + background: '#fff', +}) diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/Icons/Icon.tsx b/apps/web/src/app/(landing)/_components/DetailBanner/Icons/Icon.tsx new file mode 100644 index 0000000..eac819f --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/Icons/Icon.tsx @@ -0,0 +1,245 @@ +import { IconBox, LogoCircleBox } from './Icon.css' + +export const PointerIcon = () => ( +
+ + + +
+) + +export const WorkspaceIcon = () => ( +
+ + + + + + +
+) + +export const ChevronDown = () => ( +
+ + + +
+) + +export const Share = () => ( +
+ + + +
+) + +export const Star = () => ( +
+ + + +
+) + +export const Vook = () => ( +
+
+ + + + + +
+
+) + +export const Extension = () => ( +
+ + + +
+) + +export const Toggle = () => ( +
+ + + +
+) + +export const More = () => ( +
+ + + +
+) + +export const VookLogo = () => { + return ( + + + + + + ) +} + +export const CheckItem = () => ( + + + +) diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/Icons/index.tsx b/apps/web/src/app/(landing)/_components/DetailBanner/Icons/index.tsx new file mode 100644 index 0000000..acd2498 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/Icons/index.tsx @@ -0,0 +1,31 @@ +import { + PointerIcon, + ChevronDown, + WorkspaceIcon, + Share, + Star, + Vook, + Extension, + Toggle, + More, + VookLogo, + CheckItem, +} from './Icon' + +export const BannerIcons = { + PointerIcon, + ChevronDown, + WorkspaceIcon, + Share, + Star, + Vook, + Extension, + Toggle, + More, + VookLogo, + CheckItem, +} + +export type IconNames = keyof typeof BannerIcons + +export const iconNames = Object.keys(BannerIcons) as IconNames[] diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/_components/CardSection.tsx b/apps/web/src/app/(landing)/_components/DetailBanner/_components/CardSection.tsx new file mode 100644 index 0000000..6c34453 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/_components/CardSection.tsx @@ -0,0 +1,102 @@ +'use client' + +import React, { useEffect, useRef, useState } from 'react' +import { Icon, Text } from '@vook-client/design-system' + +import { AppearBottom } from '@/components/AppearBottom' + +import { + CardContainer, + CardContainerFooter, + CardContainerHeader, + IconContainer, +} from './CardSectoin.css' + +interface CardProps { + title?: string + date?: string +} + +export const Card = ({ + title = '비개발자를 위한 용어집', + date = '2024년 3월 17일 생성', +}: CardProps) => ( +
+
+ + {title} + +
+
+ + {date} + +
+ +
+
+
+) + +const CardSection = () => { + const [inView, setInView] = useState(false) + const ref = useRef(null) + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setInView(true) + } + }) + }, + { + threshold: 0.75, + }, + ) + + if (ref.current) { + observer.observe(ref.current) + } + + return () => { + if (ref.current) { + // eslint-disable-next-line react-hooks/exhaustive-deps + observer.unobserve(ref.current) + } + } + }, []) + + return ( +
+ {inView && ( + <> + + + + + + + + )} +
+ ) +} + +export default CardSection diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/_components/CardSectoin.css.ts b/apps/web/src/app/(landing)/_components/DetailBanner/_components/CardSectoin.css.ts new file mode 100644 index 0000000..6ee398b --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/_components/CardSectoin.css.ts @@ -0,0 +1,33 @@ +import { style, createVar } from '@vanilla-extract/css' + +export const accentVar = createVar() + +export const IconContainer = style({ + width: 32, + height: 32, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + transform: 'translateY(-5px)', +}) + +export const CardContainer = style({ + width: 460, + display: 'flex', + flexDirection: 'column', + gap: 40, + boxShadow: '0px 4px 12px #EAEAEA', + borderRadius: 20, +}) + +export const CardContainerHeader = style({ + width: 460, + padding: 32, +}) + +export const CardContainerFooter = style({ + display: 'flex', + width: '100%', + justifyContent: 'space-between', + padding: '5px 32px 29px', +}) diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/_components/DeviceScreen.css.ts b/apps/web/src/app/(landing)/_components/DetailBanner/_components/DeviceScreen.css.ts new file mode 100644 index 0000000..97c3f5d --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/_components/DeviceScreen.css.ts @@ -0,0 +1,129 @@ +import { vars } from '@vook-client/design-system' +import { style } from '@vanilla-extract/css' + +export const deviceScreen = style({ + position: 'absolute', + left: 0, + bottom: 0, + width: 1080, + height: 500, + backgroundColor: '#fff', + borderRight: `8px solid ${vars.colors['palette-gray-800']}`, + borderTop: `8px solid ${vars.colors['palette-gray-800']}`, + borderTopRightRadius: '30px', + borderBottomRightRadius: '3px', +}) + +export const deviceScreenHeader = style({ + display: 'flex', + justifyContent: 'flex-end', + alignItems: 'center', + paddingRight: 20, + height: 50.55, + backgroundColor: '#000', + borderTopRightRadius: '22px', +}) + +export const deviceScreenURLHeader = style({ + position: 'absolute', + width: '100%', + display: 'flex', + gap: 15, + justifyContent: 'flex-end', + alignItems: 'center', + paddingRight: 20, + height: 50.54, + backgroundColor: '#35363A', + zIndex: 2, +}) + +export const deviceScreenURL = style({ + display: 'flex', + width: '100%', + borderRadius: 22, + gap: 12, + justifyContent: 'flex-end', + alignItems: 'center', + backgroundColor: '#202124', + height: 33.7, + paddingRight: 15, +}) + +export const deviceScreenText = style({ + position: 'absolute', + top: 82, + left: 60, + zIndex: 1, +}) + +export const vookLogoContainer = style({ + position: 'absolute', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + boxShadow: + '0px 4.77px 9.55px rgba(0, 0, 0, 0.08), 0px 0px 4.77px rgba(0, 0, 0, 0.08)', + top: 197, + left: 373, + width: 38, + height: 38, + borderRadius: 38.2, +}) + +export const chromeExtensionContainer = style({ + width: 635, + display: 'flex', + flexDirection: 'column', + gap: 19, + position: 'absolute', + right: 52, + bottom: 20.55, + padding: 19, + boxShadow: + '0px 4.77px 9.55px rgba(0, 0, 0, 0.08), 0px 0px 4.77px rgba(0, 0, 0, 0.08)', + borderRadius: 7.16, +}) + +export const chromeExtensionHeader = style({ + display: 'flex', + justifyContent: 'space-between', +}) + +export const chromeExtensionTableContainer = style({ + borderRadius: 4.77, + border: `1.19px solid ${vars.colors['semantic-line-alternative']}`, +}) + +export const chromeExtensionTableHeaderText = style({ + display: 'flex', + width: 143, + padding: '6px 14px', + alignItems: 'center', + backgroundColor: vars.colors['palette-primary-50'], +}) + +export const chromeExtensionTable = style({ + display: 'flex', + width: 143, + padding: '9.5px 14.32px', + alignItems: 'center', +}) + +export const chromeExtensionFooter = style({ + display: 'flex', + justifyContent: 'flex-end', + gap: 4, +}) + +export const drag = style({ + display: 'inline-block', + position: 'relative', +}) + +export const dragInner = style({ + position: 'absolute', + left: 0, + top: 0, + height: '100%', + backgroundColor: 'rgba(0, 119, 255, 0.22)', +}) diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/_components/DeviceScreen.tsx b/apps/web/src/app/(landing)/_components/DetailBanner/_components/DeviceScreen.tsx new file mode 100644 index 0000000..f751fe5 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/_components/DeviceScreen.tsx @@ -0,0 +1,185 @@ +'use client' + +import React, { PropsWithChildren, useEffect, useRef, useState } from 'react' +import { Icon, Text } from '@vook-client/design-system' +import { motion } from 'framer-motion' + +import { BannerIcons } from '../Icons/index' + +import { + chromeExtensionContainer, + chromeExtensionFooter, + chromeExtensionHeader, + chromeExtensionTable, + chromeExtensionTableContainer, + chromeExtensionTableHeaderText, + deviceScreen, + deviceScreenHeader, + deviceScreenText, + deviceScreenURL, + deviceScreenURLHeader, + drag, + dragInner, + vookLogoContainer, +} from './DeviceScreen.css' + +const DragAnimation = () => { + return ( + + ) +} + +const ExtensionAnimation = ({ children }: PropsWithChildren) => ( + + {children} + +) + +const LogoAnimation = ({ children }: PropsWithChildren) => ( + + {children} + +) + +export const DeviceScreen = () => { + const [inView, setInView] = useState(false) + const ref = useRef(null) + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setInView(true) + } + }) + }, + { + threshold: 0.9, + }, + ) + + if (ref.current) { + observer.observe(ref.current) + } + + return () => { + if (ref.current) { + // eslint-disable-next-line react-hooks/exhaustive-deps + observer.unobserve(ref.current) + } + } + }, []) + + return ( +
+
+ +
+ +
+
+ + +
+ + + + +
+ +
+ + 가상화 기술은 현대 IT 인프라에서 중요한 역할을 하고 있습니다. + {'\n'} + {'\n'} + 서버 자원을 효율적으로 사용하여 비용을 절감할 수 있으며{'\n'} + 많은 기업들이{' '} +
+ {inView && } + 가상화 솔루션을 도입하여 +
{' '} + 운영 효율성을 극대화하고 있습니다. +
+
+ + {inView && ( +
+ + + + + +
+ + +
+
+
+ + 용어 + + + 동의어 + + + 뜻 + +
+
+ + 가상화 + + + Virtualization + + + 하나의 컴퓨터를 여러 개의 가상 컴퓨터처럼{'\n'} + 사용할 수 있도록 하는 기술 + +
+
+ +
+ + Vook 바로가기 + + +
+
+
+ )} +
+ ) +} diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/_components/index.ts b/apps/web/src/app/(landing)/_components/DetailBanner/_components/index.ts new file mode 100644 index 0000000..a85ede3 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/_components/index.ts @@ -0,0 +1 @@ +export { DeviceScreen } from './DeviceScreen' diff --git a/apps/web/src/app/(landing)/_components/DetailBanner/index.ts b/apps/web/src/app/(landing)/_components/DetailBanner/index.ts new file mode 100644 index 0000000..cb9df38 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/DetailBanner/index.ts @@ -0,0 +1 @@ +export { DetailBanner } from './DetailBanner' diff --git a/apps/web/src/app/(landing)/_components/Footer/Footer.css.ts b/apps/web/src/app/(landing)/_components/Footer/Footer.css.ts new file mode 100644 index 0000000..e61c098 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/Footer/Footer.css.ts @@ -0,0 +1,21 @@ +import { style } from '@vanilla-extract/css' + +export const footerContainer = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + gap: 32, + padding: 60, +}) + +export const flexBoxBetween = style({ + display: 'flex', + width: 1180, + justifyContent: 'space-between', +}) + +export const flexBox = style({ + display: 'flex', + alignItems: 'center', +}) diff --git a/apps/web/src/app/(landing)/_components/Footer/Footer.tsx b/apps/web/src/app/(landing)/_components/Footer/Footer.tsx new file mode 100644 index 0000000..8619653 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/Footer/Footer.tsx @@ -0,0 +1,50 @@ +import React from 'react' +import { Icon, Text, TypoLogo } from '@vook-client/design-system' +import Link from 'next/link' + +import { flexBox, flexBoxBetween, footerContainer } from './Footer.css' + +const Footer = () => { + return ( +
+
+ + + +
+ + 서비스이용약관 + + + + 개인정보처리방침 + + +
+
+
+
+ + 부크(Vook) + + + | + + + 이메일 vook.help@gmail.com + +
+
+ + + + + + +
+
+
+ ) +} + +export default Footer diff --git a/apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/TermHeader.tsx b/apps/web/src/app/(landing)/_components/Footer/index.ts similarity index 100% rename from apps/web/src/app/(afterLogin)/vocabulary/[id]/_component/term/TermHeader.tsx rename to apps/web/src/app/(landing)/_components/Footer/index.ts diff --git a/apps/web/src/app/(landing)/_components/HeroBanner/HeroBanner.css.ts b/apps/web/src/app/(landing)/_components/HeroBanner/HeroBanner.css.ts new file mode 100644 index 0000000..c000587 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/HeroBanner/HeroBanner.css.ts @@ -0,0 +1,60 @@ +import { keyframes, style } from '@vanilla-extract/css' + +export const heroBannerSection = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + marginBlock: 180, + marginBottom: 300, +}) + +export const heroTitle = style({ + display: 'flex', + marginBottom: 32, +}) + +export const subTitle = style({ + marginBottom: 60, +}) + +const draw = keyframes({ + '0%': { + transform: 'scaleX(0%)', + }, + '100%': { + transform: 'scaleX(100%)', + }, +}) + +export const highlightBox = style({ + position: 'relative', + width: 'fit-content', + height: 'fit-content', +}) + +export const yellowFont = style({ + color: '#FECA12', +}) + +export const yellowBlock = style({ + backgroundColor: '#FFF8D5', + width: 110, + animation: `${draw} 0.5s ease-in-out 1.5s forwards`, +}) + +export const blueBlock = style({ + backgroundColor: '#EFEFFC', + width: 154, + animation: `${draw} 0.5s ease-in-out 2s forwards`, +}) + +export const highlight = style({ + position: 'absolute', + left: -7, + height: 73, + borderRadius: 6, + zIndex: -1, + transformOrigin: 'left', + transform: 'scaleX(0%)', +}) diff --git a/apps/web/src/app/(landing)/_components/HeroBanner/HeroBanner.tsx b/apps/web/src/app/(landing)/_components/HeroBanner/HeroBanner.tsx new file mode 100644 index 0000000..c772856 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/HeroBanner/HeroBanner.tsx @@ -0,0 +1,74 @@ +import React from 'react' +import { Button, Text } from '@vook-client/design-system' +import clsx from 'clsx' +import Link from 'next/link' + +import { AppearBottom } from '@/components/AppearBottom' + +import { + blueBlock, + heroBannerSection, + heroTitle, + highlight, + highlightBox, + subTitle, + yellowBlock, + yellowFont, +} from './HeroBanner.css' + +export const HeroBanner = () => { + return ( +
+
+ + + IT 용어를 가장{' '} + + + +
+
+ + 쉽고{' '} + +
+ + +
+
+ + 빠르게{' '} + +
+ + + + 찾는 방법 + + +
+ +
+ + 용어집 관리부터 검색까지, 한 곳에서 해결하세요. + +
+
+ + + + + +
+ ) +} diff --git a/apps/web/src/app/(landing)/_components/HeroBanner/index.ts b/apps/web/src/app/(landing)/_components/HeroBanner/index.ts new file mode 100644 index 0000000..abf51bb --- /dev/null +++ b/apps/web/src/app/(landing)/_components/HeroBanner/index.ts @@ -0,0 +1 @@ +export { HeroBanner } from './HeroBanner' diff --git a/apps/web/src/app/(landing)/_components/IconBox/Card.tsx b/apps/web/src/app/(landing)/_components/IconBox/Card.tsx new file mode 100644 index 0000000..1c837bb --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconBox/Card.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import { Icon, Text } from '@vook-client/design-system' + +import { + CardContainer, + CardContainerFooter, + CardContainerHeader, + IconContainer, +} from '../DetailBanner/_components/CardSectoin.css' + +interface CardProps { + title?: string + date?: string +} + +export const Card = ({ + title = '비개발자를 위한 용어집', + date = '2024년 3월 17일 생성', +}: CardProps) => { + return ( +
+
+ + {title} + +
+
+ + {date} + +
+ +
+
+
+ ) +} diff --git a/apps/web/src/app/(landing)/_components/IconBox/IconBox.css.ts b/apps/web/src/app/(landing)/_components/IconBox/IconBox.css.ts new file mode 100644 index 0000000..056e570 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconBox/IconBox.css.ts @@ -0,0 +1,33 @@ +import { style, createVar, keyframes } from '@vanilla-extract/css' + +export const accentVar = createVar() + +const bounce = keyframes({ + '0%': { + transform: 'translateY(-80px)', + }, + '25%': { + transform: 'translateY(0)', + }, + '50%': { + transform: 'translateY(-80px)', + }, + '75%': { + transform: 'translateY(0)', + }, + '100%': { + transform: 'translateY(-80px)', + }, +}) + +export const IconBoxContainer = style({ + width: 120, + height: 120, + borderRadius: 10.55, + boxShadow: '0px 0px 4px rgba(0, 0, 0, 0.08), 0px 4px 8px rgba(0, 0, 0, 0.08)', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'inherit', + animation: `${bounce} 3s forwards`, +}) diff --git a/apps/web/src/app/(landing)/_components/IconBox/IconBox.tsx b/apps/web/src/app/(landing)/_components/IconBox/IconBox.tsx new file mode 100644 index 0000000..bd1fb4a --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconBox/IconBox.tsx @@ -0,0 +1,169 @@ +'use client' + +import { motion } from 'framer-motion' +import React from 'react' +import Image from 'next/image' + +import Notion from './assets/Notion.png' +import Jira from './assets/Jira.png' +import Excel from './assets/Excel.png' +import FileIcon from './assets/File.png' +import Folder from './assets/Folder.png' +import Pen from './assets/Pen.png' +import SpredadSheet from './assets/spredadSheet.png' +import { IconBoxContainer } from './IconBox.css' + +interface IconBoxProps { + name: keyof typeof IconProps +} + +const IconProps = { + notion: { + width: 41, + left: null, + right: 400, + y: 0, + height: 41, + delay: Math.random(), + reverse: false, + color: '#F2F2F2', + rotate: -10.71, + }, + jira: { + width: 78, + left: 170, + right: null, + y: 200, + height: 41, + delay: Math.random(), + reverse: true, + color: '#E5F0FF', + rotate: -30, + }, + excel: { + width: 96, + left: 300, + right: null, + y: 0, + height: 50, + delay: Math.random(), + reverse: false, + color: '#C9EEDD', + rotate: -22.71, + }, + file: { + width: 43, + left: null, + right: 200, + height: 47, + delay: Math.random(), + reverse: true, + color: '#CDCCF7', + y: 400, + rotate: 18.1, + }, + folder: { + width: 55, + left: undefined, + right: 100, + height: 55, + delay: Math.random(), + reverse: false, + y: 200, + color: '#FFFBE8', + rotate: 10.72, + }, + pen: { + width: 50, + left: 300, + right: null, + height: 50, + delay: Math.random(), + reverse: true, + color: '#EFEFFC', + y: 400, + rotate: -16.1, + }, + spredadSheet: { + width: 101, + left: 0, + y: 0, + right: 160, + height: 40, + delay: Math.random(), + reverse: false, + color: '#EFF4F1', + rotate: -22.71, + }, +} + +export const IconBox = ({ name }: IconBoxProps) => { + const icon = IconProps[name] + + const style = { + left: icon?.left ? icon?.left : undefined, + right: icon?.right ? icon?.right : undefined, + } + + const iconImage = { + notion: Notion, + jira: Jira, + excel: Excel, + file: FileIcon, + folder: Folder, + pen: Pen, + spredadSheet: SpredadSheet, + } + + return ( + + +
+ {`Icon +
+
+
+ ) +} diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/Excel.png b/apps/web/src/app/(landing)/_components/IconBox/assets/Excel.png new file mode 100644 index 0000000..d4053f1 Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/Excel.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/File.png b/apps/web/src/app/(landing)/_components/IconBox/assets/File.png new file mode 100644 index 0000000..501526d Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/File.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/Folder.png b/apps/web/src/app/(landing)/_components/IconBox/assets/Folder.png new file mode 100644 index 0000000..e3405dd Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/Folder.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/Jira.png b/apps/web/src/app/(landing)/_components/IconBox/assets/Jira.png new file mode 100644 index 0000000..b89e19c Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/Jira.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/Notion.png b/apps/web/src/app/(landing)/_components/IconBox/assets/Notion.png new file mode 100644 index 0000000..0b21a35 Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/Notion.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/Pen.png b/apps/web/src/app/(landing)/_components/IconBox/assets/Pen.png new file mode 100644 index 0000000..76ee0b5 Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/Pen.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/Star.png b/apps/web/src/app/(landing)/_components/IconBox/assets/Star.png new file mode 100644 index 0000000..3fc20ed Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/Star.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/assets/spredadSheet.png b/apps/web/src/app/(landing)/_components/IconBox/assets/spredadSheet.png new file mode 100644 index 0000000..7892894 Binary files /dev/null and b/apps/web/src/app/(landing)/_components/IconBox/assets/spredadSheet.png differ diff --git a/apps/web/src/app/(landing)/_components/IconBox/index.ts b/apps/web/src/app/(landing)/_components/IconBox/index.ts new file mode 100644 index 0000000..6aa3cca --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconBox/index.ts @@ -0,0 +1 @@ +export { IconBox } from './IconBox' diff --git a/apps/web/src/app/(landing)/_components/IconSection/IconSection.css.ts b/apps/web/src/app/(landing)/_components/IconSection/IconSection.css.ts new file mode 100644 index 0000000..b029c41 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconSection/IconSection.css.ts @@ -0,0 +1,50 @@ +import { style } from '@vanilla-extract/css' +import { vars } from '@vook-client/design-system' + +import { appearBottom } from '@/styles/animations.css' + +export const iconSection = style({ + position: 'relative', + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', +}) + +export const iconContainer = style({ + display: 'flex', + justifyContent: 'center', + + position: 'relative', + left: 0, + + width: 1700, + height: '100%', +}) + +export const starIcon = style({ + opacity: 0, + animation: `${appearBottom} 1s forwards`, +}) + +export const typoLogo = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + + position: 'relative', + + gap: '24px', + + transform: 'translateY(400px)', +}) + +export const typoHighlight = style({ + position: 'absolute', + bottom: -12, + + width: '100%', + height: 32, + backgroundColor: vars.colors.yellow, + zIndex: -1, +}) diff --git a/apps/web/src/app/(landing)/_components/IconSection/IconSection.tsx b/apps/web/src/app/(landing)/_components/IconSection/IconSection.tsx new file mode 100644 index 0000000..16ab63e --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconSection/IconSection.tsx @@ -0,0 +1,73 @@ +'use client' + +import { SymbolLogo, TypoLogo } from '@vook-client/design-system' + +import { IconBox } from '../IconBox' +import { IconSectionTitle } from '../IconSectionTitle' + +import { + iconContainer, + iconSection, + starIcon, + typoHighlight, + typoLogo, +} from './IconSection.css' + +interface StarIconProps { + left?: number + right?: number + top?: number + bottom?: number +} + +const StarIcon = ({ left, right, top, bottom }: StarIconProps) => ( + + + +) + +export const IconSection = () => { + return ( +
+
+ + + + + + + + + + + + +
+ +
+ +
+
+ +
+ ) +} diff --git a/apps/web/src/app/(landing)/_components/IconSection/index.ts b/apps/web/src/app/(landing)/_components/IconSection/index.ts new file mode 100644 index 0000000..db07854 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconSection/index.ts @@ -0,0 +1 @@ +export { IconSection } from './IconSection' diff --git a/apps/web/src/app/(landing)/_components/IconSectionTitle/IconSectionTitle.css.ts b/apps/web/src/app/(landing)/_components/IconSectionTitle/IconSectionTitle.css.ts new file mode 100644 index 0000000..26717a1 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconSectionTitle/IconSectionTitle.css.ts @@ -0,0 +1,33 @@ +import { keyframes, style } from '@vanilla-extract/css' + +export const iconTitle = style({ + position: 'absolute', + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + top: 150, +}) + +const drag = keyframes({ + '0%': { + transform: 'scaleX(0%)', + }, + '100%': { + transform: 'scaleX(100%)', + }, +}) + +export const dragBlock = style({ + position: 'absolute', + zIndex: -1, + opacity: 0.22, + backgroundColor: '#0077FF', + width: '99%', + height: 55, + top: -2, + left: 5, + transformOrigin: 'left', + transform: 'scaleX(0%)', + animation: `${drag} 0.5s ease-in-out forwards`, +}) diff --git a/apps/web/src/app/(landing)/_components/IconSectionTitle/IconSectionTitle.tsx b/apps/web/src/app/(landing)/_components/IconSectionTitle/IconSectionTitle.tsx new file mode 100644 index 0000000..8a6d34f --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconSectionTitle/IconSectionTitle.tsx @@ -0,0 +1,50 @@ +import { Text } from '@vook-client/design-system' +import { useInView } from 'framer-motion' +import { useRef } from 'react' + +import { dragBlock, iconTitle } from './IconSectionTitle.css' + +export const IconSectionTitle = () => { + const ref = useRef(null) + const isInView = useInView(ref) + + return ( + <> +
+ trigger +
+ {isInView && ( +
+ + 여기저기 흩어진 용어, 검색하는데 지치셨나요? + + + + 부크 + + 로 간편하게 관리하고 + +
드래그만으로 뜻을 확인 + + 하세요. + +
+ )} + + ) +} diff --git a/apps/web/src/app/(landing)/_components/IconSectionTitle/index.ts b/apps/web/src/app/(landing)/_components/IconSectionTitle/index.ts new file mode 100644 index 0000000..774e594 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/IconSectionTitle/index.ts @@ -0,0 +1 @@ +export { IconSectionTitle } from './IconSectionTitle' diff --git a/apps/web/src/app/(landing)/_components/RedirectBanner/RedirectBanner.css.ts b/apps/web/src/app/(landing)/_components/RedirectBanner/RedirectBanner.css.ts new file mode 100644 index 0000000..52adaec --- /dev/null +++ b/apps/web/src/app/(landing)/_components/RedirectBanner/RedirectBanner.css.ts @@ -0,0 +1,16 @@ +import { style } from '@vanilla-extract/css' +import { vars } from '@vook-client/design-system' + +import { FOOTER_HEIGHT } from '@/styles/layout' + +export const redirectBanner = style({ + marginTop: 160, + backgroundColor: vars.colors['palette-primary-50'], + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + gap: 48, + padding: 90, + marginBottom: FOOTER_HEIGHT, +}) diff --git a/apps/web/src/app/(landing)/_components/RedirectBanner/RedirectBanner.tsx b/apps/web/src/app/(landing)/_components/RedirectBanner/RedirectBanner.tsx new file mode 100644 index 0000000..843f7ea --- /dev/null +++ b/apps/web/src/app/(landing)/_components/RedirectBanner/RedirectBanner.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import { Button, Text } from '@vook-client/design-system' +import Link from 'next/link' + +import { redirectBanner } from './RedirectBanner.css' + +export const RedirectBanner = () => { + return ( +
+ + 나만의 용어집으로 IT 용어를 효율적으로 관리하세요 + + + + +
+ ) +} diff --git a/apps/web/src/app/(landing)/_components/RedirectBanner/index.ts b/apps/web/src/app/(landing)/_components/RedirectBanner/index.ts new file mode 100644 index 0000000..64513b6 --- /dev/null +++ b/apps/web/src/app/(landing)/_components/RedirectBanner/index.ts @@ -0,0 +1 @@ +export { RedirectBanner } from './RedirectBanner' diff --git a/apps/web/src/app/(landing)/layout.css.ts b/apps/web/src/app/(landing)/layout.css.ts new file mode 100644 index 0000000..0658e1e --- /dev/null +++ b/apps/web/src/app/(landing)/layout.css.ts @@ -0,0 +1,20 @@ +import { style } from '@vanilla-extract/css' + +import { HEADER_HEIGHT } from '@/styles/layout' + +export const landingOverlay = style({ + position: 'relative', + marginTop: HEADER_HEIGHT, +}) + +export const landingLayout = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + overflowX: 'hidden', +}) + +export const headerButtonContainer = style({ + display: 'flex', + gap: 10, +}) diff --git a/apps/web/src/app/(landing)/layout.tsx b/apps/web/src/app/(landing)/layout.tsx new file mode 100644 index 0000000..5b15133 --- /dev/null +++ b/apps/web/src/app/(landing)/layout.tsx @@ -0,0 +1,35 @@ +import { PropsWithChildren } from 'react' +import { Button } from '@vook-client/design-system' +import Link from 'next/link' + +import { Header } from '@/components/Header' +import { Footer } from '@/components/layout' + +import { + headerButtonContainer, + landingLayout, + landingOverlay, +} from './layout.css' + +const Layout = ({ children }: PropsWithChildren) => { + return ( +
+
+
+ + + + + + +
+
+
{children}
+
+
+ ) +} + +export default Layout diff --git a/apps/web/src/app/(landing)/page.tsx b/apps/web/src/app/(landing)/page.tsx new file mode 100644 index 0000000..d09ebc4 --- /dev/null +++ b/apps/web/src/app/(landing)/page.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +import { HeroBanner } from './_components/HeroBanner' +import { IconSection } from './_components/IconSection' +import { DetailBanner } from './_components/DetailBanner' +import { RedirectBanner } from './_components/RedirectBanner' + +const LandingPage = () => { + return ( +
+ + +
+ + +
+ ) +} + +export default LandingPage diff --git a/apps/web/src/app/(onboarding)/onboarding/job/page.css.ts b/apps/web/src/app/(onboarding)/onboarding/job/page.css.ts index fb2d349..e6bb38e 100644 --- a/apps/web/src/app/(onboarding)/onboarding/job/page.css.ts +++ b/apps/web/src/app/(onboarding)/onboarding/job/page.css.ts @@ -24,3 +24,7 @@ export const buttonGroup = style({ justifyContent: 'flex-end', gap: 16, }) + +export const skipButton = style({ + cursor: 'pointer', +}) diff --git a/apps/web/src/app/(onboarding)/onboarding/job/page.tsx b/apps/web/src/app/(onboarding)/onboarding/job/page.tsx index 42a510e..466bd4b 100644 --- a/apps/web/src/app/(onboarding)/onboarding/job/page.tsx +++ b/apps/web/src/app/(onboarding)/onboarding/job/page.tsx @@ -14,7 +14,7 @@ import { SelectBoxGroup } from '../_components/SelectBoxGroup' import { useOnBoarding } from '../_context/useOnboarding' import { OnboardingHeader } from '../_components/OnboardingHeader' -import { buttonGroup, header, jobGroup } from './page.css' +import { buttonGroup, header, jobGroup, skipButton } from './page.css' const JOBS: Array<{ icon: ButtonProps['prefixIcon'] @@ -69,7 +69,7 @@ const OnboardingJobPage = () => { }, { onSuccess: () => { - router.push('/') + router.push('/workspace') }, }, ) @@ -115,23 +115,30 @@ const OnboardingJobPage = () => {
- - 건너뛰기 - - + 건너뛰기 + + + +
) diff --git a/apps/web/src/components/AppearBottom/AppearBottom.tsx b/apps/web/src/components/AppearBottom/AppearBottom.tsx new file mode 100644 index 0000000..b0f3810 --- /dev/null +++ b/apps/web/src/components/AppearBottom/AppearBottom.tsx @@ -0,0 +1,31 @@ +'use client' + +import { motion } from 'framer-motion' +import { PropsWithChildren } from 'react' + +interface AppearBottomProps extends PropsWithChildren { + delay?: number +} + +export const AppearBottom = ({ children, delay }: AppearBottomProps) => { + return ( + + {children} + + ) +} diff --git a/apps/web/src/components/AppearBottom/index.ts b/apps/web/src/components/AppearBottom/index.ts new file mode 100644 index 0000000..2df541e --- /dev/null +++ b/apps/web/src/components/AppearBottom/index.ts @@ -0,0 +1 @@ +export { AppearBottom } from './AppearBottom' diff --git a/apps/web/src/components/DrawLeft/DrawLeft.tsx b/apps/web/src/components/DrawLeft/DrawLeft.tsx new file mode 100644 index 0000000..1c92b23 --- /dev/null +++ b/apps/web/src/components/DrawLeft/DrawLeft.tsx @@ -0,0 +1,33 @@ +'use client' + +import { motion } from 'framer-motion' +import { PropsWithChildren } from 'react' + +interface AppearBottomProps extends PropsWithChildren { + delay?: number +} + +export const DrawLeft = ({ children, delay }: AppearBottomProps) => { + return ( + + {children} + + ) +} diff --git a/apps/web/src/components/DrawLeft/index.ts b/apps/web/src/components/DrawLeft/index.ts new file mode 100644 index 0000000..d2b0494 --- /dev/null +++ b/apps/web/src/components/DrawLeft/index.ts @@ -0,0 +1 @@ +export { DrawLeft } from './DrawLeft' diff --git a/apps/web/src/components/Header/Header.css.ts b/apps/web/src/components/Header/Header.css.ts index 4536ae9..ea5adb2 100644 --- a/apps/web/src/components/Header/Header.css.ts +++ b/apps/web/src/components/Header/Header.css.ts @@ -4,10 +4,6 @@ import { vars } from '@vook-client/design-system' import { HEADER_HEIGHT } from '@/styles/layout' export const header = style({ - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - position: 'fixed', top: 0, left: 0, @@ -23,3 +19,18 @@ export const header = style({ backgroundColor: vars.colors['common-white'], zIndex: 100, }) + +export const headerInner = style({ + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + marginInline: 'auto', + height: '100%', + maxWidth: 1180, + width: '100%', + zIndex: 100, +}) + +export const headerInnerFull = style({ + maxWidth: '100%', +}) diff --git a/apps/web/src/components/Header/Header.tsx b/apps/web/src/components/Header/Header.tsx index 6484c50..cbf0288 100644 --- a/apps/web/src/components/Header/Header.tsx +++ b/apps/web/src/components/Header/Header.tsx @@ -1,21 +1,31 @@ import { TypoLogo } from '@vook-client/design-system' +import { PropsWithChildren } from 'react' +import clsx from 'clsx' import { Link } from '../Link' -import { SearchBox, SearchHistoryProvider } from '../SearchBox' -import { header } from './Header.css' +import { header, headerInner, headerInnerFull } from './Header.css' -export const Header = () => { +interface HeaderProps extends PropsWithChildren { + full?: boolean +} + +export const Header = ({ children, full = true }: HeaderProps) => { return (
-
- - - +
+
+ + + +
+ {children}
- - -
) } diff --git a/apps/web/src/components/Orchestration/Orchestration.tsx b/apps/web/src/components/Orchestration/Orchestration.tsx new file mode 100644 index 0000000..b6d1979 --- /dev/null +++ b/apps/web/src/components/Orchestration/Orchestration.tsx @@ -0,0 +1,27 @@ +import { motion, MotionProps } from 'framer-motion' +import { HTMLAttributes } from 'react' + +import { orchestrate, orchestrateFast } from '@/styles/motion' + +type Stagger = 'slow' | 'fast' + +type Props = { stagger?: Stagger } & HTMLAttributes & + MotionProps + +const Orchestration = ({ stagger, children, ...props }: Props) => { + if (stagger === 'fast') { + return ( + + {children} + + ) + } + + return ( + + {children} + + ) +} + +export default Orchestration diff --git a/apps/web/src/components/SearchBox/SearchBox.tsx b/apps/web/src/components/SearchBox/SearchBox.tsx index 4b18f95..1fedd71 100644 --- a/apps/web/src/components/SearchBox/SearchBox.tsx +++ b/apps/web/src/components/SearchBox/SearchBox.tsx @@ -65,7 +65,7 @@ export const SearchBox = () => { const searchQuery = useSearchQuery( { vocabularyUids: vocabulariesInfo.map((vocabulary) => vocabulary.uid), - query: searchValue, + queries: searchValue.split(' '), withFormat: true, highlightPreTag: '', highlightPostTag: '', diff --git a/apps/web/src/components/layout/Footer.tsx b/apps/web/src/components/layout/Footer.tsx index 7484c82..dc2c769 100644 --- a/apps/web/src/components/layout/Footer.tsx +++ b/apps/web/src/components/layout/Footer.tsx @@ -1,14 +1,15 @@ import React from 'react' -import { Icon } from '@vook-client/design-system' +import { Icon, Text } from '@vook-client/design-system' import { Hyperlink, Logo } from '../common/Common' import { flexAlignCenter, - flexEnd, footer, footerContainer, - footerLine, + footerEmail, + footerPolicy, + footerRow, inner, } from './Layout.css' @@ -27,12 +28,41 @@ export const Footer = () => (