Skip to content

Commit

Permalink
Merge pull request #116 from jphacks/feature/#101
Browse files Browse the repository at this point in the history
Eventの空白をzodでバリデーション
  • Loading branch information
yuto-trd authored Dec 11, 2024
2 parents c39be6e + 69c7424 commit 541f5c3
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 114 deletions.
22 changes: 9 additions & 13 deletions task_yell/src/app/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,9 @@ import {
readWantTodos,
updateWantTodo,
} from "@/lib/want-todo";
import {
addMonths,
format,
subMonths,
} from "date-fns";
import { addMonths, format, subMonths } from "date-fns";
import { ja } from "date-fns/locale";
import {
ChevronLeft,
ChevronRight,
} from "lucide-react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { generateStickyNoteServer } from "./actions";
Expand Down Expand Up @@ -157,6 +150,7 @@ export default function Home() {
newEvent: Event,
notification: { date: Date | null; type: "call" | "push" },
) => {
console.log("addEvent", newEvent);
setEvents([...events, newEvent]);
setIsEventModalOpen(false);
setRemovedStickyNote(null);
Expand Down Expand Up @@ -235,10 +229,12 @@ export default function Home() {
</div>

<div className="w-full lg:w-1/2 pl-2 bg-white dark:bg-gray-800 overflow-auto lg:block hidden">
<WantodoView
newStickyNote={newStickyNote} setNewStickyNote={setNewStickyNote}
<WantodoView
newStickyNote={newStickyNote}
setNewStickyNote={setNewStickyNote}
addStickyNote={addStickyNote}
searchTerm={searchTerm} setSearchTerm={setSearchTerm}
searchTerm={searchTerm}
setSearchTerm={setSearchTerm}
filteredStickyNotes={filteredStickyNotes}
setDraggedStickyNote={setDraggedStickyNote}
generateStickyNote={generateStickyNote}
Expand All @@ -254,7 +250,7 @@ export default function Home() {
updateStickyNote={updateStickyNote}
/>

<CreateEventDialog
<CreateEventDialog
stickyNotes={stickyNotes}
setStickyNotes={setStickyNotes}
isEventModalOpen={isEventModalOpen}
Expand Down
37 changes: 23 additions & 14 deletions task_yell/src/components/calendar-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Props = {
draggedStickyNote: StickyNote | null;
deleteStickyNote: (id: string) => void;
setIsEventModalOpen: (isOpen: boolean) => void;
}
};

function getDaysInMonth(date: Date) {
const start = startOfWeek(startOfMonth(date), { weekStartsOn: 0 });
Expand All @@ -42,7 +42,11 @@ function getEventCountForDay(events: Event[], day: Date) {
.length;
}

function getTaskIndicatorStyle(isDarkMode: boolean, todoCount: number, eventCount: number) {
function getTaskIndicatorStyle(
isDarkMode: boolean,
todoCount: number,
eventCount: number,
) {
const count = todoCount + eventCount;
if (count === 0) return "";
const baseColor = isDarkMode ? "bg-red-" : "bg-red-";
Expand All @@ -52,13 +56,16 @@ function getTaskIndicatorStyle(isDarkMode: boolean, todoCount: number, eventCoun
}

export function CalendarRenderer({
todos, events,
currentMonth, selectedDate, handleDateSelect,
todos,
events,
currentMonth,
selectedDate,
handleDateSelect,
isDarkMode,
draggedStickyNote, deleteStickyNote,
setIsEventModalOpen
}: Props
) {
draggedStickyNote,
deleteStickyNote,
setIsEventModalOpen,
}: Props) {
const days = getDaysInMonth(currentMonth);
const weeks = Math.ceil(days.length / 7);

Expand All @@ -78,7 +85,8 @@ export function CalendarRenderer({
const weekDays = days.slice(weekIndex * 7, (weekIndex + 1) * 7);
const maxEventsInWeek = Math.max(
...weekDays.map(
(day) => getTodoCountForDay(todos, day) + getEventCountForDay(events, day),
(day) =>
getTodoCountForDay(todos, day) + getEventCountForDay(events, day),
),
);
const weekHeight =
Expand All @@ -105,10 +113,11 @@ export function CalendarRenderer({
return (
<motion.div
key={day.toISOString()}
className={`p-1 border rounded-md cursor-pointer transition-all duration-300 overflow-hidden ${isSelected ? "border-blue-300 dark:border-blue-600" : ""} ${!isCurrentMonth
? "text-gray-400 dark:text-gray-600 bg-gray-100 dark:bg-gray-700"
: ""
} ${getTaskIndicatorStyle(isDarkMode, todoCount, eventCount)} hover:bg-gray-100 dark:hover:bg-gray-700`}
className={`p-1 border rounded-md cursor-pointer transition-all duration-300 overflow-hidden ${isSelected ? "border-blue-300 dark:border-blue-600" : ""} ${
!isCurrentMonth
? "text-gray-400 dark:text-gray-600 bg-gray-100 dark:bg-gray-700"
: ""
} ${getTaskIndicatorStyle(isDarkMode, todoCount, eventCount)} hover:bg-gray-100 dark:hover:bg-gray-700`}
onClick={() => handleDateSelect(day)}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
Expand Down Expand Up @@ -164,4 +173,4 @@ export function CalendarRenderer({
})}
</div>
);
};
}
25 changes: 15 additions & 10 deletions task_yell/src/components/create-event-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
format,
} from "date-fns";
import { format } from "date-fns";
import { ja } from "date-fns/locale";
import { EventCreator } from "@/components/event-creator";
import { Event, StickyNote } from "@/components/types";
Expand All @@ -20,18 +18,25 @@ type Props = {
setIsEventModalOpen: (isOpen: boolean) => void;
selectedDate: Date;
events: Event[];
addEvent: (newEvent: Event, notification: { date: Date | null; type: "call" | "push" }) => void;
addEvent: (
newEvent: Event,
notification: { date: Date | null; type: "call" | "push" },
) => void;
removedStickyNote: StickyNote | null;
setRemovedStickyNote: (note: StickyNote | null) => void;
draggedStickyNote: StickyNote | null;
};

export function CreateEventDialog({
stickyNotes, setStickyNotes,
isEventModalOpen, setIsEventModalOpen,
stickyNotes,
setStickyNotes,
isEventModalOpen,
setIsEventModalOpen,
selectedDate,
events, addEvent,
removedStickyNote, setRemovedStickyNote,
events,
addEvent,
removedStickyNote,
setRemovedStickyNote,
draggedStickyNote,
}: Props) {
return (
Expand All @@ -57,5 +62,5 @@ export function CreateEventDialog({
/>
</DialogContent>
</Dialog>
)
}
);
}
12 changes: 8 additions & 4 deletions task_yell/src/components/edit-wantodo-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ type Props = {
editingStickyNote: StickyNote | null;
setEditingStickyNote: (stickyNote: StickyNote | null) => void;
updateStickyNote: (stickyNote: StickyNote) => void;
}
};

export function EditWantodoDialog({ editingStickyNote, setEditingStickyNote, updateStickyNote }: Props) {
export function EditWantodoDialog({
editingStickyNote,
setEditingStickyNote,
updateStickyNote,
}: Props) {
return (
<Dialog
open={!!editingStickyNote}
Expand Down Expand Up @@ -50,5 +54,5 @@ export function EditWantodoDialog({ editingStickyNote, setEditingStickyNote, upd
)}
</DialogContent>
</Dialog>
)
}
);
}
31 changes: 22 additions & 9 deletions task_yell/src/components/event-creator.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import { z } from "zod";
import { DateTimeInput } from "@/components/date-time-input";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
Expand All @@ -20,16 +21,9 @@ import {
Pencil1Icon,
ViewGridIcon,
} from "@radix-ui/react-icons";
import {
format,
getHours,
isSameDay,
} from "date-fns";
import { format, getHours, isSameDay } from "date-fns";
import { ja } from "date-fns/locale";
import {
MapPinIcon,
UserPlusIcon,
} from "lucide-react";
import { MapPinIcon, UserPlusIcon } from "lucide-react";
import { useState } from "react";
import { Event } from "@/components/types";
import { priorityColors } from "./priority-colors";
Expand Down Expand Up @@ -64,6 +58,19 @@ export function EventCreator({
const [notificationType, setNotificationType] = useState<"call" | "push">(
"call",
);
// Zod スキーマの定義
const eventSchema = z.object({
title: z.string().nonempty("タイトルは空白にできません。"),
start: z.date(),
end: z.date(),
description: z.string().optional(),
category: z.string().optional(),
priority: z.string().optional(),
location: z.string().optional(),
invitees: z.array(z.string()).optional(),
isTask: z.boolean(),
isLocked: z.boolean(),
});

const handleSave = () => {
if (targetDate) {
Expand All @@ -80,6 +87,12 @@ export function EventCreator({
isTask,
isLocked,
};
// バリデーションの実行
const result = eventSchema.safeParse(newEvent);
if (!result.success) {
alert(result.error.errors.map((err) => err.message).join("\n"));
return;
}
onSave(newEvent, { date: notificationDate, type: notificationType });
}
};
Expand Down
82 changes: 39 additions & 43 deletions task_yell/src/components/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,60 @@ import { signOut } from "@/firebase/auth";
import { auth, db } from "@/firebase/client-app";
import { subscribeNotification } from "@/lib/push-notification";
import { doc, getDoc, setDoc, updateDoc } from "firebase/firestore";
import {
Menu,
Bell,
Users,
Download,
LogOut,
PhoneCall,
} from "lucide-react";
import { Menu, Bell, Users, Download, LogOut, PhoneCall } from "lucide-react";
import { useRouter } from "next/navigation";
import { useMemo, useState } from "react";

type Props = {
isDarkMode: boolean;
setIsDarkMode: (isDarkMode: boolean) => void;
}
};

export function Navigation({ isDarkMode, setIsDarkMode }: Props) {
const [isOpen, setIsOpen] = useState(false);
const [isNotificationsOpen, setIsNotificationsOpen] = useState(false);
const [notificationsEnabled, setNotificationsEnabled] = useState(false);
const router = useRouter();

const menuItems = useMemo(() => [
{
icon: PhoneCall,
label: "電話通知",
onClick: () => {
return setIsNotificationsOpen(!isNotificationsOpen);
const menuItems = useMemo(
() => [
{
icon: PhoneCall,
label: "電話通知",
onClick: () => {
return setIsNotificationsOpen(!isNotificationsOpen);
},
},
},
{
icon: Bell,
label: "プッシュ通知",
onClick: async () => {
await subscribeNotification();
{
icon: Bell,
label: "プッシュ通知",
onClick: async () => {
await subscribeNotification();
},
},
},
{ icon: Users, label: "友達", onClick: () => console.log("友達") },
{
icon: Download,
label: "インポート",
onClick: () => {
if (auth.currentUser) {
router.push(
`/api/auth/google-cal?userId=${encodeURIComponent(auth.currentUser.uid)}`,
);
}
{ icon: Users, label: "友達", onClick: () => console.log("友達") },
{
icon: Download,
label: "インポート",
onClick: () => {
if (auth.currentUser) {
router.push(
`/api/auth/google-cal?userId=${encodeURIComponent(auth.currentUser.uid)}`,
);
}
},
},
},
{
icon: LogOut,
label: "ログアウト",
onClick: async () => {
await signOut();
router.refresh();
{
icon: LogOut,
label: "ログアウト",
onClick: async () => {
await signOut();
router.refresh();
},
},
},
], [isNotificationsOpen, router]);
],
[isNotificationsOpen, router],
);

return (
<Sheet open={isOpen} onOpenChange={setIsOpen}>
Expand Down Expand Up @@ -157,5 +153,5 @@ export function Navigation({ isDarkMode, setIsDarkMode }: Props) {
</nav>
</SheetContent>
</Sheet>
)
}
);
}
Loading

0 comments on commit 541f5c3

Please sign in to comment.