-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] 하루한컷 업로드 #14
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
base: develop
Are you sure you want to change the base?
[FEAT] 하루한컷 업로드 #14
Changes from 23 commits
9d1b136
6fabbb4
506304b
afaa8de
91ee31c
99a9353
528d81f
10d3ab3
cf13f28
10d1bd5
48dd0e8
2a675b1
e763d5e
272b1a2
8f7b486
3f99a50
5e6ef76
95f3e7a
57e3a87
889e0aa
3b8a5a2
8a563dd
ec28cdb
0494d6c
7dfdcac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,7 @@ import { SharedDiaryCard } from "@/components/dailyRecord/SharedDiaryCard"; | |
| import DailyRecordData from "@/mock/dailyRecord.json"; | ||
|
|
||
| const DailyRecordPage = () => { | ||
| const MY_ID = 101; | ||
| const MY_ID = 111; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if MY_ID is used elsewhere in the codebase
rg -n "MY_ID" --type=ts --type=tsxRepository: IT-Cotato/12th-SimTok-FE Length of output: 95 🏁 Script executed: # Examine the full context of the page.tsx file
cat -n src/app/day-log/page.tsxRepository: IT-Cotato/12th-SimTok-FE Length of output: 1074 🏁 Script executed: # Search for authentication-related patterns and user context
rg -n "useAuth|useSession|getCurrentUser|getUser|userId" --type=ts --type=tsx -A 2 | head -50Repository: IT-Cotato/12th-SimTok-FE Length of output: 95 🏁 Script executed: # Check if there's a git history showing the change from 101 to 111
git log -p --all -S "MY_ID" -- "src/app/day-log/page.tsx" 2>/dev/null | head -100Repository: IT-Cotato/12th-SimTok-FE Length of output: 50 🏁 Script executed: #!/bin/bash
# Search for MY_ID with general pattern matching
rg "MY_ID" -g "*.ts" -g "*.tsx" --type-list | head -20Repository: IT-Cotato/12th-SimTok-FE Length of output: 457 🏁 Script executed: # Try without file type restriction
rg -n "MY_ID" --include="*.ts" --include="*.tsx"Repository: IT-Cotato/12th-SimTok-FE Length of output: 509 🏁 Script executed: # Search for authentication/user context patterns
rg -n "(useAuth|useSession|getCurrentUser|getUser|userId|authContext)" --include="*.ts" --include="*.tsx" | head -40Repository: IT-Cotato/12th-SimTok-FE Length of output: 509 🏁 Script executed: # Check the mock data file to understand the structure
cat -n src/mock/dailyRecord.json | head -50Repository: IT-Cotato/12th-SimTok-FE Length of output: 1352 🏁 Script executed: # Search for other hardcoded IDs to understand the testing pattern
rg -n "= (10[0-9]|11[0-9])" --include="*.ts" --include="*.tsx" | grep -i "id\|user"Repository: IT-Cotato/12th-SimTok-FE Length of output: 509 🏁 Script executed: #!/bin/bash
# Simple search for MY_ID usage
rg "MY_ID" .Repository: IT-Cotato/12th-SimTok-FE Length of output: 480 🏁 Script executed: # Check if userId 111 exists in the full mock data file
cat src/mock/dailyRecord.json | grep -n "111"Repository: IT-Cotato/12th-SimTok-FE Length of output: 50 🏁 Script executed: # Check the full length of the mock data to see all userIds
tail -20 src/mock/dailyRecord.jsonRepository: IT-Cotato/12th-SimTok-FE Length of output: 423 🏁 Script executed: # Search for authentication/context patterns more simply
rg "useAuth\|useSession\|AuthContext\|UserContext" .Repository: IT-Cotato/12th-SimTok-FE Length of output: 50 🏁 Script executed: # Look at the git history of the dailyRecord file
git log --oneline src/mock/dailyRecord.json 2>/dev/null | head -10Repository: IT-Cotato/12th-SimTok-FE Length of output: 92 하드코딩된 MY_ID는 개발용 모의 데이터입니다. 코드 중복 제거 및 인증 통합 준비 필요 MY_ID = 111은 모의 데이터와 함께 사용되는 개발 단계의 코드입니다. 실제로 dailyRecord.json의 모든 userId는 101~110 범위이므로, 111은 "레코드 없음" 시나리오를 의도적으로 테스트하는 것으로 확인됩니다. 다만, 다음 두 가지를 개선해야 합니다:
🤖 Prompt for AI Agents |
||
| const hasMyRecord = DailyRecordData.some(item => item.userId === MY_ID); | ||
|
|
||
| return ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { BackHeader } from "@/components/common/BackHeader"; | ||
| import { DailyMissionCard } from "@/components/dailyPhoto/DailyMissionCard"; | ||
| import { DailyMissionProgress } from "@/components/dailyPhoto/DailyMissionProgress"; | ||
|
|
||
| //하루한컷 업로드 페이지 | ||
| const DayStoryUpload = () => { | ||
| return ( | ||
| <main className="w-full bg-black"> | ||
| <BackHeader title="하루한컷" titleColor="white" /> | ||
| <DailyMissionProgress /> | ||
| <div className="mt-[143px] flex items-center justify-center"> | ||
| <DailyMissionCard /> | ||
| </div> | ||
| </main> | ||
| ); | ||
| }; | ||
| export default DayStoryUpload; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { SharedDiaryComment } from "@/components/dailyRecord/SharedDiaryChat"; | ||
|
|
||
| const SharedDiaryChatPage = () => { | ||
| return <SharedDiaryComment variant="page" />; | ||
| }; | ||
|
|
||
| export default SharedDiaryChatPage; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| //공유일기 글쓰기 페이지 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 미구현 페이지 추적 필요. 이 파일은 주석만 있고 실제 구현이 없는 플레이스홀더입니다. 사용자가 이 라우트에 접근하면 빈 페이지가 표시될 수 있습니다. 다음 중 하나를 권장합니다:
해당 작업을 위한 이슈를 생성하거나 기본 페이지 구조를 생성하는 데 도움이 필요하신가요? 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,9 +9,15 @@ interface HeaderProps { | |
| title: string; | ||
| timeAgo?: string; // 하루한컷보기에서 사용 | ||
| menuIcon?: boolean; // 채팅페이지에서 사용 | ||
| titleColor?: string; //하루한컷 업로드에서 사용 | ||
| } | ||
|
|
||
| export const BackHeader = ({ title, timeAgo, menuIcon }: HeaderProps) => { | ||
| export const BackHeader = ({ | ||
| title, | ||
| timeAgo, | ||
| menuIcon, | ||
| titleColor = "black", | ||
| }: HeaderProps) => { | ||
| const router = useRouter(); | ||
|
|
||
| return ( | ||
|
|
@@ -21,9 +27,11 @@ export const BackHeader = ({ title, timeAgo, menuIcon }: HeaderProps) => { | |
| onClick={() => router.back()} | ||
| className="absolute top-1/2 left-4 -translate-y-1/2 cursor-pointer" | ||
| > | ||
| <BackIcon className="h-6 w-6" /> | ||
| <BackIcon className={`text-${titleColor} h-6 w-6`} /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 동적 Tailwind 클래스명이 작동하지 않습니다. Tailwind CSS의 JIT 컴파일러는 빌드 타임에 정적 분석을 통해 클래스를 생성합니다. 🔎 해결 방법방법 1 (권장): 조건부 렌더링 사용 - <BackIcon className={`text-${titleColor} h-6 w-6`} />
+ <BackIcon className={`${titleColor === "white" ? "text-white" : "text-black"} h-6 w-6`} /> <h1
- className={`text-h1 flex w-full items-center justify-center whitespace-nowrap text-${titleColor}`}
+ className={`text-h1 flex w-full items-center justify-center whitespace-nowrap ${titleColor === "white" ? "text-white" : "text-black"}`}
>방법 2: safelist에 추가 (tailwind.config에서) // tailwind.config.js
module.exports = {
safelist: [
'text-white',
'text-black',
],
// ...
}방법 3: style prop 사용 - <BackIcon className={`text-${titleColor} h-6 w-6`} />
+ <BackIcon className="h-6 w-6" style={{ color: titleColor }} />방법 1이 타입 안전성과 Tailwind의 디자인 시스템 활용 측면에서 가장 권장됩니다. Also applies to: 33-33 🤖 Prompt for AI Agents |
||
| </button> | ||
| <h1 className="text-h1 flex w-full items-center justify-center whitespace-nowrap text-black"> | ||
| <h1 | ||
| className={`text-h1 flex w-full items-center justify-center whitespace-nowrap text-${titleColor}`} | ||
| > | ||
| {title} | ||
| </h1> | ||
| {timeAgo && ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,41 @@ | ||||||
| "use client"; | ||||||
| import { useState } from "react"; | ||||||
|
|
||||||
| import { WEEK_DAYS } from "@/constants/dayToKorean"; | ||||||
| import { MISSION_STATUS } from "@/constants/missionCard"; | ||||||
|
|
||||||
| import { getTodayIndex } from "@/utils/getCurrentDay"; | ||||||
|
|
||||||
| export const DailyMissionCard = () => { | ||||||
| const [status, setStatus] = | ||||||
| useState<keyof typeof MISSION_STATUS>("NOT_STARTED"); | ||||||
| const currentDayIndex = getTodayIndex(); | ||||||
| const currentDay = WEEK_DAYS[currentDayIndex]; // 현재 요일 | ||||||
|
|
||||||
| const subtitle = | ||||||
| typeof MISSION_STATUS[status].subtitle === "function" | ||||||
| ? `${MISSION_STATUS[status].subtitle(currentDay)}요일` | ||||||
| : MISSION_STATUS[status].subtitle; | ||||||
|
|
||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. subtitle 계산 시 요일을 붙이는 부분이 "요일"을 하드코딩하고 있어서, 나중에 subtitle 함수가 이미 요일까지 포함한 문구를 반환한다면 중복될 수 있을 것 같아요.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 유틸 분리하라는게 무슨말인지 이해가 안가요ㅠ 현재 로직은 subtitle을 미션 완료 상태에 따라서 상수로 빼둔 상태이고 미션이 NOT_STARTED 상태라면 요일의 앞부분을 함수로 가져오는 방식입니다. 현재의 요일의 인덱스를 가져와서 WEEK_DAYS에서 해당 요일을 한국어로 선언되어있는 배열에서 값을 가져오는 방식입니다.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기서
이런식으로 |
||||||
| return ( | ||||||
| <section className="flex h-[385px] w-[353px] flex-col items-center justify-center gap-5 rounded-2xl bg-white"> | ||||||
| <div className="flex flex-col items-center justify-center"> | ||||||
| <h3 className="text-green-01 text-h3"> | ||||||
| {MISSION_STATUS[status].title} | ||||||
| </h3> | ||||||
| <p className="text-neutral-06 text-sub1-r -mt-[4px]">{subtitle}</p> | ||||||
| </div> | ||||||
| <div className="bg-neutral-11 h-28 w-28 rounded-full"> | ||||||
| {/* 아이콘 영역 */} | ||||||
| </div> | ||||||
| <div className="text-sub-number p-[10px]"> | ||||||
| 오늘의 하늘을 공유해주세요. | ||||||
| </div> | ||||||
| <button | ||||||
| className={`${status == "NOT_STARTED" ? "bg-gradient-orange" : "bg-green-01"} text-button-sb h-[50px] w-[90px] cursor-pointer rounded-2xl text-white`} | ||||||
|
||||||
| className={`${status == "NOT_STARTED" ? "bg-gradient-orange" : "bg-green-01"} text-button-sb h-[50px] w-[90px] cursor-pointer rounded-2xl text-white`} | |
| className={`${status === "NOT_STARTED" ? "bg-gradient-orange" : "bg-green-01"} text-button-sb h-[50px] w-[90px] cursor-pointer rounded-2xl text-white`} |
🤖 Prompt for AI Agents
In @src/components/dailyPhoto/DailyMissionCard.tsx at line 35, In
DailyMissionCard update the conditional className expression to use strict
equality (replace `==` with `===`) when comparing the `status` variable so the
ternary `status === "NOT_STARTED" ? "bg-gradient-orange" : "bg-green-01"` is
used, ensuring type-safe comparison in the JSX expression that builds the
className string.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| "use client"; | ||
|
|
||
| import CheckIcon from "@/assets/check.svg"; | ||
| import QuestionIcon from "@/assets/questionMark.svg"; | ||
|
|
||
| import { WEEK_DAYS } from "@/constants/dayToKorean"; | ||
|
|
||
| import { getWeekDayStatus } from "@/utils/getCurrentDay"; | ||
|
|
||
| export const DailyMissionProgress = () => { | ||
| return ( | ||
| <ul className="scrollbar-hide mt-8 flex gap-[9px] overflow-x-auto px-4"> | ||
| {WEEK_DAYS.map((item, index) => { | ||
| const status = getWeekDayStatus(index); // past | today | future | ||
| const isTodayCompleted = false; | ||
|
|
||
| const showCheck = | ||
| status === "past" || (status === "today" && isTodayCompleted); | ||
|
|
||
| return ( | ||
| <li key={item} className="h-[82px] w-[74px] shrink-0"> | ||
| <div | ||
| className={`${showCheck ? "bg-spring-01" : "bg-white"} ${status != "future" ? "border-mint-01" : "border-neutral-08"} flex h-full flex-col items-center justify-center gap-[3px] rounded-2xl border border-solid px-[10px] py-[6px]`} | ||
| > | ||
| {showCheck ? ( | ||
| <div className="bg-mint-01 flex h-8 w-8 items-center justify-center rounded-full"> | ||
| <CheckIcon className="text-spring-01 h-6 w-6" /> | ||
| </div> | ||
| ) : ( | ||
| <div | ||
| className={`${status === "today" ? "bg-mint-01" : "bg-neutral-08"} flex h-8 w-8 items-center justify-center rounded-full`} | ||
| > | ||
| <QuestionIcon | ||
| className={`${status === "today" ? "text-white" : "text-neutral-06"} h-6 w-6`} | ||
| /> | ||
| </div> | ||
| )} | ||
| <span | ||
| className={`text-sub1-sb ${status === "today" ? "text-neutral-01" : "text-neutral-06"}`} | ||
| > | ||
| {item} | ||
| </span> | ||
| </div> | ||
| </li> | ||
| ); | ||
| })} | ||
| </ul> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import Image from "next/image"; | ||
|
|
||
| import { DiaryComment } from "@/types/diaryComment.type"; | ||
|
|
||
| import { formatDate } from "@/utils/formatDate"; | ||
|
|
||
| interface CommentListProps { | ||
| comments: DiaryComment[]; | ||
| } | ||
|
|
||
| export const CommentList = ({ comments }: CommentListProps) => { | ||
| if (comments.length === 0) { | ||
| return ( | ||
| <div className="flex flex-col items-center justify-center pt-[109px]"> | ||
| <p className="text-sub1-sb text-neutral-01">아직 댓글이 없습니다</p> | ||
| <p className="text-sub2-r text-neutral-06">댓글을 남겨보세요!</p> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <ul className="flex flex-col"> | ||
| {comments.map(comment => ( | ||
| <li key={comment.id} className="flex gap-[10px] px-4 py-[10px]"> | ||
| <Image | ||
| src={comment.profileImg} | ||
| alt={comment.userName} | ||
| width={56} | ||
| height={56} | ||
| className="h-14 w-14 rounded-2xl object-cover" | ||
| /> | ||
| <div className="flex flex-1 justify-between"> | ||
| <div className="flex flex-col"> | ||
| <p className="text-d3 text-black">{comment.userName}</p> | ||
| <p className="text-sub1-r text-neutral-05">{comment.comment}</p> | ||
| </div> | ||
| <p className="text-body3 text-neutral-05 flex flex-col self-start"> | ||
| {formatDate(comment.createdAt)} | ||
| </p> | ||
| </div> | ||
| </li> | ||
| ))} | ||
| </ul> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,39 +1,43 @@ | ||
| "use client"; | ||
| import { useRouter } from "next/navigation"; | ||
|
|
||
| import CheckIcon from "@/assets/check.svg"; | ||
|
|
||
| interface RecordMissionInfoProps { | ||
| hasMyRecord: boolean; | ||
| } | ||
| export const RecordMissionInfo = ({ hasMyRecord }: RecordMissionInfoProps) => { | ||
| const router = useRouter(); | ||
| return ( | ||
| <section className="border-mint-01 bg-neutral-11 mx-4 mt-[13.5px] cursor-pointer rounded-2xl border"> | ||
| <div className="flex h-[76px] items-center justify-between p-[10px]"> | ||
| {hasMyRecord ? ( | ||
| <> | ||
| <p className="text-sub1-sb text-neutral-07"> | ||
| 오늘의 챌린지 미션을 완료했어요. | ||
| </p> | ||
| <div className="flex flex-col items-center gap-[7px]"> | ||
| <div className="bg-neutral-07 flex h-6 w-6 items-center justify-center rounded-full"> | ||
| <CheckIcon className="h-4 w-4 text-white" /> | ||
| </div> | ||
|
|
||
| <p className="text-sub2-r text-neutral-06 -mt-[4px] px-[6px]"> | ||
| 미션완료 | ||
| </p> | ||
| <section className="border-mint-01 bg-neutral-11 mx-4 mt-[13.5px] rounded-2xl border"> | ||
| {hasMyRecord ? ( | ||
| <div className="flex h-[76px] items-center justify-between p-[10px]"> | ||
| <p className="text-sub1-sb text-neutral-07"> | ||
| 오늘의 챌린지 미션을 완료했어요. | ||
| </p> | ||
| <div className="flex flex-col items-center gap-[7px]"> | ||
| <div className="bg-neutral-07 flex h-6 w-6 items-center justify-center rounded-full"> | ||
| <CheckIcon className="h-4 w-4 text-white" /> | ||
| </div> | ||
| </> | ||
| ) : ( | ||
| <> | ||
| <p className="text-sub1-sb text-black"> | ||
| 오늘의 챌린지 미션이 도착했어요! | ||
|
|
||
| <p className="text-sub2-r text-neutral-06 -mt-[4px] px-[6px]"> | ||
| 미션완료 | ||
| </p> | ||
| <div className="flex h-full flex-col justify-end"> | ||
| <p className="text-green-01 text-sub2-r px-[6px]">시작하기</p> | ||
| </div> | ||
| </> | ||
| )} | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ) : ( | ||
| <div | ||
| className="flex h-[76px] cursor-pointer items-center justify-between p-[10px]" | ||
| onClick={() => router.push("/day-story/upload")} | ||
| > | ||
| <p className="text-sub1-sb text-black"> | ||
| 오늘의 챌린지 미션이 도착했어요! | ||
| </p> | ||
| <div className="flex h-full flex-col justify-end"> | ||
| <p className="text-green-01 text-sub2-r px-[6px]">시작하기</p> | ||
| </div> | ||
| </div> | ||
| )} | ||
| </section> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
@use-funnel/next version 0.0.22 compatibility Next.js 16 React 19💡 Result:
Short answer: No — there’s no published @use-funnel/next v0.0.22 on npm, and the package’s docs list supported React as ^16.8, so the current release is not explicitly compatible with React 19 / Next.js 16. [1][2][3]
Sources:
If you want, I can: 1) check the package’s GitHub for any unreleased v0.0.22/branches or compatibility notes, or 2) suggest a migration/workaround (shim/adapter) for using it with Next.js 16 + React 19. Which would you prefer?
🏁 Script executed:
Repository: IT-Cotato/12th-SimTok-FE
Length of output: 192
🌐 Web query:
@toss/use-funnel vs @use-funnel/next differences API migration💡 Result:
Summary of key differences and migration steps from @toss/use-funnel → @use-funnel (/@use-funnel/next):
What changed (high-level)
Concrete migration mappings
Step list → createFunnelSteps
Components → render by step or funnel.Render
withState() → type generics on createFunnelSteps/useFunnel
onStepChange callback → observe funnel.step
Initial step via router query
Migration checklist (minimal)
References
If you want, tell me one example file from your repo (old code) and I’ll produce the exact migrated code to @use-funnel/next.
버전 번호 확인 및 호환성 검증 필수.
npm에 게시된 @use-funnel/next의 최신 버전은 v0.0.21이며, v0.0.22는 존재하지 않습니다. 또한 공식 문서에서 지원하는 React 버전은 ^16.8로 명시되어 있어 React 19와의 명시적 호환성이 보장되지 않습니다.
@toss/use-funnel에서 @use-funnel/next로의 마이그레이션에는 다음과 같은 주요 breaking changes가 있습니다:
createFunnelSteps()사용)<Funnel>/<Funnel.Step>→funnel.Render또는 조건부 렌더링)withState()HOC → createFunnelSteps 제네릭 타입)onStepChange→useEffectwithfunnel.step)다음을 반드시 확인하세요:
🤖 Prompt for AI Agents