From fe504b3d35234963e924ff5536fb19a679f6c5a8 Mon Sep 17 00:00:00 2001 From: NAJEONG KIM <73640737+Najeong-Kim@users.noreply.github.com> Date: Sun, 18 Aug 2024 04:18:40 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=A7=81=ED=81=AC=EB=A1=9C=20=EA=B3=B5?= =?UTF-8?q?=EC=9C=A0=ED=95=98=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add share dialog * refactor: Fix folder structures * fix: Fix tag error * fix: Fix console error * feat: Add copy url and toast * feat: Add checking postposition --- package.json | 2 + public/{ => assets}/background.png | Bin public/{ => assets}/logo.svg | 0 public/{ => assets}/snow.png | Bin public/{ => blinds}/blind_01.png | Bin public/{ => blinds}/blind_02-1.png | Bin public/{ => blinds}/blind_02.png | Bin public/{ => blinds}/blind_03-1.png | Bin public/{ => blinds}/blind_03.png | Bin public/{ => blinds}/blind_04-1.png | Bin public/{ => blinds}/blind_04.png | Bin public/{ => downloads}/android.png | Bin public/{ => downloads}/ios.png | Bin public/shares/share_01.png | Bin 0 -> 2788 bytes public/shares/share_02.png | Bin 0 -> 7145 bytes public/shares/share_03.png | Bin 0 -> 2814 bytes public/shares/share_04.png | Bin 0 -> 2051 bytes src/app/(web)/layout.tsx | 4 +- src/app/layout.tsx | 2 + .../ui/app-download-dialog.tsx | 14 ++- .../discovery-detail/ui/share-dialog.tsx | 94 ++++++++++++++++++ .../discovery-detail/ui/vote-dialog.tsx | 0 .../ui/discovery-detail-page.tsx | 18 ++-- src/shared/lib/getPostposition.ts | 12 +++ src/shared/lib/index.ts | 1 + src/shared/ui/toaster.tsx | 29 ++++++ .../discovery-detail/ui/discovery-summary.tsx | 2 +- src/widgets/header/ui/header.tsx | 15 ++- yarn.lock | 10 ++ 29 files changed, 180 insertions(+), 23 deletions(-) rename public/{ => assets}/background.png (100%) rename public/{ => assets}/logo.svg (100%) rename public/{ => assets}/snow.png (100%) rename public/{ => blinds}/blind_01.png (100%) rename public/{ => blinds}/blind_02-1.png (100%) rename public/{ => blinds}/blind_02.png (100%) rename public/{ => blinds}/blind_03-1.png (100%) rename public/{ => blinds}/blind_03.png (100%) rename public/{ => blinds}/blind_04-1.png (100%) rename public/{ => blinds}/blind_04.png (100%) rename public/{ => downloads}/android.png (100%) rename public/{ => downloads}/ios.png (100%) create mode 100644 public/shares/share_01.png create mode 100644 public/shares/share_02.png create mode 100644 public/shares/share_03.png create mode 100644 public/shares/share_04.png rename src/{widgets => features}/discovery-detail/ui/app-download-dialog.tsx (79%) create mode 100644 src/features/discovery-detail/ui/share-dialog.tsx rename src/{widgets => features}/discovery-detail/ui/vote-dialog.tsx (100%) create mode 100644 src/shared/lib/getPostposition.ts create mode 100644 src/shared/ui/toaster.tsx diff --git a/package.json b/package.json index c51d566..9209ddf 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,11 @@ "autoprefixer": "^10.4.19", "class-variance-authority": "^0.7.0", "next": "14.2.5", + "next-themes": "^0.3.0", "react": "^18", "react-dom": "^18", "react-hls-player": "^3.0.7", + "sonner": "^1.5.0", "tailwind-scrollbar-hide": "^1.1.7", "tailwindcss-animate": "^1.0.7", "ts-pattern": "^5.2.0", diff --git a/public/background.png b/public/assets/background.png similarity index 100% rename from public/background.png rename to public/assets/background.png diff --git a/public/logo.svg b/public/assets/logo.svg similarity index 100% rename from public/logo.svg rename to public/assets/logo.svg diff --git a/public/snow.png b/public/assets/snow.png similarity index 100% rename from public/snow.png rename to public/assets/snow.png diff --git a/public/blind_01.png b/public/blinds/blind_01.png similarity index 100% rename from public/blind_01.png rename to public/blinds/blind_01.png diff --git a/public/blind_02-1.png b/public/blinds/blind_02-1.png similarity index 100% rename from public/blind_02-1.png rename to public/blinds/blind_02-1.png diff --git a/public/blind_02.png b/public/blinds/blind_02.png similarity index 100% rename from public/blind_02.png rename to public/blinds/blind_02.png diff --git a/public/blind_03-1.png b/public/blinds/blind_03-1.png similarity index 100% rename from public/blind_03-1.png rename to public/blinds/blind_03-1.png diff --git a/public/blind_03.png b/public/blinds/blind_03.png similarity index 100% rename from public/blind_03.png rename to public/blinds/blind_03.png diff --git a/public/blind_04-1.png b/public/blinds/blind_04-1.png similarity index 100% rename from public/blind_04-1.png rename to public/blinds/blind_04-1.png diff --git a/public/blind_04.png b/public/blinds/blind_04.png similarity index 100% rename from public/blind_04.png rename to public/blinds/blind_04.png diff --git a/public/android.png b/public/downloads/android.png similarity index 100% rename from public/android.png rename to public/downloads/android.png diff --git a/public/ios.png b/public/downloads/ios.png similarity index 100% rename from public/ios.png rename to public/downloads/ios.png diff --git a/public/shares/share_01.png b/public/shares/share_01.png new file mode 100644 index 0000000000000000000000000000000000000000..a76059ef9e7dfa8d8427507111e40ff3cfe99383 GIT binary patch literal 2788 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 QE&u=k07*qoM6N<$g1xkPA^-pY literal 0 HcmV?d00001 diff --git a/public/shares/share_04.png b/public/shares/share_04.png new file mode 100644 index 0000000000000000000000000000000000000000..eae94802daa56fab6e5d09ce344ecb55437671e3 GIT binary patch literal 2051 zcmV+e2>kbnP))%f%(OUg*yA_j}!Kcem5snVp&U-tNvPDa^8y?e2GfeBbZ)dvD$d zSW3~CBh}|HiU1>Uu+yoc5C|0LsY2_yjzl?dQK57HqI1hGJ)XNQ9>PKdETCAFh3bFs z>F^CH;R{J3hX~sRCHewb`1|hjD9z1@3JhaRa3%6Grs(i6{rJ#Bi9Yca*Cp|P5M>xZ zyWqt!=~sbM&?oX%DDiLJ7MGzBErN422g{h2z%is_73m>Rraw>X5dKA_TcIuMJC7PG>N@{UKg8@nBvbe zF)pW&BB?~UO7T{3p5G+;5svmD98V*UPb|2ykSgx=oL9$%yqzp&e^QG{WGTgQIjStA z-^FI=Gjd?PL!TK5=vwf}1M=U=tlHdf=?WjMQVXwN6tDfXdt~KN>R^`EO@P;87$9^M#c58FKYG@Y0z9x z{c^FxD6lqMi$pm&lHjUTAB5DeTR3H0j%KwT1wS+$Q)zv;Y=)1&x<5>5i(doVcfe-WZAA(0SRUP-=!Ixstwp&KoF;|$q7Se++R3t&#&r+((I;3O?V~&m z=NxKCS^5bJqrHF?jCd641v@US3Wu|kS6%~NeI2o>NBcKdfq9y7Tv>)usublOY3v7z*SLcR10=k#VPT=-OU`#AfyX?`b>&(NIu$_jK+;lif^jhV`u2hI96 zr+}Oa>a>w{NNet;RCJd1hchm0+QAlbb_RI-C(IyG_DJI5exy#T%sfwJd z+AXA&ryc^b6iwa22?Np17BWj^{I3sS9J24SCwWgOO`fu+i)wO_{`)Wfq26rlCBY`i=Fu%f1L#9L2dfuWMcpFVC^+*6dSdLK&sND)bJ5` zq>l_4-lAW@gWAO}k_l}zw~mP9Y!EfU1A#fwvgj~vwuMaQvQWHSElFPdmK1tmm-xt#)&VoF*kNl3Iil72Ld(S_D)sB}H@bxaH;^H%vnp{T`^nNq z*1@mEeGs-H!-Y&V#9DN(9oFFWDfA$->oPf|;|}4_a5B&4-gQri+(6@w6HPVd@Ej-v zE_b|6({(X}oK)bgR9pXTli>V~NSS+iVnU*u37xg~s+h^WynDpjE}o&QT|xz~HMI0C zkLfokGudj>v9@zPl$S5?5?ka%rZw+wrR_o>N8l)OV&S;h-}d=-PuA{*a~wI5AiLUgS2=qIW4alW0{T-*kgK?7AF~Jr30XDQLPZ!M!?Dxvfl4#l3zPol`%@^lfDr zegn=k?BiP{qFiSzxEtFwhvsa*f=j+jMCWOMU7>Ze2Y{FZzr zt{&6A`CVp9@l~_~r+UrX*{cH?KfjLr`pB4G5uWXXmx*}8n9cHL)!MeEu~m3oLO1+A zz0?XO_IDp>hC56%>W1!dZ%pt;)D2Mog)bfWwe9A7 zB&4?Lpd1L?7Xf7)FQ8;fChzKFyd2|2amNXnNTJf$zI%om@! hRXm(4rJK&B#s7R4=S3wG_gw%0002ovPDHLkV1oZ1>}~)6 literal 0 HcmV?d00001 diff --git a/src/app/(web)/layout.tsx b/src/app/(web)/layout.tsx index 2466710..1d3387a 100644 --- a/src/app/(web)/layout.tsx +++ b/src/app/(web)/layout.tsx @@ -5,7 +5,9 @@ import { cn } from '@/shared/lib'; export default function Layout({ children }: { children: React.ReactNode }) { return (
-
+
{children}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e3eb500..d04a815 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import '@/app/globals.css'; import type { Metadata } from 'next'; +import { Toaster } from '@/shared/ui/toaster'; import Providers from './_providers'; export const metadata: Metadata = { @@ -13,6 +14,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) {children} + ); diff --git a/src/widgets/discovery-detail/ui/app-download-dialog.tsx b/src/features/discovery-detail/ui/app-download-dialog.tsx similarity index 79% rename from src/widgets/discovery-detail/ui/app-download-dialog.tsx rename to src/features/discovery-detail/ui/app-download-dialog.tsx index fffc592..d27d064 100644 --- a/src/widgets/discovery-detail/ui/app-download-dialog.tsx +++ b/src/features/discovery-detail/ui/app-download-dialog.tsx @@ -1,8 +1,8 @@ import Image from 'next/image'; -import android from '@public/android.png'; -import ios from '@public/ios.png'; -import logo from '@public/logo.svg'; -import snow from '@public/snow.png'; +import logo from '@public/assets/logo.svg'; +import snow from '@public/assets/snow.png'; +import android from '@public/downloads/android.png'; +import ios from '@public/downloads/ios.png'; import { CloseIcon } from '@/shared/icons'; import { cn } from '@/shared/lib'; @@ -22,13 +22,11 @@ const AppDownloadDialog = ({ className, onClose }: AppDownloadDialogProps) => { snow logo -

+

{'지금 앱 다운로드하고\n블라인드된 정보를\n매일 확인해보세요'}

diff --git a/src/features/discovery-detail/ui/share-dialog.tsx b/src/features/discovery-detail/ui/share-dialog.tsx new file mode 100644 index 0000000..a61408a --- /dev/null +++ b/src/features/discovery-detail/ui/share-dialog.tsx @@ -0,0 +1,94 @@ +import Image from 'next/image'; +import { useCallback } from 'react'; +import { toast } from 'sonner'; +import logo from '@public/assets/logo.svg'; +import snow from '@public/assets/snow.png'; +import share1 from '@public/shares/share_01.png'; +import share2 from '@public/shares/share_02.png'; +import share3 from '@public/shares/share_03.png'; +import share4 from '@public/shares/share_04.png'; +import { CloseIcon } from '@/shared/icons'; +import { cn, getPostposition } from '@/shared/lib'; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogTitle, + DialogTrigger, +} from '@/shared/ui/dialog'; + +interface ShareDialogProps { + trigger: React.ReactNode; + name?: string; +} + +const ShareDialog = ({ trigger, name }: ShareDialogProps) => { + const handleCopyUrl = useCallback(() => { + const currentUrl = window.location.href; + navigator.clipboard + .writeText(currentUrl) + .then(() => { + toast('클립보드에 복사되었습니다'); + }) + .catch((error) => { + console.error('클립보드 복사 실패!', error); + }); + }, []); + + return ( + + {trigger} + + + + + snow + + + + logo +
+

{getPostposition(name || '')}

+

공유해보세요!

+
+
+
+ +

카카오톡

+
+
+ +

인스타그램

+
+
+ +

스레드

+
+
+ +

링크 공유

+
+
+
+
+ ); +}; + +export default ShareDialog; diff --git a/src/widgets/discovery-detail/ui/vote-dialog.tsx b/src/features/discovery-detail/ui/vote-dialog.tsx similarity index 100% rename from src/widgets/discovery-detail/ui/vote-dialog.tsx rename to src/features/discovery-detail/ui/vote-dialog.tsx diff --git a/src/pages/discovery-detail/ui/discovery-detail-page.tsx b/src/pages/discovery-detail/ui/discovery-detail-page.tsx index f93e8be..5f62f29 100644 --- a/src/pages/discovery-detail/ui/discovery-detail-page.tsx +++ b/src/pages/discovery-detail/ui/discovery-detail-page.tsx @@ -3,12 +3,12 @@ import Image from 'next/image'; import { useState } from 'react'; import { useCallback } from 'react'; -import blind1 from '@public/blind_01.png'; +import blind1 from '@public/blinds/blind_01.png'; import { DiscoveryContentTabList } from '@/widgets/discovery-detail/model/constants'; -import AppDownloadDialog from '@/widgets/discovery-detail/ui/app-download-dialog'; import DiscoverySummary from '@/widgets/discovery-detail/ui/discovery-summary'; import { Header } from '@/widgets/header/ui'; import { WebcamMap, WebcamSlopList } from '@/widgets/webcam/ui'; +import AppDownloadDialog from '@/features/discovery-detail/ui/app-download-dialog'; import useMapPinch from '@/features/slop/hooks/useMapPinch'; import calculateWebcamPosition from '@/features/slop/lib/calculateWebcamPosition'; import { DiscoveryData } from '@/entities/discovery'; @@ -49,7 +49,7 @@ const DiscoveryDetailPage = ({ params }: { params: { resortId: number } }) => { return (
-
+
    {DiscoveryContentTabList.map((tab) => ( @@ -99,8 +99,8 @@ const DiscoveryDetailPage = ({ params }: { params: { resortId: number } }) => {

    주간 예보

    {showAppDownloadDialog && ( @@ -118,16 +118,16 @@ const DiscoveryDetailPage = ({ params }: { params: { resortId: number } }) => {

    인기 시간대

    슬로프 운행 현황

    {showAppDownloadDialog && ( diff --git a/src/shared/lib/getPostposition.ts b/src/shared/lib/getPostposition.ts new file mode 100644 index 0000000..ab4bccb --- /dev/null +++ b/src/shared/lib/getPostposition.ts @@ -0,0 +1,12 @@ +const getPostposition = (name: string) => { + const charCode = name.charCodeAt(name.length - 1); + + const consonantCode = (charCode - 44032) % 28; + + if (consonantCode === 0) { + return `${name}를`; + } + return `${name}을`; +}; + +export default getPostposition; diff --git a/src/shared/lib/index.ts b/src/shared/lib/index.ts index d4b67fe..77f411e 100644 --- a/src/shared/lib/index.ts +++ b/src/shared/lib/index.ts @@ -1,3 +1,4 @@ export { default as cn } from '@/shared/lib/cn'; export { default as getBoundedPositions } from '@/shared/lib/getBoundedPositions'; +export { default as getPostposition } from '@/shared/lib/getPostposition'; export type { ExcludeArray } from '@/shared/lib/util.d.ts'; diff --git a/src/shared/ui/toaster.tsx b/src/shared/ui/toaster.tsx new file mode 100644 index 0000000..584f52a --- /dev/null +++ b/src/shared/ui/toaster.tsx @@ -0,0 +1,29 @@ +'use client'; + +import { useTheme } from 'next-themes'; +import { Toaster as Sonner } from 'sonner'; + +type ToasterProps = React.ComponentProps; + +const Toaster = ({ ...props }: ToasterProps) => { + const { theme = 'system' } = useTheme(); + + return ( + + ); +}; + +export { Toaster }; diff --git a/src/widgets/discovery-detail/ui/discovery-summary.tsx b/src/widgets/discovery-detail/ui/discovery-summary.tsx index 313b586..3ad492d 100644 --- a/src/widgets/discovery-detail/ui/discovery-summary.tsx +++ b/src/widgets/discovery-detail/ui/discovery-summary.tsx @@ -1,12 +1,12 @@ import { useCallback } from 'react'; import WeatherIcon from '@/features/discovery/ui/weather-icon'; +import VoteDialog from '@/features/discovery-detail/ui/vote-dialog'; import type { Discovery } from '@/entities/discovery'; import { BusIcon, LiftIcon, VoteIcon } from '@/shared/icons'; import { cn } from '@/shared/lib'; import Card from '@/shared/ui/card'; import { DiscoverySummaryActionList } from '../model/constants'; import DiscoverySummaryAction from './discovery-summary-action'; -import VoteDialog from './vote-dialog'; const DiscoverySummary = ({ name, slope, weather }: Discovery) => { const handleAction = useCallback( diff --git a/src/widgets/header/ui/header.tsx b/src/widgets/header/ui/header.tsx index 707e9d5..e34062b 100644 --- a/src/widgets/header/ui/header.tsx +++ b/src/widgets/header/ui/header.tsx @@ -1,13 +1,15 @@ import { useRouter } from 'next/navigation'; +import ShareDialog from '@/features/discovery-detail/ui/share-dialog'; import { ChevronLeftIcon, ShareIcon } from '@/shared/icons'; import { cn } from '@/shared/lib'; interface HeaderProps { + resortName?: string; hasBackButton?: boolean; hasShareButton?: boolean; } -const Header = ({ hasBackButton, hasShareButton }: HeaderProps) => { +const Header = ({ resortName, hasBackButton, hasShareButton }: HeaderProps) => { const router = useRouter(); return ( @@ -24,9 +26,14 @@ const Header = ({ hasBackButton, hasShareButton }: HeaderProps) => { WeSki {hasShareButton && ( - + + +
    + } + name={resortName} + /> )}
    ); diff --git a/yarn.lock b/yarn.lock index 999073c..0b35a83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2337,6 +2337,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +next-themes@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.3.0.tgz#b4d2a866137a67d42564b07f3a3e720e2ff3871a" + integrity sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w== + next@14.2.5: version "14.2.5" resolved "https://registry.yarnpkg.com/next/-/next-14.2.5.tgz#afe4022bb0b752962e2205836587a289270efbea" @@ -2878,6 +2883,11 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +sonner@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sonner/-/sonner-1.5.0.tgz#af359f817063318415326b33aab54c5d17c747b7" + integrity sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA== + source-map-js@^1.0.2, source-map-js@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"