Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
11 changes: 11 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',

images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'sprint-fe-project.s3.ap-northeast-2.amazonaws.com',
port: '',
pathname: '/**',
},
Comment on lines +5 to +12

Choose a reason for hiding this comment

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

해당 코드를 추가 하신 이유가 무엇인가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

외부 이미지를 사용하기 위해 추가한 설정입니다.
Next.js의 Image 컴포넌트는 보안상의 이유로 외부 도메인의 이미지를 기본적으로 차단합니다.

받아온 이미지 URL을 보면

"imageUrl": "https://sprint-fe-project.s3.ap-northeast-2.amazonaws.com/taskify/task_image/7-6_50923_1749446154135.jpeg",

이렇고, 외부 API에서 데이터를 받아올때. 이미지 URL은 AWS S3에 저장해서 제공하고 있습니다.(amazonaws)

Next.js에서 이 이미지를 표시하려면 S3 도메인을 허용해야 했습니다.

images: {
  remotePatterns: [
    {
      protocol: 'https',        // HTTPS만 허용
      hostname: 'sprint-fe-project.s3.ap-northeast-2.amazonaws.com', // AWS S3 버킷
      port: '',                 // 기본 포트 (443)
      pathname: '/**',          // 모든 경로 허용
    },
  ],
},

Choose a reason for hiding this comment

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

답변 감사합니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

외부 도메인의 이미지를 차단하는 지는 처음 알았네용 😮

],
},
}

export default nextConfig
3 changes: 3 additions & 0 deletions public/images/calendar.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 public/images/config.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 public/images/plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file removed src/app/api/.gitkeep
Empty file.
19 changes: 19 additions & 0 deletions src/app/api/axiosClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import axios from 'axios'

const axiosClient = axios.create({
baseURL: 'https://sp-taskify-api.vercel.app',
})

// 작업용 임시 토큰
const TEMP_TOKEN =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NTc4NiwidGVhbUlkIjoiNy02IiwiaWF0IjoxNzQ5MzEyOTI3LCJpc3MiOiJzcC10YXNraWZ5In0.JFrNYvsX_b5-yCMm-Nsmp56gaVwzJ7JfBqYirBR3qw0'

axiosClient.interceptors.request.use((config) => {
if (TEMP_TOKEN) {
config.headers['Authorization'] = `Bearer ${TEMP_TOKEN}`
}

return config
})
Comment on lines +10 to +16

This comment was marked as resolved.


export default axiosClient
45 changes: 45 additions & 0 deletions src/app/api/useCards.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//Colums id: 50923,50924,50925,50926
//나중에는 fetchColumns의 결과로 받은 컬럼 아이디를 모아서 넣어야할듯.
//size일단 10으로 하고, 나중에 커서아이디 받아서 무한 스크롤 구현해야 함.
import { useQuery } from '@tanstack/react-query'
Copy link
Contributor

Choose a reason for hiding this comment

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

tanStack Query 사용하셨군용!!


import axiosClient from './axiosClient'

export interface Assignee {
id: number
nickname: string
profileImageUrl: string | null
}
export interface Card {
id: number
title: string
description: string
tags: string[]
dueDate: string
assignee: Assignee
imageUrl: string
teamId: string
dashboardId: number
columnId: number
createdAt: string
updatedAt: string
}
export interface CardResponse {
cards: Card[]
totalCount: number
cursorId: number
}

export async function fetchCards(columnId: number): Promise<CardResponse> {
const res = await axiosClient.get<CardResponse>(
`/7-6/cards?size=10&columnId=${columnId}`,
)
return res.data
}

This comment was marked as resolved.


export default function useCards(column: number) {
return useQuery<CardResponse>({
queryKey: ['columnId', column],
queryFn: () => fetchCards(column),
})
}
32 changes: 32 additions & 0 deletions src/app/api/useColumns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useQuery } from '@tanstack/react-query'

import axiosClient from './axiosClient'

//타입
export interface Column {
id: number
title: string
teamId: string
dashboardId: number
createdAt: string
updatedAt: string
}
export interface ColumnsResponse {
data: Column[]
}

//fetch 함수 (API 호출 전용)
export async function fetchColums(dashboardId: number): Promise<Column[]> {
const res = await axiosClient.get<ColumnsResponse>(
`/7-6/columns?dashboardId=${dashboardId}`,
)
return res.data.data
}

//useQuery
export default function useColumns(dashboardId: number) {
return useQuery<Column[]>({
queryKey: ['columns', dashboardId],
queryFn: () => fetchColums(dashboardId),
})
}
Empty file removed src/app/dashboard/.gitkeep
Empty file.
28 changes: 28 additions & 0 deletions src/app/dashboard/[id]/Card/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Image from 'next/image'

import type { Card } from '@/app/api/useCards'

import Tags from './Tags'

export default function Card({ card }: { card: Card }) {
const { imageUrl, title, tags, dueDate, assignee } = card
return (
<div className="BG-white Border-section relative w-314 rounded-6 border-solid px-20 py-16">
Todo Card
{imageUrl && (
<Image
src={imageUrl}
alt="카드 이미지"
width={400}
height={600}
className="h-auto w-full rounded-6 object-contain"
priority
/>
)}
<p>{title}</p>
<Tags tags={tags} />
<p>{dueDate}</p>
<p>프로필</p>
</div>
)
}
17 changes: 17 additions & 0 deletions src/app/dashboard/[id]/Card/Tags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default function Tags({ tags }: { tags: string[] }) {
//태그 컬러 - 랜덤 배정
//카드 생성 시 - 동일 태그 입력 불가하도록
return (
<div className="flex gap-6">
{tags.map((tag) => (
<span
key={tag}
className="inline-block whitespace-nowrap rounded-4 px-9 pb-3 pt-5"
style={{ backgroundColor: '#F7DBF0', color: '#D549B6' }}
>
{tag}
</span>
))}
</div>
)
}
44 changes: 44 additions & 0 deletions src/app/dashboard/[id]/Column/Column.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Image from 'next/image'

import useCards from '@/app/api/useCards'
import type { Column } from '@/app/api/useColumns'

import Card from '../Card/Card'
export default function Column({ column }: { column: Column }) {
const { id, title }: { id: number; title: string } = column
const { data, isLoading, error } = useCards(id)

if (isLoading) return <p>loading...</p>
if (error) return <p>error...{error.message}</p>

return (
<div className="BG-gray Border-column flex w-354 shrink-0 flex-col gap-16 p-20">
<div className="mb-24 flex items-center justify-between">
<div className="flex items-center">
<div className="mb-7 mr-8 size-8 rounded-25 bg-blue-500"></div>
<h2 className="mr-12 text-18 font-bold leading-none">{title}</h2>
<span className="Text-gray block size-20 rounded-4 bg-[#EEEEEE] pt-3 text-center text-12 font-medium leading-tight dark:bg-[#2E2E2E]">
{data?.totalCount}
</span>
</div>
<Image
src={'/images/config.svg'}
alt="컬럼 설정"
width={20}
height={20}
/>
</div>
<button className="BG-white Border-btn rounded-6 px-146 py-9">
<div className="flex h-22 w-22 items-center justify-center rounded-4 bg-blue-100">
<Image
src={'/images/plus.svg'}
alt="추가하기"
width={10}
height={10}
/>
</div>
</button>
{data?.cards.map((card) => <Card key={card.id} card={card} />)}
</div>
)
}
37 changes: 37 additions & 0 deletions src/app/dashboard/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client'

import Image from 'next/image'

import useColumns from '@/app/api/useColumns'

import Column from './Column/Column'
export default function DashboardID() {
const dashboard = 15120

This comment was marked as resolved.

const { data: columns, isLoading, error } = useColumns(dashboard)
if (isLoading) return <p>loading...</p>
if (error) return <p>error...{error.message}</p>

return (
<>
<div className="fixed left-0 h-1080 w-300 bg-gray-100">사이드바</div>
<div className="ml-300">
<div className="flex">
{columns?.map((column) => <Column key={column.id} column={column} />)}
<div className="BG-gray Border-column p-20">
<button className="BG-white Border-btn flex items-center gap-12 whitespace-nowrap rounded-8 px-85 pb-20 pt-24 text-18 font-bold">
<span>새로운 컬럼 추가하기</span>
<div className="flex h-22 w-22 items-center justify-center rounded-4 bg-blue-100">
<Image
src={'/images/plus.svg'}
alt="플러스 아이콘"
width={10}
height={10}
/>
</div>
</button>
</div>
</div>
</div>
</>
)
}
3 changes: 3 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ body {
.Border-section {
@apply border border-[#D9D9D9] dark:border-[#000000];
}
.Border-column {
@apply border-r border-[#EEEEEE] dark:border-[#262626];
}
.BG-addPhoto {
@apply bg-[#F5F5F5] dark:bg-[#2E2E2E];
}
Expand Down
7 changes: 6 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import './globals.css'
import type { Metadata } from 'next'

import { Providers } from './providers'
import ThemeToggle from './shared/components/ThemeToggle'

export const metadata: Metadata = {
title: 'Coplan',
Expand All @@ -20,7 +21,11 @@ export default function RootLayout({
return (
<html lang="en" suppressHydrationWarning>
<body>
<Providers>{children}</Providers>
<Providers>
<ThemeToggle />
{/* 푸쉬하기 전에 이거 삭제해야함 */}
{children}
</Providers>
</body>
</html>
)
Expand Down
17 changes: 13 additions & 4 deletions src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
'use client'

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ThemeProvider } from 'next-themes'
import { ReactNode } from 'react'
import { ReactNode, useState } from 'react'

export function Providers({ children }: { children: ReactNode }) {
const [queryClient] = useState(() => new QueryClient())

return (
<ThemeProvider attribute="class" defaultTheme="system" enableSystem={true}>
{children}
</ThemeProvider>
<QueryClientProvider client={queryClient}>
Copy link
Contributor

Choose a reason for hiding this comment

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

tanStack Query의 경우도 provider로 감싸줘야 하는군용

<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem={true}
>
{children}
</ThemeProvider>
</QueryClientProvider>
)
}