Skip to content

Commit

Permalink
Merge pull request #214 from themoment-team/develop
Browse files Browse the repository at this point in the history
Release v0.3.0
  • Loading branch information
hyeongrok7874 committed Sep 7, 2023
2 parents c1aa092 + e1f41d6 commit ed13232
Show file tree
Hide file tree
Showing 38 changed files with 1,711 additions and 138 deletions.
2 changes: 2 additions & 0 deletions apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
"eslint": "8.40.0",
"eslint-config-next": "13.4.2",
"react-dom": "18.2.0",
"react-kakao-maps-sdk": "^1.1.12",
"types": "workspace:^",
"typescript": "5.0.4",
"ui": "workspace:^"
},
"devDependencies": {
"@storybook/react": "^7.0.6",
"eslint-config-custom": "workspace:^",
"kakao.maps.d.ts": "^0.1.38",
"tsconfig": "workspace:^"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions apps/client/public/images/about/Location/svg/ChevronIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions apps/client/public/images/about/Location/svg/CloseIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions apps/client/public/images/about/Location/svg/CopyLinkIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions apps/client/public/images/about/Location/svg/MarkerIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions apps/client/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ export default function RootLayout({
`,
}}
/>
<Script
src={`//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_KAKAOMAP_APPKEY}&autoload=false&libraries=services,clusterer`}
type='text/javascript'
strategy='beforeInteractive'
/>
</head>

<body>
Expand Down
76 changes: 64 additions & 12 deletions apps/client/src/app/list/[category]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { notFound, redirect } from 'next/navigation';

import { Footer, Header, ListPageContent } from 'client/components';

import type { CategoryType } from 'types';
import { postUrl } from 'api/client';

import { categoryList, categoryQueryString, minutesToSeconds } from 'common';

import type { CategoryType, PostListType } from 'types';

import type { Metadata } from 'next';

Expand All @@ -21,32 +27,78 @@ const categoryTitle: {
},
} as const;

export const generateMetadata = async ({
export const generateMetadata = ({
params: { category },
}: ListPageProps): Promise<Metadata> => ({
title: { absolute: categoryTitle[category].title },
description: categoryTitle[category].description,
openGraph: {
title: categoryTitle[category].title,
}: ListPageProps): Metadata => {
if (!categoryList.includes(category)) {
return notFound();
}

return {
title: { absolute: categoryTitle[category].title },
description: categoryTitle[category].description,
url: `https://official.hellogsm.kr/list/${category}`,
},
});
openGraph: {
title: categoryTitle[category].title,
description: categoryTitle[category].description,
url: `https://official.hellogsm.kr/list/${category}`,
},
};
};

interface ListPageProps {
params: { category: CategoryType };
searchParams: { pageNumber: string };
}

export default function ListPage({
export default async function ListPage({
params: { category },
searchParams,
}: ListPageProps) {
/**falsy 값을 1로 대체 (ex. '', 0, undefined) */
const pageNumber = Number(searchParams.pageNumber || 1);
const postList = await getPostList(category, pageNumber);

if (postList.postList.length < 1) {
return redirect(`/list/${category}`);
}

return (
<>
<Header segment={'list'} />
<ListPageContent category={category} searchParams={searchParams} />
<ListPageContent
category={category}
postList={postList}
pageNumber={pageNumber}
/>
<Footer />
</>
);
}

async function getPostList(
category: CategoryType,
pageNumber: number
): Promise<PostListType> {
const PAGE_SIZE = 12;

try {
const res = await fetch(
`${process.env.BASE_URL}/api/client${postUrl.postList(
categoryQueryString[category],
pageNumber,
PAGE_SIZE
)}`,
{
next: {
revalidate: minutesToSeconds(5),
},
}
);

const data: PostListType = await res.json();

return data;
} catch (e) {
return notFound();
}
}
4 changes: 2 additions & 2 deletions apps/client/src/app/post/[postSeq]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Footer, Header, AssembledPost } from 'client/components';

import { postUrl } from 'api/client';

import { descriptionFormatting } from 'common';
import { descriptionFormatting, minutesToSeconds } from 'common';

import type { PostDetailType } from 'types';

Expand Down Expand Up @@ -53,7 +53,7 @@ async function getPostDetail(postSeq: number) {
`${process.env.BASE_URL}/api/client${postUrl.postDetail(postSeq)}`,
{
next: {
revalidate: 60,
revalidate: minutesToSeconds(5),
},
}
);
Expand Down
4 changes: 3 additions & 1 deletion apps/client/src/app/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ThemeProvider } from '@emotion/react';

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

import { theme } from 'common';
import { minutesToMs, theme } from 'common';

export default function Providers({ children }: { children: React.ReactNode }) {
// TODO: client api 연동 시, queryclient option 공유 가능하도록 구성 변경
Expand All @@ -16,6 +16,8 @@ export default function Providers({ children }: { children: React.ReactNode }) {
defaultOptions: {
queries: {
retry: false,
staleTime: minutesToMs(5),
cacheTime: minutesToMs(5),
},
},
})
Expand Down
81 changes: 81 additions & 0 deletions apps/client/src/components/About/Location/Map/InfoWindow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import Image from 'next/image';

import * as S from './style';
interface InfoWindowProps {
latitude: number;
longitude: number;
onClose: () => void;
}

const InfoWindow: React.FC<InfoWindowProps> = ({
latitude,
longitude,
onClose,
}) => {
const CloseButtonClick = () => {
onClose();
};

const copyLinkButtonClick = () => {
const linkToCopy = 'http://kko.to/CtKpnV33Dj';
navigator.clipboard.writeText(linkToCopy).then(() => {
alert('링크가 복사되었습니다');
});
};

return (
<S.Next>
<S.Box>
<S.Close>
<Image
alt='closeIcon'
width={20}
height={20}
src='/images/about/location/svg/CloseIcon.svg'
onClick={CloseButtonClick}
/>
</S.Close>
<S.ContentBox>
<S.Title>광주소프트웨어마이스터고등학교</S.Title>
<S.Address>광주 광산구 상무대로 312 </S.Address>
<div> (우) 62423&nbsp;&nbsp;(지번) 송정동 710-3</div>
<S.Number>062-949-6800</S.Number>
</S.ContentBox>
<S.BottomBox>
<S.IconBox>
<a
href={`https://map.kakao.com/link/roadview/${latitude},${longitude}`}
target='_blank'
>
<S.Icon>
<Image
width={16}
height={16}
alt='smallMarker'
src='/images/about/location/svg/SmallMarkerIcon.svg'
/>
</S.Icon>
</a>
<S.Icon onClick={copyLinkButtonClick}>
<Image
width={16}
height={16}
alt='CopyLinkIcon'
src='/images/about/location/svg/CopyLinkIcon.svg'
/>
</S.Icon>
</S.IconBox>
<a
href={`https://map.kakao.com/link/to/광주소프트웨어마이스터고등학교,${latitude},${longitude}`}
target='_blank'
>
<S.LocationBtn>길찾기</S.LocationBtn>
</a>
</S.BottomBox>
</S.Box>
<S.Triangle2 />
</S.Next>
);
};

export default InfoWindow;
64 changes: 64 additions & 0 deletions apps/client/src/components/About/Location/Map/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { useState } from 'react';

import Image from 'next/image';

import InfoWindow from './InfoWindow';
import * as S from './style';

interface OverlayProps {
latitude: number;
longitude: number;
}

const Overlay: React.FC<OverlayProps> = ({ latitude, longitude }) => {
const [isInfoWindowVisible, setIsInfoWindowVisible] = useState(false);
const [isCustomOverlayVisible, setIsCustomOverlayVisible] = useState(true);

const isOverlay = () => {
setIsInfoWindowVisible(!isInfoWindowVisible);
setIsCustomOverlayVisible(!isCustomOverlayVisible);
};

const onCloseInfoWindow = () => {
setIsInfoWindowVisible(false);
setIsCustomOverlayVisible(true);
};

return (
<div>
{isCustomOverlayVisible && (
<S.CustomOverlay>
<S.Default onClick={isOverlay}>
<S.MarkerIcon>
<Image
width={20}
height={20}
alt='markerIcon'
src='/images/about/location/svg/MarkerIcon.svg'
/>
</S.MarkerIcon>
<S.Title>광주소프트웨어마이스터고등학교</S.Title>
<S.Chevron>
<Image
width={20}
height={20}
alt='chevronIcon'
src='/images/about/location/svg/ChevronIcon.svg'
/>
</S.Chevron>
</S.Default>
<S.Triangle />
</S.CustomOverlay>
)}
{isInfoWindowVisible && (
<InfoWindow
latitude={latitude}
longitude={longitude}
onClose={onCloseInfoWindow}
/>
)}
</div>
);
};

export default Overlay;
Loading

1 comment on commit ed13232

@vercel
Copy link

@vercel vercel bot commented on ed13232 Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.