Skip to content
Open
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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cSpell.words": ["autoincrement"]
}
106 changes: 35 additions & 71 deletions app/create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
"use client";

import { createDiary } from "@/src/features/diary/actions/createDiary";
import Moods from "@/src/features/diary/ui/moods";
import Link from "next/link";
import { useState } from "react";

export default function CreateDiary() {
const [formData, setFormData] = useState({
title: "",
content: "",
mood: "",
weather: "",
categoryId: "",
tags: "",
isPublic: false,
});
import { useActionState, useEffect } from "react";

const moods = [
{ value: "happy", label: "😊 행복", emoji: "😊" },
{ value: "sad", label: "😢 슬픔", emoji: "😢" },
{ value: "angry", label: "😠 화남", emoji: "😠" },
{ value: "excited", label: "🤩 신남", emoji: "🤩" },
{ value: "calm", label: "😌 평온", emoji: "😌" },
{ value: "nervous", label: "😰 긴장", emoji: "😰" },
];
const initialState = {
success: false,
message: "",
};

export default function CreateDiaryPage() {
const [state, formAction] = useActionState(createDiary, initialState);

const weathers = [
{ value: "sunny", label: "☀️ 맑음", emoji: "☀️" },
Expand All @@ -38,15 +28,12 @@ export default function CreateDiary() {
{ id: "5", name: "꿈", color: "#F59E0B" },
];

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// 실제 저장 로직은 나중에 구현
console.log("일기 저장:", formData);
};
useEffect(() => {
console.log(state);
});

return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
{/* Navigation */}
<nav className="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
Expand All @@ -59,59 +46,39 @@ export default function CreateDiary() {
<Link href="/" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 px-3 py-2 rounded-md text-sm font-medium">
</Link>
<Link href="/about" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 px-3 py-2 rounded-md text-sm font-medium">
소개
</Link>
</div>
</div>
</div>
</nav>

{/* Main Content */}
<main className="max-w-4xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">새로운 일기 작성</h1>
<p className="mt-2 text-gray-600 dark:text-gray-400">오늘의 소중한 순간을 기록해보세요</p>
</div>

<form onSubmit={handleSubmit} className="space-y-6">
<form action={formAction} className="space-y-6">
{/* 숨겨진 필수 필드들 */}
<input type="hidden" name="userId" value="1" />

<div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 border border-gray-200 dark:border-gray-700">
{/* Title */}
<div className="mb-6">
<label htmlFor="title" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
제목 *
</label>
<label htmlFor="title" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"></label>
<input
type="text"
id="title"
name="title"
value={formData.title}
onChange={(e) => setFormData((prev) => ({ ...prev, title: e.target.value }))}
placeholder="오늘의 일기 제목을 입력하세요"
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
required
/>
</div>

{/* Mood & Weather */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">기분 *</label>
<div className="grid grid-cols-3 gap-2">
{moods.map((mood) => (
<button
key={mood.value}
type="button"
onClick={() => setFormData((prev) => ({ ...prev, mood: mood.value }))}
className={`p-3 rounded-lg border text-sm font-medium transition-colors ${
formData.mood === mood.value
? "border-blue-500 bg-blue-50 dark:bg-blue-900 text-blue-700 dark:text-blue-300"
: "border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500 dark:bg-gray-700"
}`}
>
{mood.label}
</button>
))}
<Moods />
</div>
</div>

Expand All @@ -122,9 +89,8 @@ export default function CreateDiary() {
<button
key={weather.value}
type="button"
onClick={() => setFormData((prev) => ({ ...prev, weather: weather.value }))}
className={`p-3 rounded-lg border text-sm font-medium transition-colors ${
formData.weather === weather.value
weather.value === weather.value
? "border-blue-500 bg-blue-50 dark:bg-blue-900 text-blue-700 dark:text-blue-300"
: "border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500 dark:bg-gray-700"
}`}
Expand All @@ -136,7 +102,6 @@ export default function CreateDiary() {
</div>
</div>

{/* Content */}
<div className="mb-6">
<label htmlFor="content" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
내용 *
Expand All @@ -145,25 +110,21 @@ export default function CreateDiary() {
id="content"
name="content"
rows={8}
value={formData.content}
onChange={(e) => setFormData((prev) => ({ ...prev, content: e.target.value }))}
placeholder="오늘 하루는 어땠나요? 자유롭게 작성해보세요..."
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white resize-none"
required
/>
</div>

{/* Category */}
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">카테고리</label>
<div className="flex flex-wrap gap-2">
{categories.map((category) => (
<button
key={category.id}
type="button"
onClick={() => setFormData((prev) => ({ ...prev, categoryId: category.id }))}
className={`px-4 py-2 rounded-full text-sm font-medium text-white transition-opacity ${
formData.categoryId === category.id ? "opacity-100 ring-2 ring-offset-2 ring-blue-500" : "opacity-70 hover:opacity-100"
category.id === category.id ? "opacity-100 ring-2 ring-offset-2 ring-blue-500" : "opacity-70 hover:opacity-100"
}`}
style={{ backgroundColor: category.color }}
>
Expand All @@ -173,7 +134,6 @@ export default function CreateDiary() {
</div>
</div>

{/* Tags */}
<div className="mb-6">
<label htmlFor="tags" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
태그
Expand All @@ -182,30 +142,34 @@ export default function CreateDiary() {
type="text"
id="tags"
name="tags"
value={formData.tags}
onChange={(e) => setFormData((prev) => ({ ...prev, tags: e.target.value }))}
placeholder="태그를 쉼표로 구분해서 입력하세요 (예: 친구, 카페, 행복)"
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
/>
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">태그는 쉼표(,)로 구분해서 입력하세요</p>
</div>

{/* Public/Private */}
<div className="mb-6">
<label className="flex items-center space-x-3 cursor-pointer">
<input
type="checkbox"
checked={formData.isPublic}
onChange={(e) => setFormData((prev) => ({ ...prev, isPublic: e.target.checked }))}
className="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
/>
<input type="checkbox" checked={false} className="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500" />
<span className="text-sm font-medium text-gray-700 dark:text-gray-300">이 일기를 공개로 설정</span>
</label>
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">공개로 설정하면 다른 사용자들이 볼 수 있습니다</p>
</div>
</div>

{/* Action Buttons */}
{/* 서버 응답 상태 표시 */}
{state.message && (
<div
className={`rounded-lg p-4 ${
state.success
? "bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 text-green-700 dark:text-green-300"
: "bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 text-red-700 dark:text-red-300"
}`}
>
<p className="font-medium">{state.message}</p>
</div>
)}

<div className="flex justify-end space-x-4">
<Link
href="/"
Expand Down
14 changes: 2 additions & 12 deletions app/diary/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { handleDeleteDiary } from "@/src/features/diary/actions/deleteDiary";
import Link from "next/link";

export default function DiaryDetail({ params }: { params: { id: string } }) {
Expand Down Expand Up @@ -60,14 +61,6 @@ export default function DiaryDetail({ params }: { params: { id: string } }) {
console.log("일기 수정");
};

const handleDelete = async () => {
"use server";
// 삭제 확인 및 삭제 로직
if (confirm("정말로 이 일기를 삭제하시겠습니까?")) {
console.log("일기 삭제");
}
};

return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
{/* Navigation */}
Expand All @@ -83,9 +76,6 @@ export default function DiaryDetail({ params }: { params: { id: string } }) {
<Link href="/" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 px-3 py-2 rounded-md text-sm font-medium">
</Link>
<Link href="/about" className="text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 px-3 py-2 rounded-md text-sm font-medium">
소개
</Link>
<Link href="/create" className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-medium transition-colors">
✏️ 일기 쓰기
</Link>
Expand Down Expand Up @@ -150,7 +140,7 @@ export default function DiaryDetail({ params }: { params: { id: string } }) {
✏️ 수정
</button>
<button
onClick={handleDelete}
onClick={() => handleDeleteDiary(diaryId)}
className="px-4 py-2 bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-300 rounded-lg hover:bg-red-200 dark:hover:bg-red-800 font-medium transition-colors"
>
🗑️ 삭제
Expand Down
6 changes: 1 addition & 5 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
</html>
);
}
32 changes: 2 additions & 30 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { getMoodEmoji } from "@/src/shared/libs/getMoodEmoji";
import { getWeatherEmoji } from "@/src/shared/libs/getWeatherEmoji";
import Link from "next/link";

export default function Home() {
Expand Down Expand Up @@ -40,31 +42,8 @@ export default function Home() {
},
];

const getMoodEmoji = (mood: string) => {
const moodMap: { [key: string]: string } = {
happy: "😊",
sad: "😢",
angry: "😠",
excited: "🤩",
calm: "😌",
nervous: "😰",
};
return moodMap[mood] || "😐";
};

const getWeatherEmoji = (weather: string) => {
const weatherMap: { [key: string]: string } = {
sunny: "☀️",
rainy: "🌧️",
cloudy: "☁️",
snowy: "❄️",
};
return weatherMap[weather] || "🌤️";
};

return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
{/* Navigation */}
<nav className="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
Expand All @@ -85,20 +64,16 @@ export default function Home() {
</div>
</nav>

{/* Main Content */}
<main className="max-w-4xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
{/* Header */}
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">나의 일기장</h1>
<p className="mt-2 text-gray-600 dark:text-gray-400">소중한 순간들을 기록해보세요</p>
</div>

{/* Diary List */}
<div className="space-y-6">
{dummyDiaries.map((diary) => (
<div key={diary.id} className="bg-white dark:bg-gray-800 rounded-lg shadow-md hover:shadow-lg transition-shadow duration-200 border border-gray-200 dark:border-gray-700">
<div className="p-6">
{/* Header */}
<div className="flex items-start justify-between mb-4">
<div className="flex-1">
<Link href={`/diary/${diary.id}`} className="block hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
Expand All @@ -123,10 +98,8 @@ export default function Home() {
</div>
</div>

{/* Content Preview */}
<p className="text-gray-700 dark:text-gray-300 mb-4 line-clamp-3">{diary.content}</p>

{/* Tags */}
<div className="flex items-center justify-between">
<div className="flex flex-wrap gap-2">
{diary.tags.map((tag, index) => (
Expand All @@ -144,7 +117,6 @@ export default function Home() {
))}
</div>

{/* Empty State (일기가 없을 때) */}
{dummyDiaries.length === 0 && (
<div className="text-center py-12">
<div className="text-6xl mb-4">📝</div>
Expand Down
Loading