From a3a1b325dd8fb292b5ba0bd8cd9ccfe50c6fedfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8C=E1=85=A5=E1=86=BC=E1=84=83=E1=85=A2=E1=84=8B?= =?UTF-8?q?=E1=85=B2=E1=86=AB?= Date: Fri, 5 Apr 2024 20:06:19 +0900 Subject: [PATCH] wip --- apps/web/package.json | 1 + apps/webextension/public/insp-empty.webp | Bin 0 -> 3460 bytes .../src/components/Thumbnails/Thumbnails.tsx | 34 ++ .../src/components/Thumbnails/index.tsx | 1 + .../src/components/Thumbnails/mock.ts | 532 ++++++++++++++++++ apps/webextension/src/pages/popup/App.tsx | 2 + .../pages/popup/hooks/useGetInspiration.ts | 3 + packages/api/src/types/member.ts | 1 + packages/api/src/types/tag.ts | 2 +- packages/constants/src/assets.ts | 15 + packages/constants/src/index.ts | 1 + packages/hooks/src/index.ts | 1 + packages/hooks/src/useOpenGraphImage/index.ts | 1 + .../useOpenGraphImage/useOpenGraphImage.ts | 30 + .../src/components/BottomSheetModal.tsx | 2 +- .../src/components/Thumbnail.tsx | 124 ++++ .../src/components/ThumbnailContent.tsx | 90 +++ packages/ui-components/src/index.ts | 1 + packages/ui-components/src/types/auth.ts | 15 + packages/ui-components/src/types/index.ts | 0 .../ui-components/src/types/inspiration.ts | 25 + packages/ui-components/src/types/member.ts | 8 + .../ui-components/src/types/pagination.ts | 17 + packages/ui-components/src/types/tag.ts | 12 + packages/ui-styles/src/index.ts | 2 +- packages/ui-styles/src/utils/index.ts | 1 + .../src/utils/selectRandomColor/index.ts | 1 + .../selectRandomColor/selectRandomColor.ts | 10 + pnpm-lock.yaml | 3 + 29 files changed, 932 insertions(+), 3 deletions(-) create mode 100644 apps/webextension/public/insp-empty.webp create mode 100644 apps/webextension/src/components/Thumbnails/Thumbnails.tsx create mode 100644 apps/webextension/src/components/Thumbnails/index.tsx create mode 100644 apps/webextension/src/components/Thumbnails/mock.ts create mode 100644 apps/webextension/src/pages/popup/hooks/useGetInspiration.ts create mode 100644 packages/constants/src/assets.ts create mode 100644 packages/hooks/src/useOpenGraphImage/index.ts create mode 100644 packages/hooks/src/useOpenGraphImage/useOpenGraphImage.ts create mode 100644 packages/ui-components/src/components/Thumbnail.tsx create mode 100644 packages/ui-components/src/components/ThumbnailContent.tsx create mode 100644 packages/ui-components/src/types/auth.ts create mode 100644 packages/ui-components/src/types/index.ts create mode 100644 packages/ui-components/src/types/inspiration.ts create mode 100644 packages/ui-components/src/types/member.ts create mode 100644 packages/ui-components/src/types/pagination.ts create mode 100644 packages/ui-components/src/types/tag.ts create mode 100644 packages/ui-styles/src/utils/selectRandomColor/index.ts create mode 100644 packages/ui-styles/src/utils/selectRandomColor/selectRandomColor.ts diff --git a/apps/web/package.json b/apps/web/package.json index e8d0c172..7682cbeb 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -17,6 +17,7 @@ "@tanstack/react-query": "5.18.1", "@ygtang/api": "workspace:^", "@ygtang/constants": "workspace:*", + "@ygtang/hooks": "workspace:*", "@ygtang/http": "workspace:^", "@ygtang/ui-components": "workspace:*", "@ygtang/ui-styles": "workspace:*", diff --git a/apps/webextension/public/insp-empty.webp b/apps/webextension/public/insp-empty.webp new file mode 100644 index 0000000000000000000000000000000000000000..d12ab9fc98eff274bf24c92e1711104fe53d318e GIT binary patch literal 3460 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 J-)a4~`zI97C* literal 0 HcmV?d00001 diff --git a/apps/webextension/src/components/Thumbnails/Thumbnails.tsx b/apps/webextension/src/components/Thumbnails/Thumbnails.tsx new file mode 100644 index 00000000..1bc755c2 --- /dev/null +++ b/apps/webextension/src/components/Thumbnails/Thumbnails.tsx @@ -0,0 +1,34 @@ +import { css } from "@emotion/react"; +import { InspirationType } from "@ygtang/api"; +import { Thumbnail } from "@ygtang/ui-components"; + +import { XXX } from "./mock"; + +export default function Thumbnails() { + return ( +
+ {XXX.map( + ({ id, type, content, openGraphResponse, memo, tagResponses }) => ( + + ), + )} +
+ ); +} + +const thumbnailWrapperCss = css` + width: 100%; + padding-top: 16px; + padding-bottom: 5px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; +`; diff --git a/apps/webextension/src/components/Thumbnails/index.tsx b/apps/webextension/src/components/Thumbnails/index.tsx new file mode 100644 index 00000000..00e8fc4f --- /dev/null +++ b/apps/webextension/src/components/Thumbnails/index.tsx @@ -0,0 +1 @@ +export { default } from "./Thumbnails"; diff --git a/apps/webextension/src/components/Thumbnails/mock.ts b/apps/webextension/src/components/Thumbnails/mock.ts new file mode 100644 index 00000000..452731de --- /dev/null +++ b/apps/webextension/src/components/Thumbnails/mock.ts @@ -0,0 +1,532 @@ +import { InspirationInterface } from "@ygtang/api"; + +export const XXX: InspirationInterface[] = [ + { + id: 8048, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [ + { + id: 597, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "3123123132", + createdDatetime: "2022-06-05 23:36:53", + updatedDatetime: "2022-06-05 23:36:53", + }, + { + id: 1295, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "아아아아ㅇㅇㅇ", + createdDatetime: "2022-08-26 02:42:28", + updatedDatetime: "2022-08-26 02:42:28", + }, + { + id: 2448, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "ㅍㅍㅇㄴㄴㅌㅊㅌㅇㄴ", + createdDatetime: "2023-02-09 03:56:43", + updatedDatetime: "2023-02-09 03:56:43", + }, + { + id: 2447, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "ㅊㅊㄴㅌㅌㅌ", + createdDatetime: "2023-02-09 03:56:40", + updatedDatetime: "2023-02-09 03:56:40", + }, + { + id: 4876, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "로 ㄹㅎㅍ", + createdDatetime: "2024-02-21 11:48:26", + updatedDatetime: "2024-02-21 11:48:26", + }, + ], + type: "IMAGE", + content: + "https://s3.ap-northeast-2.amazonaws.com/ygt-bucket-2023/upload/4e39f31d-5b0d-4fcf-ae2d-5de7ae1ce9dd.png", + memo: "ㅋㅌㅊ", + openGraphResponse: { + code: 500, + description: null, + siteName: null, + title: null, + url: null, + image: null, + }, + createdDatetime: "2024-02-21 11:48:34", + updatedDatetime: "2024-02-21 11:48:34", + }, + { + id: 6130, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [ + { + id: 289, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "인과관계", + createdDatetime: "2022-05-13 23:49:42", + updatedDatetime: "2022-05-13 23:49:42", + }, + { + id: 597, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "3123123132", + createdDatetime: "2022-06-05 23:36:53", + updatedDatetime: "2022-06-05 23:36:53", + }, + { + id: 599, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "fsadfdsfsd", + createdDatetime: "2022-06-05 23:37:30", + updatedDatetime: "2022-06-05 23:37:30", + }, + { + id: 1295, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "아아아아ㅇㅇㅇ", + createdDatetime: "2022-08-26 02:42:28", + updatedDatetime: "2022-08-26 02:42:28", + }, + { + id: 2448, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "ㅍㅍㅇㄴㄴㅌㅊㅌㅇㄴ", + createdDatetime: "2023-02-09 03:56:43", + updatedDatetime: "2023-02-09 03:56:43", + }, + { + id: 2705, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "ㅗㅓㅓ", + createdDatetime: "2023-02-15 15:17:06", + updatedDatetime: "2023-02-15 15:17:06", + }, + { + id: 2447, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "ㅊㅊㄴㅌㅌㅌ", + createdDatetime: "2023-02-09 03:56:40", + updatedDatetime: "2023-02-09 03:56:40", + }, + ], + type: "LINK", + content: "https://github.com/depromeet/ygtang-client/pull/388", + memo: "32131223", + openGraphResponse: { + code: 200, + description: + "⛳️작업 내용\n\n\n링크 썸네일이 간혈적으로 보이지 않는 문제를 해결했어요\n\nog state 갱신을 didUpdate > didMount로 수정했어요 f8f8ec4\n\n\n\n국지적으로 사용되던 OpenGraph interface를 OpenGraphResponse로 대체했어요\n\n전체적으로 서버 리스폰스 인터페이스를 따르는 것이 변경에 유연하게 대처할 수 있는...", + siteName: null, + title: + "링크 썸네일 간혈적으로 보이지 않는 문제, OpenGraphResponse 적용 by hyesungoh · Pull Request #388 · depromeet/ygtang-client", + url: "https://github.com/depromeet/ygtang-client/pull/388", + image: + "https://opengraph.githubassets.com/a6822aaeebb5eeee5ba315c68a1bf6d388c02fd15c987b7b5b42ebd2a5890c83/depromeet/ygtang-client/pull/388", + }, + createdDatetime: "2023-07-23 19:59:41", + updatedDatetime: "2024-01-07 22:27:34", + }, + { + id: 4781, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [ + { + id: 599, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "fsadfdsfsd", + createdDatetime: "2022-06-05 23:37:30", + updatedDatetime: "2022-06-05 23:37:30", + }, + { + id: 1295, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "아아아아ㅇㅇㅇ", + createdDatetime: "2022-08-26 02:42:28", + updatedDatetime: "2022-08-26 02:42:28", + }, + ], + type: "LINK", + content: "https://dddabf98.ygt.pages.dev/onboard", + memo: "", + openGraphResponse: { + code: 200, + description: null, + siteName: null, + title: "", + url: "https://dddabf98.ygt.pages.dev/onboard", + image: null, + }, + createdDatetime: "2023-03-31 02:13:04", + updatedDatetime: "2023-03-31 02:13:04", + }, + { + id: 4556, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [ + { + id: 272, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "희소성", + createdDatetime: "2022-05-13 23:46:05", + updatedDatetime: "2022-05-13 23:46:05", + }, + { + id: 289, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "인과관계", + createdDatetime: "2022-05-13 23:49:42", + updatedDatetime: "2022-05-13 23:49:42", + }, + ], + type: "LINK", + content: + "https://blog.bitsrc.io/understand-the-most-reliable-frontend-architecture-c8578e3166b", + memo: "", + openGraphResponse: { + code: 500, + description: null, + siteName: null, + title: null, + url: null, + image: null, + }, + createdDatetime: "2023-03-16 17:17:38", + updatedDatetime: "2023-03-16 17:17:38", + }, + { + id: 4067, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [ + { + id: 1579, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "코딩테스트", + createdDatetime: "2022-10-18 01:16:53", + updatedDatetime: "2022-10-18 01:16:53", + }, + { + id: 2448, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "ㅍㅍㅇㄴㄴㅌㅊㅌㅇㄴ", + createdDatetime: "2023-02-09 03:56:43", + updatedDatetime: "2023-02-09 03:56:43", + }, + ], + type: "LINK", + content: + "https://anthonyhobday.com/sideprojects/saferules/?utm_source=Nomad Academy", + memo: "", + openGraphResponse: { + code: 200, + description: null, + siteName: null, + title: "Visual design rules you can safely follow every time", + url: "https://anthonyhobday.com/sideprojects/saferules/?utm_source=Nomad Academy", + image: null, + }, + createdDatetime: "2023-03-03 17:05:37", + updatedDatetime: "2023-03-03 17:05:37", + }, + { + id: 4048, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [], + type: "LINK", + content: "https://product.29cm.co.kr/catalog/648418", + memo: "가방 살까말까..", + openGraphResponse: { + code: 200, + description: + '블랭코브(BLANKOF) BS 02-2A DAYPACK 26 (BLACK). <시즌정보>\nSEASONLESS\n\n<상세정보>\n규격 : 26L 가로33 세로45 깊이18\n타입 : 1WAY (백팩)\n수납 : LAPTOP 15"\n가공 : 초발수가공 (DWR) / 방수가공 (Laminating)\n겉감 : NYLON 100% (ROOTSCOPE® Original)\n안감 : NYLON 100%\n지퍼 : YKK® AquaGuard®\n보증 : 제품 자체 결함 시 무상보증기간 100개월 (이후 유상 서비스)\n\n1일 치 용량의 수납이 가능하게 설계된 데이팩으로 내구성 및 유틸리티 기능을 강화하여 출시하였습니다.\n\n랩톱 수납공간을 따로 분리하여 15인치 랩톱 PC도 여유롭게 보관할 수 있게 하였으며, 전면부 포켓은 목적에 따라 소지품 보관을 따로 분류할 수 있도록 양분화 하였습니다.\n\n원단은 수년간 연구로 직접 개발하여 제작한 ROOTSCOPE® GIM 는 솔라 트윌 조직의 나일론 원단으로 바스락 거리는 터치감과 가볍지만 견고한 것이 특징입니다. DWR 가공과 래미네이팅 후가공된 3 Layer 원단 및 YKK® AquaGuard 지퍼를 사용하여 생활 발수 및 방수에 알맞게 제작되었습니다.\n\n* 가방이 무거워져도 견고함을 더해주는 체스트 스트랩과 싱글 웹 스트랩 제품과 같이 사용할 수 있습니다. (별도 구매)', + siteName: null, + title: "BS 02-2A DAYPACK 26 (BLACK) - 감도 깊은 취향 셀렉트샵 29CM", + url: "https://product.29cm.co.kr/catalog/648418", + image: + "https://img.29cm.co.kr/next-product/2021/11/25/50c3b1e70efb48698915b5f6dbee7fd4_20211125163624.jpg?width=1200", + }, + createdDatetime: "2023-03-02 20:34:02", + updatedDatetime: "2023-03-02 20:34:02", + }, + { + id: 4047, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [ + { + id: 272, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + content: "희소성", + createdDatetime: "2022-05-13 23:46:05", + updatedDatetime: "2022-05-13 23:46:05", + }, + ], + type: "LINK", + content: "https://product.29cm.co.kr/catalog/1929818", + memo: "라지 사이즈", + openGraphResponse: { + code: 200, + description: + '더 레스큐(THE RESQ) CHAMBRAY TEDDY SHIRT [INDIGO].

[THE RESQ]의 시그니처 유틸리티 워크 셔츠인 \'Teddy Shirt\' 입니다.



빈티지하면서 탄탄한 밀도감을 지닌 20수 인디고 코튼 샴브레이 원단으로 제작하였고,

편한 착용감과 자연스러운 실루엣을 지닌 여유있는 패턴으로 설계하였습니다.



이너 및 단품으로 범용성있게 활용할 수 있도록 셔츠의 밑단의 곡을 완만하게 디자인하였고,

옆솔기 선 하단은 빈티지한 무드를 지닌 거셋 디테일로 보강하였습니다.



스마트한 구조를 지닌 테디셔츠 고유의 레이어드 포켓은 3개의 실용적인 수납 공간을 제공하며,

소매에 보강된 엘보우 패치 디테일로 더 튼튼하게 오래 입을 수 있도록 하였습니다.



자연스러운 실루엣과 퍼커링이 특징인 더블 스티치 기법으로 봉제하였고,

각 부속의 접합부는 바택(Bar Tack)처리하여 튼튼하게 보강하였습니다.



완성 후 가먼트 워싱 처리를 한 Sanforized(방축가공) 상태로 세탁 후 변형을 최소화하였습니다.





ㆍ실측 사이즈(cm)

- M : 어깨 52 / 가슴 61 / 소매기장 61 / 총기장 76

- L : 어깨 53 / 가슴 63 / 소매 62 / 총기장 77

- XL : 어깨 54 / 가슴 65 / 소매 63 / 총기장 78

* 실측방법에 따라 오차 1~2cm 정도 발생할 수 있으니 참고 부탁드립니다.



ㆍ소재

- Cotton 100%, Natural Nut Buttons



ㆍ단독 세탁, 세탁기 가능, 찬물 세탁, 그늘에 건조

* 인디고 염료로 인해 이염의 우려가 있으므로 착용 초기에는 단독 세탁을 권장드립니다.



', + siteName: null, + title: "CHAMBRAY TEDDY SHIRT [INDIGO] - 감도 깊은 취향 셀렉트샵 29CM", + url: "https://product.29cm.co.kr/catalog/1929818", + image: + "https://img.29cm.co.kr/item/202403/11eee27b3b4d23bc9a76a3a9e4bb9943.jpg?width=1200", + }, + createdDatetime: "2023-03-02 20:33:31", + updatedDatetime: "2023-03-02 20:33:31", + }, + { + id: 3264, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [], + type: "LINK", + content: + "https://blog.bitsrc.io/how-to-manage-react-states-like-a-pro-4127cf7df5e0", + memo: "", + openGraphResponse: { + code: 200, + description: + "The “secret” behind excellent state management is understanding how…", + siteName: null, + title: "How To Manage React States Like A Pro", + url: "https://blog.bitsrc.io/how-to-manage-react-states-like-a-pro-4127cf7df5e0", + image: + "https://miro.medium.com/v2/da:true/resize:fit:1200/0*Fah-PFsd1Bi-WIH2", + }, + createdDatetime: "2023-02-08 04:03:30", + updatedDatetime: "2023-02-08 04:03:30", + }, + { + id: 3261, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [], + type: "LINK", + content: + "https://junghan92.medium.com/%EB%B2%88%EC%97%AD-create-react-app-%EA%B6%8C%EC%9E%A5%EC%9D%84-vite%EB%A1%9C-%EB%8C%80%EC%B2%B4-pr-%EB%8C%80%ED%95%9C-dan-abramov%EC%9D%98-%EB%8B%B5%EB%B3%80-3050b5678ac8", + memo: "fafds", + openGraphResponse: { + code: 500, + description: null, + siteName: null, + title: null, + url: null, + image: null, + }, + createdDatetime: "2023-02-08 02:28:31", + updatedDatetime: "2023-02-08 02:28:31", + }, + { + id: 2848, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [], + type: "LINK", + content: "https://adecade.co.kr/product/liberty-pants-black/382/", + memo: "", + openGraphResponse: { + code: 200, + description: + "Fabric Info Wool 8% Poly 70% Rayon 19% Polyurethane 3% Detail *Side Seam *Pleats Made in Korea 서스테인의 오리지널리티 팬츠를 바탕으로 디자인된 트라우져입니다. 절개 부분의 디테일은 살리고 입었을 때 필요한 실루엣은 더 깔끔하게 잡아서 재해석된 팬츠입니", + siteName: null, + title: "Liberty Pants Black - A.DECADE", + url: "https://adecade.co.kr/product/liberty-pants-black/382/", + image: + "https://adecade.co.kr/web/product/big/202211/9bcb3fffec5e22e070a0cdfeb0505998.jpg", + }, + createdDatetime: "2023-01-28 00:34:02", + updatedDatetime: "2023-01-28 00:34:02", + }, + { + id: 2847, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [], + type: "LINK", + content: "https://adecade.co.kr/product/liberty-pants-charcoal/383/", + memo: "", + openGraphResponse: { + code: 200, + description: + "Fabric Info Wool 8% Poly 70% Rayon 19% Polyurethane 3% Detail *Side Seam *Pleats Made in Korea 서스테인의 오리지널리티 팬츠를 바탕으로 디자인된 트라우져입니다. 절개 부분의 디테일은 살리고 입었을 때 필요한 실루엣은 더 깔끔하게 잡아서 재해석된 팬츠입니", + siteName: null, + title: "Liberty Pants Charcoal - A.DECADE", + url: "https://adecade.co.kr/product/liberty-pants-charcoal/383/", + image: + "https://adecade.co.kr/web/product/big/202211/28a22e633d8df2bf8cef4a2a90780ee5.jpg", + }, + createdDatetime: "2023-01-28 00:33:50", + updatedDatetime: "2023-01-28 00:33:50", + }, + { + id: 2755, + memberResponse: { + id: 9, + nickName: "머유니버스", + email: "meoyooniverse@gmail.com", + createdDatetime: "2022-05-13 19:52:58", + }, + tagResponses: [], + type: "LINK", + content: "https://www.instagram.com/p/Cir3hyvP3cu/?igshid=YmMyMTA2M2Y=", + memo: "", + openGraphResponse: { + code: 200, + description: null, + siteName: null, + title: "Instagram", + url: "https://www.instagram.com/p/Cir3hyvP3cu/?igshid=YmMyMTA2M2Y=", + image: null, + }, + createdDatetime: "2023-01-10 00:55:32", + updatedDatetime: "2023-01-10 00:55:32", + }, +]; diff --git a/apps/webextension/src/pages/popup/App.tsx b/apps/webextension/src/pages/popup/App.tsx index 4a72dc89..1b01a6b0 100644 --- a/apps/webextension/src/pages/popup/App.tsx +++ b/apps/webextension/src/pages/popup/App.tsx @@ -6,6 +6,7 @@ import { useTheme, YgtangTheme } from "@ygtang/ui-styles"; import logo from "~/assets/img/logo.svg"; import NavigationBar from "~/components/NavigationBar"; +import Thumbnails from "~/components/Thumbnails"; import { useUserData } from "./hooks/useUserData"; @@ -83,6 +84,7 @@ export function PopupApp() { 영감탱으로 이동 + ); diff --git a/apps/webextension/src/pages/popup/hooks/useGetInspiration.ts b/apps/webextension/src/pages/popup/hooks/useGetInspiration.ts new file mode 100644 index 00000000..ab1e9c4b --- /dev/null +++ b/apps/webextension/src/pages/popup/hooks/useGetInspiration.ts @@ -0,0 +1,3 @@ +export function useGetInspiration() { + return {}; +} diff --git a/packages/api/src/types/member.ts b/packages/api/src/types/member.ts index 60697ba3..b556e1a1 100644 --- a/packages/api/src/types/member.ts +++ b/packages/api/src/types/member.ts @@ -2,6 +2,7 @@ export interface MemberResponseInterface { id: number; nickName: string; email: string; + createdDatetime?: string; } export type UserInformationType = Omit; diff --git a/packages/api/src/types/tag.ts b/packages/api/src/types/tag.ts index 6e80e00c..8b5b11f9 100644 --- a/packages/api/src/types/tag.ts +++ b/packages/api/src/types/tag.ts @@ -2,7 +2,7 @@ import { MemberResponseInterface } from "./member"; export interface TagInterface { id: number; - count: number; + count?: number; memberResponse: MemberResponseInterface; content: string; createdDatetime: string; diff --git a/packages/constants/src/assets.ts b/packages/constants/src/assets.ts new file mode 100644 index 00000000..ba7dbb0a --- /dev/null +++ b/packages/constants/src/assets.ts @@ -0,0 +1,15 @@ +export const INSPIRATION_EMPTY_IMAGE_SRC = '/insp-empty.webp'; +export const INSPIRATION_EMPTY_TEXT_IMAGE_SRC = '/InspirationEmptyText.png'; +export const USER_PROFILE_IMAGE_SRC = '/UserProfile.png'; + +export const INSPIRATION_MODAL_IMAGE = { + 1: '/modal_characters/1.png', + 2: '/modal_characters/2.png', + 3: '/modal_characters/3.png', +}; + +export const ONBOARD_IMAGE = [ + '/onboard_images/onboard_1.png', + '/onboard_images/onboard_2.png', + '/onboard_images/onboard_3.png', +] as const; diff --git a/packages/constants/src/index.ts b/packages/constants/src/index.ts index 98aa2ae6..158cd982 100644 --- a/packages/constants/src/index.ts +++ b/packages/constants/src/index.ts @@ -16,3 +16,4 @@ export { staggerOne, } from "./motions"; export { sessionStorageRedirectKey } from "./sessionStorage"; +export { INSPIRATION_EMPTY_IMAGE_SRC } from './assets' \ No newline at end of file diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 8f5492ba..4d5bfd4d 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -5,3 +5,4 @@ export { usePreventScroll } from "./usePreventScroll"; export { useToggle } from "./useToggle"; export { useUserAgent } from "./useUserAgent"; export { useWindowSize } from "./useWindowSize"; +export { useOpenGraphImage } from './useOpenGraphImage' \ No newline at end of file diff --git a/packages/hooks/src/useOpenGraphImage/index.ts b/packages/hooks/src/useOpenGraphImage/index.ts new file mode 100644 index 00000000..a5272ec1 --- /dev/null +++ b/packages/hooks/src/useOpenGraphImage/index.ts @@ -0,0 +1 @@ +export { default as useOpenGraphImage } from './useOpenGraphImage'; diff --git a/packages/hooks/src/useOpenGraphImage/useOpenGraphImage.ts b/packages/hooks/src/useOpenGraphImage/useOpenGraphImage.ts new file mode 100644 index 00000000..e585fac5 --- /dev/null +++ b/packages/hooks/src/useOpenGraphImage/useOpenGraphImage.ts @@ -0,0 +1,30 @@ +import { SyntheticEvent, useEffect, useState } from 'react'; + +interface UseOpenGraphImageProps { + url: string | undefined | null; + image: string | undefined | null; +} + +export default function useOpenGraphImage({ url, image }: UseOpenGraphImageProps) { + const [src, setSrc] = useState(url && image ? url + image : ''); + + useEffect(() => { + // NOTE: initial state를 og.url + og.image로 한 이유는 + // og.image가 안되는 경우가 상대주소로 작성이 되어 있어 영감탱 서버에 요청하기 때문 + if (url && image) { + setSrc(url + image); + } else if (image) { + setSrc(image); + } + }, [image, url]); + + const onImageError = (e: SyntheticEvent) => { + if (!image) return; + + // NOTE: 두번째로 시도하는 og.image에서도 에러를 발생할 경우 + if (e.currentTarget.src === image) return; + setSrc(image); + }; + + return { src, onImageError }; +} diff --git a/packages/ui-components/src/components/BottomSheetModal.tsx b/packages/ui-components/src/components/BottomSheetModal.tsx index 6e0eefc1..1b690962 100644 --- a/packages/ui-components/src/components/BottomSheetModal.tsx +++ b/packages/ui-components/src/components/BottomSheetModal.tsx @@ -5,7 +5,7 @@ import { usePreventScroll } from "@ygtang/hooks"; import { motion, Variants } from "framer-motion"; import { dimBackdropCss } from "../shared/styles"; -import PortalWrapper from "./PortalWrapper"; +import { PortalWrapper } from ".."; export interface BottomSheetModalProps { isShowing: boolean; diff --git a/packages/ui-components/src/components/Thumbnail.tsx b/packages/ui-components/src/components/Thumbnail.tsx new file mode 100644 index 00000000..b379d7b2 --- /dev/null +++ b/packages/ui-components/src/components/Thumbnail.tsx @@ -0,0 +1,124 @@ +import { memo } from "react"; +import { css, Theme } from "@emotion/react"; +import { selectRandomColor } from "@ygtang/ui-styles"; + +import { InspirationInterface, OpenGraphResponse } from "../types/inspiration"; +import ThumbnailContent from "./ThumbnailContent"; + +export interface ContentThumbnailProps + extends Pick { + tags: InspirationInterface["tagResponses"]; + openGraph?: OpenGraphResponse; + memo: InspirationInterface["memo"]; +} + +function Thumbnail({ + id, + type, + tags, + content, + openGraph, +}: ContentThumbnailProps) { + const moveToInspirationView = (id: number) => {}; + + return ( +
+
+
moveToInspirationView(id)}> + +
+ + +
+
+ ); +} + +export default memo(Thumbnail); + +const wrapperCss = (theme: Theme) => css` + max-width: 100%; + aspect-ratio: 1; + overflow: hidden; + color: ${theme.color.background}; + background-color: ${selectRandomColor(theme, ["gray03", "gray04", "gray05"])}; + border-radius: ${theme.borderRadius.outer}; + + @supports not (aspect-ratio: 1) { + position: relative; + + &::before { + content: ""; + float: left; + padding-top: 100%; + } + &::after { + content: ""; + display: block; + clear: both; + } + } +`; + +const supportAspectRatioWrapperCss = css` + width: 100%; + height: 100%; + padding: 6px; + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 6px; + + @supports not (aspect-ratio: 1) { + position: absolute; + top: 0; + left: 0; + } +`; + +const contentWrapperCss = (theme: Theme) => css` + width: 100%; + height: 100%; + overflow: hidden; + border-radius: ${theme.borderRadius.default}; +`; + +function Tags({ tags }: Pick) { + if (tags && tags.length > 0) + return ( +
+ {tags.map((eachTag) => ( + + #{eachTag.content} + + ))} +
+ ); + + return null; +} + +const tagWrapperCss = css` + height: 16px; + flex-shrink: 0; + display: flex; + align-items: center; + gap: 2px; + overflow-x: scroll; + overflow-y: hidden; +`; + +const tagCss = (theme: Theme) => css` + height: 100%; + padding: 2px 4px; + background-color: ${theme.color.dim02}; + border-radius: ${theme.borderRadius.default}; + font-weight: ${theme.font.weight.medium}; + font-size: 10px; + line-height: 1.2; + white-space: nowrap; +`; diff --git a/packages/ui-components/src/components/ThumbnailContent.tsx b/packages/ui-components/src/components/ThumbnailContent.tsx new file mode 100644 index 00000000..7d4f33c5 --- /dev/null +++ b/packages/ui-components/src/components/ThumbnailContent.tsx @@ -0,0 +1,90 @@ +import { useEffect, useState } from 'react'; +import { css, Theme } from '@emotion/react'; + +import { ContentThumbnailProps } from './Thumbnail'; +import { OpenGraphResponse } from '../types/inspiration'; +import { textEllipsisCss } from '@ygtang/ui-styles'; +import { useOpenGraphImage } from '@ygtang/hooks' +import { INSPIRATION_EMPTY_IMAGE_SRC } from '@ygtang/constants' + +export default function ThumbnailContent({ + type, + content, + openGraph, +}: Pick) { + if (type === 'IMAGE') return {`${content}; + if (type === 'LINK') return ; + + // Text type + return

{content}

; +} + +const imageCss = css` + width: 100%; + height: 100%; + object-fit: cover; +`; + +const textCss = css` + font-size: 12px; + padding: 6px; + line-height: 150%; +`; + +function LinkContent({ openGraph }: Pick) { + const [og, setOg] = useState(); + const { src, onImageError } = useOpenGraphImage({ + url: og?.url, + image: og?.image || INSPIRATION_EMPTY_IMAGE_SRC, + }); + + useEffect(() => { + setOg(openGraph); + }, []); + + return ( +
+
+ {src && {`${og?.url}} +
+ +
+

{og?.title}

+

{og?.url}

+
+
+ ); +} + +const linkWrapperCss = css` + width: 100%; + height: 100%; + display: grid; + grid-template-rows: calc(100% - 42px) 42px; + font-size: 10px; +`; + +const linkImgWrapperCss = (theme: Theme) => css` + width: 100%; + background-color: ${theme.color.dim01}; + + & > img { + width: 100%; + height: 100%; + object-fit: cover; + } +`; + +const linkTextWrapperCss = (theme: Theme) => css` + width: 100%; + padding: 7px 6px; + background-color: ${theme.color.dim01}; + display: flex; + flex-direction: column; + justify-content: space-between; + overflow: hidden; + + & p { + ${textEllipsisCss(1)} + } +`; diff --git a/packages/ui-components/src/index.ts b/packages/ui-components/src/index.ts index 3bccc57f..7204bb16 100644 --- a/packages/ui-components/src/index.ts +++ b/packages/ui-components/src/index.ts @@ -20,6 +20,7 @@ export type { SvgComponentProps, SvgProps } from "./components/Svg"; export { Svg } from "./components/Svg"; export type { InputProps, SearchBarProps } from "./components/TextField"; export { Input, SearchBar, TextField } from "./components/TextField"; +export { default as Thumbnail } from "./components/Thumbnail"; // shared export { dimBackdropCss } from "./shared/styles"; diff --git a/packages/ui-components/src/types/auth.ts b/packages/ui-components/src/types/auth.ts new file mode 100644 index 00000000..13e61b28 --- /dev/null +++ b/packages/ui-components/src/types/auth.ts @@ -0,0 +1,15 @@ +export interface AuthTokenResponseInterface { + accessToken: string; + refreshToken: string; + accessTokenExpireDate: string; +} + +export interface CheckSignupResponseInterface { + message: string; + data: boolean; +} + +export interface CheckEmailCerificateResponseInterface { + message: string; + data: boolean; +} diff --git a/packages/ui-components/src/types/index.ts b/packages/ui-components/src/types/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/ui-components/src/types/inspiration.ts b/packages/ui-components/src/types/inspiration.ts new file mode 100644 index 00000000..68bda477 --- /dev/null +++ b/packages/ui-components/src/types/inspiration.ts @@ -0,0 +1,25 @@ +import { MemberResponseInterface } from "./member"; +import { TagInterface } from "./tag"; + +export type InspirationType = "TEXT" | "IMAGE" | "LINK"; + +export interface OpenGraphResponse { + code: number; + description: string | null; + siteName: string | null; + title: string | null; + url: string | null; + image: string | null; +} + +export interface InspirationInterface { + id: number; + memberResponse: MemberResponseInterface; + tagResponses: TagInterface[]; + type: InspirationType; + content: string; + memo: string; + openGraphResponse: OpenGraphResponse; + createdDatetime: string; + updatedDatetime: string; +} diff --git a/packages/ui-components/src/types/member.ts b/packages/ui-components/src/types/member.ts new file mode 100644 index 00000000..b556e1a1 --- /dev/null +++ b/packages/ui-components/src/types/member.ts @@ -0,0 +1,8 @@ +export interface MemberResponseInterface { + id: number; + nickName: string; + email: string; + createdDatetime?: string; +} + +export type UserInformationType = Omit; diff --git a/packages/ui-components/src/types/pagination.ts b/packages/ui-components/src/types/pagination.ts new file mode 100644 index 00000000..3dd350d4 --- /dev/null +++ b/packages/ui-components/src/types/pagination.ts @@ -0,0 +1,17 @@ +export interface PaginationInterface { + number: number; + size: number; + totalElements: number; + totalPages: number; + last: boolean; + sort: SortInterface; + numberOfElements: number; + first: boolean; + empty: boolean; +} + +export interface SortInterface { + empty: boolean; + unsorted: boolean; + sorted: boolean; +} diff --git a/packages/ui-components/src/types/tag.ts b/packages/ui-components/src/types/tag.ts new file mode 100644 index 00000000..8b5b11f9 --- /dev/null +++ b/packages/ui-components/src/types/tag.ts @@ -0,0 +1,12 @@ +import { MemberResponseInterface } from "./member"; + +export interface TagInterface { + id: number; + count?: number; + memberResponse: MemberResponseInterface; + content: string; + createdDatetime: string; + updatedDatetime: string; +} + +export type TagType = Pick; diff --git a/packages/ui-styles/src/index.ts b/packages/ui-styles/src/index.ts index ae9bea3f..9914efc8 100644 --- a/packages/ui-styles/src/index.ts +++ b/packages/ui-styles/src/index.ts @@ -2,4 +2,4 @@ export { GlobalStyle } from "./GlobalStyle"; export type { ThemeColor } from "./Theme"; export type { Theme, Theme as YgtangTheme } from "./Theme"; export { theme, ThemeProvider, useTheme, theme as ygtangTheme } from "./Theme"; -export { fullViewHeight, textEllipsisCss, viewHeight } from "./utils"; +export { fullViewHeight, textEllipsisCss, viewHeight, selectRandomColor } from "./utils"; \ No newline at end of file diff --git a/packages/ui-styles/src/utils/index.ts b/packages/ui-styles/src/utils/index.ts index 971b9130..28c1ab6d 100644 --- a/packages/ui-styles/src/utils/index.ts +++ b/packages/ui-styles/src/utils/index.ts @@ -1,2 +1,3 @@ export { textEllipsisCss } from "./textEllipsisCss"; export { fullViewHeight, viewHeight } from "./viewHeight"; +export { selectRandomColor } from './selectRandomColor' \ No newline at end of file diff --git a/packages/ui-styles/src/utils/selectRandomColor/index.ts b/packages/ui-styles/src/utils/selectRandomColor/index.ts new file mode 100644 index 00000000..117ccaf6 --- /dev/null +++ b/packages/ui-styles/src/utils/selectRandomColor/index.ts @@ -0,0 +1 @@ +export { selectRandomColor } from './selectRandomColor'; diff --git a/packages/ui-styles/src/utils/selectRandomColor/selectRandomColor.ts b/packages/ui-styles/src/utils/selectRandomColor/selectRandomColor.ts new file mode 100644 index 00000000..6899fa0b --- /dev/null +++ b/packages/ui-styles/src/utils/selectRandomColor/selectRandomColor.ts @@ -0,0 +1,10 @@ +import { Theme } from '@emotion/react'; + +type ColorType = keyof Theme['color']; + +export function selectRandomColor(theme: Theme, colorRange: ColorType[]) { + const randomNumber = Math.floor(Math.random() * colorRange.length); + const randomColor = colorRange[randomNumber] ?? 'black'; + + return theme.color[randomColor]; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b8f346a8..d454e36c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ importers: '@ygtang/constants': specifier: workspace:* version: link:../../packages/constants + '@ygtang/hooks': + specifier: workspace:* + version: link:../../packages/hooks '@ygtang/http': specifier: workspace:^ version: link:../../packages/http