Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ListyWave ver2.5.0 : SEO 개선 / 라벨 또는 카테고리 클릭시 검색 이동 기능 추가 #249

Merged
merged 2 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/app/collection/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,23 @@ export default function CollectionPage() {
<div className={styles.categoryFolders}>
{data &&
data.map((category) => (
<div key={category.codeValue} className={styles.categoryContainer}>
<div key={category.code} className={styles.categoryContainer}>
<div
className={styles.categoryFolder}
onClick={() => {
handleCategoryClick(category.nameValue);
handleCategoryClick(category.engName);
}}
>
<Image
className={styles.categoryIcon}
src={category?.categoryImageUrl ?? ''}
width={50}
height={50}
alt={`${category.korNameValue} ${categoriesLocale[language].folder}`}
alt={`${category.korName} ${categoriesLocale[language].folder}`}
/>
<div className={styles.folderIcon}>{codeToFolderIcon(category.codeValue, language)}</div>
<div className={styles.folderIcon}>{codeToFolderIcon(category.code, language)}</div>
</div>
<p className={styles.categoryLabel}>{language === 'ko' ? category.korNameValue : category.nameValue}</p>
<p className={styles.categoryLabel}>{language === 'ko' ? category.korName : category.engName}</p>
</div>
))}
</div>
Expand Down
36 changes: 18 additions & 18 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ReactNode } from 'react';
import type { Metadata, Viewport } from 'next';
import { ReferrerEnum } from 'next/dist/lib/metadata/types/metadata-types';
import { OpenGraphType } from 'next/dist/lib/metadata/types/opengraph-types';
import { ToastContainer } from 'react-toastify';
import { GoogleTagManager } from '@next/third-parties/google';

Expand All @@ -9,6 +11,7 @@ import '@/styles/GlobalStyles.css';
import * as styles from './layout.css';

import CommonProvider from './_context/CommonProvider';
import METADATA from '@/lib/constants/metadata';

export const viewport: Viewport = {
width: 'device-width',
Expand All @@ -19,27 +22,24 @@ export const viewport: Viewport = {
};

export const metadata: Metadata = {
// Template Object
title: {
template: '%s | ListyWave',
default: 'ListyWave', // 대체 제목 (required),
template: METADATA.title.template,
default: METADATA.title.default,
},
description:
"What’s In Your List? 🌊 나의 취향을 리스트로 기록하고, 공유하고, 발견해요. 리스티웨이브에서 모든 기준은 '나의 취향'이에요. 내 취향 가득한 편안한 공간이 되면 좋겠습니다.",
authors: [{ name: '에잇🩷' }],
generator: 'Next.js',
applicationName: 'ListyWave',
referrer: 'origin-when-cross-origin', // Referrer-Policy
keywords: ['ListyWave', 'list', 'SNS'],
metadataBase: new URL('https://listywave.com'),
description: METADATA.description.default,
authors: [{ name: METADATA.authors.name, url: METADATA.authors.url }],
generator: METADATA.generator,
applicationName: METADATA.applicationName,
referrer: METADATA.referrer as ReferrerEnum,
keywords: METADATA.keywords,
metadataBase: new URL(METADATA.url),
openGraph: {
title: 'ListyWave',
description:
"What’s In Your List? 🌊 나의 취향을 리스트로 기록하고, 공유하고, 발견해요. 리스티웨이브에서 모든 기준은 '나의 취향'이에요. 내 취향 가득한 편안한 공간이 되면 좋겠습니다.",
url: 'https://listywave.com',
type: 'website',
siteName: 'ListyWave',
locale: 'ko',
title: METADATA.title.openGraph,
description: METADATA.description.default,
url: METADATA.url,
type: METADATA.type as OpenGraphType,
siteName: METADATA.siteName,
locale: METADATA.locale,
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function ListDetailInner({ data, listId }: ListDetailInnerProps) {
listId: listId,
ownerId: data?.ownerId,
items: listData,
category: data?.category,
category: data?.categoryKorName,
title: data?.title,
description: data?.description,
collaborators: data?.collaborators,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const categoryWrapper = style({

export const labelWrapper = style({
marginRight: '8px',
cursor: 'pointer',
});

export const listTitle = style([
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use client';
import { MouseEvent } from 'react';
import Image from 'next/image';
import { useQuery } from '@tanstack/react-query';
import { useParams, useRouter } from 'next/navigation';
Expand Down Expand Up @@ -77,6 +78,18 @@ function ListInformation() {
return null;
}

const handleCategorySearch = (categoryEngName: string) => {
router.push(`/search?category=${categoryEngName}`);
};

const handleLabelSearch = (e: MouseEvent<HTMLDivElement>) => {
const labelElement = e.currentTarget.querySelector('div');
const labelText = labelElement?.textContent;
if (labelText) {
router.push(`/search?keyword=${labelText}`);
}
};

return (
<>
{isOn && (
Expand Down Expand Up @@ -105,12 +118,12 @@ function ListInformation() {
<>
<div className={styles.wrapper}>
<div className={styles.categoryWrapper}>
<div className={styles.labelWrapper}>
<Label colorType="blue">{list?.category}</Label>
<div className={styles.labelWrapper} onClick={() => handleCategorySearch(list?.categoryEngName)}>
<Label colorType="blue">{list?.categoryKorName}</Label>
</div>
{list?.labels.map((item: LabelType) => {
return (
<div className={styles.labelWrapper} key={item.name}>
<div className={styles.labelWrapper} key={item.name} onClick={handleLabelSearch}>
<Label colorType="skyblue">{`${item.name}`}</Label>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/app/list/[listId]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export default function EditPage() {
useEffect(() => {
if (listDetailData) {
methods.reset({
category: categories?.find((c) => c.korNameValue === listDetailData.category)?.nameValue || 'culture',
category: categories?.find((c) => c.korName === listDetailData.categoryKorName)?.engName || 'culture',
labels: listDetailData.labels.map((obj) => obj.name),
collaboratorIds: listDetailData.collaborators.filter((c) => c.id !== user.id).map((c) => c.id),
title: listDetailData.title,
Expand Down
31 changes: 31 additions & 0 deletions src/app/list/[listId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
import { Metadata, ResolvingMetadata } from 'next';
import * as styles from './ListDetail.css';

import ListInformation from '@/app/list/[listId]/_components/ListDetailOuter/ListInformation';
import axiosInstance from '@/lib/axios/axiosInstance';
import { ListDetailType } from '@/lib/types/listType';
import METADATA from '@/lib/constants/metadata';

interface ListDetailProps {
params: { listId: number };
}

export async function generateMetadata({ params }: ListDetailProps, parent: ResolvingMetadata): Promise<Metadata> {
const listId = params.listId;
const { data } = await axiosInstance.get<ListDetailType>(`/lists/${listId}`);
const { title, ownerNickname, collaborators, description, items } = data;

const previousImages = (await parent).openGraph?.images || [];
const listType = collaborators.length === 0 ? 'Mylist' : 'Collabo-list';

return {
title: {
absolute: `${ownerNickname}'s ${listType} - ${data.title}`,
},
description: `${description}`,
authors: [{ name: `${ownerNickname}` }],
openGraph: {
title: `${title} By.${ownerNickname}`,
description: `${description || `${ownerNickname}님의 취향을 기록한 리스트입니다.`}`,
url: `${METADATA.url}/list/${listId}`,
images: [`${items[0].imageUrl}`, ...previousImages],
},
};
}

export default function ListDetailPage() {
return (
Expand Down
6 changes: 3 additions & 3 deletions src/app/list/create/_components/CreateList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function CreateList({ onNextClick, type }: CreateListProps) {
const handleQueryParams = () => {
if (isTemplateCreation) {
setValue('title', searchParams?.get('title'));
const c = categories?.find((c) => c.korNameValue === searchParams?.get('category'))?.nameValue;
const c = categories?.find((c) => c.korName === searchParams?.get('category'))?.engName;
setValue('category', c);
}
};
Expand Down Expand Up @@ -143,9 +143,9 @@ function CreateList({ onNextClick, type }: CreateListProps) {
{/* 카테고리 */}
<Section title={listLocale[language].category} isRequired={true}>
<ButtonSelector
list={categories?.filter((category: CategoryType) => category.codeValue !== '0') || []}
list={categories?.filter((category: CategoryType) => category.code !== '0') || []}
onClick={(item: CategoryType) => {
setValue('category', item.nameValue);
setValue('category', item.engName);
}}
defaultValue={category}
/>
Expand Down
8 changes: 4 additions & 4 deletions src/app/list/create/_components/list/ButtonSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ function ButtonSelector({ list, onClick, defaultValue }: ButtonSelectorProps) {
<div className={styles.container}>
{list.map((item) => (
<button
key={item.codeValue}
className={`${styles.button} ${item.nameValue.toLocaleLowerCase() === selectedButton?.toLocaleLowerCase() ? styles.buttonActive : ''}`}
key={item.code}
className={`${styles.button} ${item.engName.toLocaleLowerCase() === selectedButton?.toLocaleLowerCase() ? styles.buttonActive : ''}`}
onClick={() => {
onClick(item);
setSelectedButton(item.nameValue);
setSelectedButton(item.engName);
}}
>
{item.korNameValue}
{item.korName}
</button>
))}
</div>
Expand Down
12 changes: 12 additions & 0 deletions src/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import DOMAIN_URL from '@/lib/constants/domain';
import type { MetadataRoute } from 'next';

export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
},
sitemap: `${DOMAIN_URL}/sitemap.xml`,
};
}
12 changes: 5 additions & 7 deletions src/app/search/_components/CategoryArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,16 @@ function CategoryArea({ onClick }: { onClick: MouseEventHandler }) {
? Array.from({ length: 6 }).map((_, index) => <CategoryAreaSkeleton key={index} />)
: data &&
data.map((category) => (
<div className={styles.category} key={category.codeValue} onClick={onClick} data-value={category.nameValue}>
<div className={styles.category} key={category.code} onClick={onClick} data-value={category.engName}>
<Image
className={categoryValue === category.nameValue ? styles.selectedCategoryImage : styles.categoryImage}
className={categoryValue === category.engName ? styles.selectedCategoryImage : styles.categoryImage}
src={category.categoryImageUrl ?? ''}
alt={category.korNameValue}
alt={category.korName}
width="60"
height="60"
/>
<div className={styles.categoryText}>
{language === 'ko' ? category.korNameValue : category.nameValue}
</div>
{categoryValue === category.nameValue && (
<div className={styles.categoryText}>{language === 'ko' ? category.korName : category.engName}</div>
{categoryValue === category.engName && (
<div className={styles.selectedIconWrapper}>
<CheckIcon className={styles.selectedIcon} />
</div>
Expand Down
25 changes: 25 additions & 0 deletions src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { MetadataRoute } from 'next';
import DOMAIN_URL from '@/lib/constants/domain';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
return [
{
url: DOMAIN_URL,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
},
{
url: `${DOMAIN_URL}/intro`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.8,
},
{
url: `${DOMAIN_URL}/search`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.8,
},
];
}
28 changes: 14 additions & 14 deletions src/app/start-listy/_components/ChoiceCategory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { startListyLocale } from '@/app/start-listy/locale';
import { useLanguage } from '@/store/useLanguage';

interface CategoryProps {
handleChangeCategory: (category: Omit<CategoryType, 'codeValue'>) => void;
handleChangeCategory: (category: Omit<CategoryType, 'code'>) => void;
}

export default function ChoiceCategory({ handleChangeCategory }: CategoryProps) {
Expand All @@ -23,27 +23,27 @@ export default function ChoiceCategory({ handleChangeCategory }: CategoryProps)
queryFn: getCategories,
});

const categories = data ? data?.filter((category) => category.korNameValue !== '전체') : [];
const categories = data ? data?.filter((category) => category.korName !== '전체') : [];

const onClickChangeCategory = (e: MouseEvent<HTMLDivElement>) => {
if (e.target === e.currentTarget) {
return;
}

const targetId = (e.target as HTMLButtonElement).id;
const category = data?.find((category) => category.nameValue === targetId);
const category = data?.find((category) => category.engName === targetId);

if (category) {
handleChangeCategory({
nameValue: category.nameValue,
korNameValue: category.korNameValue,
engName: category.engName,
korName: category.korName,
});
setValue('category', category.nameValue);
setValue('category', category.engName);
} else {
console.log(startListyLocale[language].notFountCategory);
handleChangeCategory({
nameValue: '',
korNameValue: '',
engName: '',
korName: '',
});
}
};
Expand All @@ -54,16 +54,16 @@ export default function ChoiceCategory({ handleChangeCategory }: CategoryProps)
<div onClick={onClickChangeCategory} className={styles.container}>
{categories.map((category) => (
<button
key={category.codeValue}
id={category.nameValue}
key={category.code}
id={category.engName}
type="button"
className={
category.nameValue === getValues('category')
? `${styles.variants[`${category.nameValue}Button`]} ${styles.selected}`
: styles.variants[`${category.nameValue}Button`]
category.engName === getValues('category')
? `${styles.variants[`${category.engName}Button`]} ${styles.selected}`
: styles.variants[`${category.engName}Button`]
}
>
{category.korNameValue}
{category.korName}
</button>
))}
</div>
Expand Down
Loading