Skip to content

Commit

Permalink
✨ Feat - 세미나 리스트 노션 api 연결 #44
Browse files Browse the repository at this point in the history
  • Loading branch information
bianbbc87 committed May 7, 2024
1 parent c02d023 commit 3601137
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 38 deletions.
4 changes: 4 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
// notion image doamin
images: {
domains: ['prod-files-secure.s3.us-west-2.amazonaws.com'],
},
webpack(config) {
const fileLoaderRule = config.module.rules.find((rule) =>
rule.test?.test?.('.svg'),
Expand Down
59 changes: 59 additions & 0 deletions src/app/api/seminar/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Client } from '@notionhq/client';
import { NextRequest } from 'next/server';

const notion = new Client({
auth: process.env.NOTION_SECRET_KEY,
});

// seminar 데이터 query select, 오름차순
async function querySeminarData(databaseId: string, tag: string): Promise<any[]> {
try {
const response = await notion.databases.query({
database_id: databaseId,
filter: {
property: 'Tags',
multi_select: {
contains: tag
}
},
sorts: [
{
property: 'Date',
direction: 'ascending'
}
]
});

return response.results;
} catch (error) {
console.error('Error querying Notion database and fetching member data:', JSON.stringify(error));
throw error;
}
}

type Data = {
items?: any[];
message: string;
};

export async function GET(req: NextRequest) {
const databaseId = process.env.NOTION_SEMINAR_DATABASE_ID || '';
const tag = '🏕️ Camping Seminar';

try {
const data = await querySeminarData(databaseId, tag);
return new Response(JSON.stringify({ data, message: 'Success' }), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
});
} catch (error) {
return new Response(JSON.stringify({ message: `Failed: ${error?.toString()}` }), {
status: 500,
headers: {
'Content-Type': 'application/json',
},
});
}
}
18 changes: 8 additions & 10 deletions src/app/seminar/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
'use client';

import SeminarHeader from '@/components/seminar/header/SeminarHeader';
import SeminarMenuBar from '@/components/seminar/menubar/SeminarMenuBar';
import SeminarThumbnailList from '@/components/seminar/thumbnail/SeminarThumbnailList';
import SeminarToggle from '@/components/seminar/toggle/SeminarToggle';
import React, { useState } from 'react';
import { refactorSeminarData } from '@/hooks/seminar/notionDataRefactor';

const SeminarPage = async () => {
// seminar 데이터 가져오기
const seminarResponse = await fetch('http://localhost:3001/api/seminar');
const seminarList = await seminarResponse.json();

const SeminarPage = () => {
const [selectedCategory, setSelectedCategory] = useState<string>('all');
const seminars = refactorSeminarData(seminarList.data || []);

return <section className="flex justify-center">
<div className="max-w-[1200px] desktop:px-10 tablet:px-10 px-4 bg-mono_black">
Expand All @@ -18,11 +19,8 @@ const SeminarPage = () => {
{/* toggle */}
<SeminarToggle />

{/* select button */}
<SeminarMenuBar selectedCategory={selectedCategory} setSelectedCategory={setSelectedCategory} />

{/* seminar list */}
<SeminarThumbnailList selectedCategory={selectedCategory} />
<SeminarThumbnailList seminar={seminars} />
<div className="h-[7.5rem]"></div>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/seminar/header/SeminarHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';

import BannerImg from '@/svg/seminar/seminar_banner.svg';
import { motion } from 'framer-motion';
import Link from 'next/link';
import { OpenSeminar } from '@/interfaces/seminar/openSeminar';
import { OPEN_SEMINAR_DATA } from '@/constants/seminar/openSeminarData';

/**
Expand Down
10 changes: 7 additions & 3 deletions src/components/seminar/thumbnail/SeminarThumbnail.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SeminarMember } from '@/interfaces/seminar/seminarMember';
import { SeminarThumbnail } from '@/interfaces/seminar/seminarThumbnail';
import Image from 'next/image';

Expand All @@ -12,17 +13,20 @@ import Image from 'next/image';
* Renders the header component for the recruitment section.
* @returns The rendered header component.
*/
const SeminarThumbnailBox = ({ data }: { data: SeminarThumbnail }) => {
const SeminarThumbnailBox = ({ seminar }: { seminar: SeminarThumbnail }) => {
return (
<div className="w-full aspect-w-16 aspect-h-9">
<div className='rounded-lg overflow-hidden'>
<Image
src={data.seminar_image_url}
alt={`${data.presenter_name}'s_seminarimage`}
src={seminar.seminar_image_url}
alt={`${seminar.title} image`}
width={1600}
height={900}
quality={100}
priority
rel="preload"
/>
</div>
</div>
);
};
Expand Down
55 changes: 31 additions & 24 deletions src/components/seminar/thumbnail/SeminarThumbnailList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import React, { useState } from 'react';
import SeminarThumbnailBox from './SeminarThumbnail';
import { SEMINAR_DATA } from '@/constants/seminar/seminarData';
import Link from 'next/link'
import { motion } from 'framer-motion';
import { seminarCardVariants } from '@/constants/seminar/seminarCardVariants';
import SeminarPagination from './SeminarPagination';
import { SeminarThumbnail } from '@/interfaces/seminar/seminarThumbnail';
import SeminarMenuBar from '../menubar/SeminarMenuBar';

/**
* @description
Expand All @@ -22,12 +23,13 @@ import SeminarPagination from './SeminarPagination';
* @returns The rendered header component.
*/

const SeminarThumbnailList = ({ selectedCategory }: { selectedCategory: string }) => {
const SeminarThumbnailList = ({ seminar }: { seminar:SeminarThumbnail[] }) => {
const [currentPage, setCurrentPage] = useState(1);
const [selectedCategory, setSelectedCategory] = useState<string>('all');
const itemsPerPage = 12; // 한 페이지당 표시할 항목 수

// topic으로 데이터 필터링
const filteredData = selectedCategory !== "all" ? SEMINAR_DATA.filter(seminar => seminar.topic === selectedCategory) : SEMINAR_DATA;
const filteredData = selectedCategory !== "all" ? seminar.filter(seminar => seminar.topic === selectedCategory) : seminar;

// 페이지네이션
const indexOfLastItem = currentPage * itemsPerPage;
Expand All @@ -48,14 +50,18 @@ const SeminarThumbnailList = ({ selectedCategory }: { selectedCategory: string }


return (
<div>
{/* select button */}
<SeminarMenuBar selectedCategory={selectedCategory} setSelectedCategory={setSelectedCategory} />

<div className="mt-10">
{/* 썸네일 리스트 */}

{/* desktop인 경우 */}
<div className="desktop:grid tablet:hidden hidden desktop:grid-cols-3 gap-x-8 gap-y-10">
{currentItems.map((seminar) => (
{currentItems.map((seminar:SeminarThumbnail, index:number) => (
<motion.section
key={seminar.id}
key={index}
whileHover={{ scale: 1.05, transition: { duration: 0.3 } }}
whileTap={{ scale: 0.8 }}
initial={{ y: 20, opacity: 0 }}
Expand All @@ -65,23 +71,23 @@ const SeminarThumbnailList = ({ selectedCategory }: { selectedCategory: string }
variants={seminarCardVariants}
style={{ transformOrigin: '10% 60%' }}
>
<Link
href={`/seminar/${seminar.id}`}
>
<SeminarThumbnailBox
key={seminar.id}
data={seminar}
/>
</Link>
<Link
href={`/seminar/${seminar.id}`}
>
<SeminarThumbnailBox
key={index}
seminar={seminar}
/>
</Link>
</motion.section>
))}
</div>

{/*tablet, mobile인 경우 */}
<div className="desktop:hidden grid tablet:grid-cols-2 grid-cols-1 gap-x-8 gap-y-10">
{filteredData.map((seminar) => (
{filteredData.map((seminar:SeminarThumbnail, index:number) => (
<motion.section
key={seminar.id}
key={index}
whileHover={{ scale: 1.05, transition: { duration: 0.3 } }}
whileTap={{ scale: 0.8 }}
initial={{ y: 20, opacity: 0 }}
Expand All @@ -90,15 +96,15 @@ const SeminarThumbnailList = ({ selectedCategory }: { selectedCategory: string }
viewport={{ once: true, amount: 0.9 }}
variants={seminarCardVariants}
style={{ transformOrigin: '10% 60%' }}
>
>
<Link
href={`/seminar/${seminar.id}`}
>
<SeminarThumbnailBox
key={seminar.id}
data={seminar}
/>
</Link>
href={`/seminar/${seminar.id}`}
>
<SeminarThumbnailBox
key={index}
seminar={seminar}
/>
</Link>
</motion.section>
))}
</div>
Expand All @@ -110,6 +116,7 @@ const SeminarThumbnailList = ({ selectedCategory }: { selectedCategory: string }
/>

</div>
</div>
);
};
export default SeminarThumbnailList;
Expand Down

0 comments on commit 3601137

Please sign in to comment.