diff --git a/package.json b/package.json index afba44da..0ba8c0a4 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "@vanilla-extract/sprinkles": "^1.6.1", "axios": "^1.6.2", "clsx": "^2.0.0", + "dayjs": "^1.11.10", + "ko": "link:dayjs/locale/ko", "framer-motion": "^10.18.0", "next": "14.0.3", "react": "^18", diff --git a/pages/write/index.tsx b/pages/write/index.tsx new file mode 100644 index 00000000..33cf2a37 --- /dev/null +++ b/pages/write/index.tsx @@ -0,0 +1,60 @@ +import WriteInput from '@components/Input/WriteInput'; +import WriteGuide from '@domain/Write/components/Guide'; +import WritePageTab from '@domain/Write/components/WritePageTab'; +import WriteHistory from '@domain/Write/History'; +import { type WriteHisotry } from '@domain/Write/types'; +import { useInput } from '@hooks/useInput'; + +const MOCK: WriteHisotry[] = [ + { + date: '2024-01-03', + history: [ + { createAt: '2024-01-03T01:01', id: '1', value: 'test 1' }, + { createAt: '2024-01-03T11:01', id: '2', value: 'test 2' }, + { + createAt: '2024-01-03T21:01', + id: '11', + value: + 'test 11test 11test 11test 11test 11test 11test 11test 11test 11test 11test 11test 11', + }, + { createAt: '2024-01-03T11:01', id: '21', value: 'test 21' }, + { createAt: '2024-01-03T21:01', id: '12', value: 'test 12' }, + { createAt: '2024-01-03T19:01', id: '22', value: 'test 22' }, + { createAt: '2024-01-03T23:01', id: '23', value: 'test 23' }, + ], + }, + { + date: '2024-01-04', + history: [ + { createAt: '2024-01-04T01:01', id: '3', value: 'test 3' }, + { createAt: '2024-01-04T01:01', id: '4', value: 'test 4' }, + { createAt: '2024-01-04T11:01', id: '7', value: 'test 7' }, + ], + }, + { + date: '2024-01-05', + history: [ + { createAt: '2024-01-05T11:01', id: '5', value: 'test 5' }, + { createAt: '2024-01-05T19:01', id: '6', value: 'test 6' }, + ], + }, +]; + +const WritePage = () => { + const writeInput = useInput({ id: 'write-input' }); + + return ( + + + + + + } + template={null} + /> + ); +}; + +export default WritePage; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e3b4a390..42363406 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,9 +29,15 @@ dependencies: clsx: specifier: ^2.0.0 version: 2.0.0 + dayjs: + specifier: ^1.11.10 + version: 1.11.10 framer-motion: specifier: ^10.18.0 version: 10.18.0(react-dom@18.2.0)(react@18.2.0) + ko: + specifier: link:dayjs/locale/ko + version: link:dayjs/locale/ko next: specifier: 14.0.3 version: 14.0.3(@babel/core@7.23.5)(react-dom@18.2.0)(react@18.2.0) @@ -6388,6 +6394,10 @@ packages: engines: {node: '>=8'} dev: true + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dev: false + /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: diff --git a/src/assets/icons/clock.svg b/src/assets/icons/clock.svg new file mode 100644 index 00000000..a8a085c6 --- /dev/null +++ b/src/assets/icons/clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Input/WriteInput/index.tsx b/src/components/Input/WriteInput/index.tsx index ba34fc6a..9fdbbb0d 100644 --- a/src/components/Input/WriteInput/index.tsx +++ b/src/components/Input/WriteInput/index.tsx @@ -30,6 +30,8 @@ const WriteInput = ({ lineBreak: {}, }); + const isValid = useMemo(() => value.length > 0, [value.length]); + const handleResize = (e: ChangeEvent) => { const { scrollHeight, clientHeight, value } = e.target; @@ -64,8 +66,6 @@ const WriteInput = ({ } }; - const isValid = useMemo(() => value.length > 0, [value.length]); - return (
) => { + return ( +
  • +

    + {dayjs(createAt).locale('ko').format('a h:mm')} +

    +

    {value}

    +
  • + ); +}; + +export default WriteHistoryCard; diff --git a/src/domain/Write/History/components/Card/style.css.ts b/src/domain/Write/History/components/Card/style.css.ts new file mode 100644 index 00000000..4e5a6983 --- /dev/null +++ b/src/domain/Write/History/components/Card/style.css.ts @@ -0,0 +1,30 @@ +import { style } from '@vanilla-extract/css'; + +import { sprinkles } from '@styles/sprinkles.css'; +import { COLORS } from '@styles/tokens'; + +export const container = style({ + backgroundColor: COLORS['Grey/100'], + borderRadius: '16px', + padding: '28px 32px', + height: 'fit-content', +}); + +export const date = style({ + marginBottom: '16px', + color: COLORS['Grey/400'], + fontSize: '15px', + fontWeight: '500', +}); + +export const value = style([ + sprinkles({ typography: '15/Body/Regular' }), + { + marginBottom: '16px', + color: COLORS['Grey/900'], + fontSize: '15px', + fontWeight: '400', + lineHeight: '24px', + letterSpacing: '-0.2px', + }, +]); diff --git a/src/domain/Write/History/components/Column/index.tsx b/src/domain/Write/History/components/Column/index.tsx new file mode 100644 index 00000000..10b049ea --- /dev/null +++ b/src/domain/Write/History/components/Column/index.tsx @@ -0,0 +1,24 @@ +import { type Write } from '@domain/Write/types'; + +import WriteHistoryCard from '../Card'; +import * as styles from './style.css'; + +interface ColumnProps { + list: Write[] | undefined; +} + +const Column = ({ list }: ColumnProps) => { + if (!list) { + return null; + } + + return ( +
      + {list.map((el) => ( + + ))} +
    + ); +}; + +export default Column; diff --git a/src/domain/Write/History/components/Column/style.css.ts b/src/domain/Write/History/components/Column/style.css.ts new file mode 100644 index 00000000..f1397b7e --- /dev/null +++ b/src/domain/Write/History/components/Column/style.css.ts @@ -0,0 +1,8 @@ +import { style } from '@vanilla-extract/css'; + +export const container = style({ + display: 'flex', + flexDirection: 'column', + gap: '16px', + flex: '1', +}); diff --git a/src/domain/Write/History/index.tsx b/src/domain/Write/History/index.tsx new file mode 100644 index 00000000..c6a901fb --- /dev/null +++ b/src/domain/Write/History/index.tsx @@ -0,0 +1,63 @@ +import dayjs from 'dayjs'; + +import 'dayjs/locale/ko'; + +import Icon from '@components/Icon'; + +import { type Write, type WriteHisotry } from '../types'; +import Column from './components/Column'; +import * as styles from './style.css'; + +interface WriteHistoryProps { + data: WriteHisotry[]; +} + +const WriteHistory = ({ data }: WriteHistoryProps) => { + const parser = (arr: Write[]): Write[][] => { + let queue1: Write[] = []; + let queue2: Write[] = []; + let queue3: Write[] = []; + + arr.forEach((history, i) => { + const extra = i % 3; + if (extra === 0) { + queue1.push(history); + } else if (extra === 1) { + queue2.push(history); + } else { + queue3.push(history); + } + }); + + return [queue1, queue2, queue3]; + }; + + return ( +
    + {data.map((writeHistory) => { + const { date, history } = writeHistory; + + return ( +
    +
    +
    + + + {dayjs(date).locale('ko').format('YYYY.MM.DD (dd)')} + +
    +
    + +
    + {parser(history).map((list, i) => { + return ; + })} +
    +
    + ); + })} +
    + ); +}; + +export default WriteHistory; diff --git a/src/domain/Write/History/style.css.ts b/src/domain/Write/History/style.css.ts new file mode 100644 index 00000000..cf937bf6 --- /dev/null +++ b/src/domain/Write/History/style.css.ts @@ -0,0 +1,43 @@ +import { style } from '@vanilla-extract/css'; + +import { COLORS } from '@styles/tokens'; + +export const container = style({ + marginBottom: '48px', + display: 'flex', + flexDirection: 'column', + gap: '64px', + maxHeight: '420px', + overflow: 'scroll', +}); + +export const dateLabelWrapper = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + marginTop: '12px', + marginBottom: '24px', +}); + +export const dateLabel = style({ + padding: '6px 28px', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + border: `1px solid ${COLORS['Grey/200']}`, + borderRadius: '100px', +}); + +export const dateLabelText = style({ + marginLeft: '6px', + color: COLORS['Grey/700'], + fontSize: '15px', + fontWeight: 500, + lineHeight: '24px', + letterSpacing: '-0.2px', +}); + +export const contentWrapper = style({ + display: 'flex', + gap: '16px', +}); diff --git a/src/domain/Write/components/Guide/index.tsx b/src/domain/Write/components/Guide/index.tsx new file mode 100644 index 00000000..675120b5 --- /dev/null +++ b/src/domain/Write/components/Guide/index.tsx @@ -0,0 +1,11 @@ +import * as styles from './style.css'; + +const WriteGuide = () => { + return ( +

    + 끄적인 글은 일주일 후에 사라져요! 오래 간직하고 싶다면 저장해주세요 😊 +

    + ); +}; + +export default WriteGuide; diff --git a/src/domain/Write/components/Guide/style.css.ts b/src/domain/Write/components/Guide/style.css.ts new file mode 100644 index 00000000..b882af68 --- /dev/null +++ b/src/domain/Write/components/Guide/style.css.ts @@ -0,0 +1,12 @@ +import { style } from '@vanilla-extract/css'; + +import { COLORS } from '@styles/tokens'; + +export const guideText = style({ + marginTop: '148px', + marginBottom: '12px', + color: COLORS['Grey/500'], + textAlign: 'center', + fontSize: '15px', + fontWeight: '500', +}); diff --git a/src/domain/Write/components/WritePageTab.tsx b/src/domain/Write/components/WritePageTab.tsx new file mode 100644 index 00000000..262aa00e --- /dev/null +++ b/src/domain/Write/components/WritePageTab.tsx @@ -0,0 +1,41 @@ +import { type ReactNode } from 'react'; + +import Tabs from '@components/Tabs'; + +import * as styles from './style.css'; + +interface WritePageTabProps { + write: ReactNode; + template: ReactNode; +} + +const WritePageTab = ({ write }: WritePageTabProps) => { + return ( + <> + +
    + + + 끄적이는 + + + 참고하는 + + +
    + +
    + {write} +
    +
    + + ); +}; + +export default WritePageTab; diff --git a/src/domain/Write/components/style.css.ts b/src/domain/Write/components/style.css.ts new file mode 100644 index 00000000..612f4b38 --- /dev/null +++ b/src/domain/Write/components/style.css.ts @@ -0,0 +1,6 @@ +import { style } from '@vanilla-extract/css'; + +export const header = style({ + display: 'flex', + justifyContent: 'center', +}); diff --git a/src/domain/Write/types/index.ts b/src/domain/Write/types/index.ts new file mode 100644 index 00000000..ee167fa0 --- /dev/null +++ b/src/domain/Write/types/index.ts @@ -0,0 +1,10 @@ +export interface Write { + id: string; + createAt: string; + value: string; +} + +export interface WriteHisotry { + date: string; + history: Write[]; +} diff --git a/src/feature/DomainA/components/example.tsx b/src/feature/DomainA/components/example.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/feature/DomainA/index.tsx b/src/feature/DomainA/index.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/feature/DomainA/utils/example.ts b/src/feature/DomainA/utils/example.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/feature/Example/components/example.tsx b/src/feature/Example/components/example.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/feature/Example/index.tsx b/src/feature/Example/index.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/src/feature/Example/utils/example.ts b/src/feature/Example/utils/example.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/styles/global.css.ts b/src/styles/global.css.ts index cf4a75d3..3c01df3a 100644 --- a/src/styles/global.css.ts +++ b/src/styles/global.css.ts @@ -22,6 +22,9 @@ globalStyle('body', { lineHeight: 1, WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale', + maxWidth: '1680px', + padding: '0 120px', + margin: '0 auto', }); globalStyle('h1, h2, h3, h4, h5, h6, p', { diff --git a/tsconfig.json b/tsconfig.json index a3d1a63b..10b4c8bd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,7 +20,7 @@ "@assets/*": ["./src/assets/*"], "@components/*": ["./src/components/*"], "@constants/*": ["./src/constants/*"], - "@feature/*": ["./src/feature/*"], + "@domain/*": ["./src/domain/*"], "@hooks/*": ["./src/hooks/*"], "@models/*": ["./src/models/*"], "@stores/*": ["./src/stores/*"],