diff --git a/frontend/src/app/(app)/bill/[id]/actions.ts b/frontend/src/app/(app)/bill/[id]/actions.ts deleted file mode 100644 index 3e6160d..0000000 --- a/frontend/src/app/(app)/bill/[id]/actions.ts +++ /dev/null @@ -1,80 +0,0 @@ -"use server"; - -import { auth } from "@auth"; -import prisma from "@src/lib/prisma"; -import { revalidatePath } from "next/cache"; -import { zact } from "zact/server"; -import { z } from "zod"; - -export const Vote = zact(z.object({ id: z.string().cuid() }))(async (data) => { - const session = await auth(); - - if (!session?.user?.id) { - return { - error: "Unauthorized", - }; - } - - const vote = await prisma.vote.findFirst({ - where: { - commentId: data.id, - userId: session.user.id, - }, - }); - - if (!vote) { - const res = await prisma.vote.create({ - data: { - comment: { connect: { id: data.id } }, - user: { connect: { id: session.user.id } }, - }, - }); - - revalidatePath("/"); - - return res; - } - - if (vote) { - const res = await prisma.vote.delete({ - where: { - id: vote.id, - }, - }); - - revalidatePath("/"); - - return res; - } -}); - -export async function addComment({ - bill_id, - comment, - type, -}: { - bill_id: string; - comment: string; - type: any; -}) { - const session = await auth(); - - if (!session?.user?.id) { - return { - error: "Unauthorized", - }; - } - - const res = await prisma.comment.create({ - data: { - bill: { connect: { id: bill_id } }, - comment, - type: type, - user: { connect: { id: session.user.id } }, - }, - }); - - revalidatePath("/"); - - return res; -} diff --git a/frontend/src/app/(app)/bill/[id]/form.tsx b/frontend/src/app/(app)/bill/[id]/form.tsx index 909cd4e..922dcd3 100644 --- a/frontend/src/app/(app)/bill/[id]/form.tsx +++ b/frontend/src/app/(app)/bill/[id]/form.tsx @@ -2,6 +2,7 @@ import "dayjs/locale/ja"; +import { addComment, Vote } from "@src/app/actions"; import { LoginPrompt } from "@src/components/login/login"; import dayjs from "dayjs"; import { type Session } from "next-auth"; @@ -9,8 +10,6 @@ import { useRef, useState, useTransition } from "react"; import { experimental_useFormStatus as useFormStatus } from "react-dom"; import { VscTriangleUp } from "react-icons/vsc"; -import { addComment, Vote } from "./actions"; - dayjs.locale("ja"); type Comment = { diff --git a/frontend/src/app/(app)/dashboard/settings/Settings.tsx b/frontend/src/app/(app)/dashboard/settings/Settings.tsx index ce2fa12..cf0aec2 100644 --- a/frontend/src/app/(app)/dashboard/settings/Settings.tsx +++ b/frontend/src/app/(app)/dashboard/settings/Settings.tsx @@ -2,6 +2,7 @@ import { Dialog, Switch } from "@headlessui/react"; import GLogo from "@public/g-logo.svg"; +import { DeleteAccount, updatePrefecture, updateUser } from "@src/app/actions"; import Modal from "@src/components/ui/dialog"; import { ArrowDownIcon } from "@xpadev-net/designsystem-icons"; import cn from "classnames"; @@ -9,8 +10,6 @@ import { useRouter } from "next/navigation"; import { type Session } from "next-auth"; import { useEffect, useState, useTransition } from "react"; -import { DeleteAccount, updatePrefecture, updateUser } from "./actions"; - export default function Settings({ prefectures, user, diff --git a/frontend/src/app/(app)/dashboard/settings/actions.ts b/frontend/src/app/(app)/dashboard/settings/actions.ts deleted file mode 100644 index 00b7d6b..0000000 --- a/frontend/src/app/(app)/dashboard/settings/actions.ts +++ /dev/null @@ -1,64 +0,0 @@ -"use server"; - -import { auth } from "@auth"; -import prisma from "@src/lib/prisma"; - -export async function updateUser({ kids }: { kids: boolean }) { - const session = await auth(); - - if (!session?.user?.id) { - return { - error: "Unauthorized", - }; - } - - const res = await prisma.user.update({ - data: { - kids: kids, - }, - where: { - id: session?.user.id, - }, - }); - - return res; -} - -export async function updatePrefecture({ prefecture }: { prefecture: number }) { - const session = await auth(); - - if (!session?.user?.id) { - return { - error: "Unauthorized", - }; - } - - const res = await prisma.user.update({ - data: { - prefectureId: prefecture, - }, - where: { - id: session?.user.id, - }, - }); - - return res; -} - -export async function DeleteAccount() { - const session = await auth(); - - if (!session?.user?.id) { - return { - error: "Unauthorized", - }; - } - - const res = await prisma.user.delete({ - where: { - id: session.user.id, - }, - }); - - return res; -} diff --git a/frontend/src/app/(app)/face/PersonModal.tsx b/frontend/src/app/(app)/face/PersonModal.tsx index 3d48532..85e2978 100644 --- a/frontend/src/app/(app)/face/PersonModal.tsx +++ b/frontend/src/app/(app)/face/PersonModal.tsx @@ -2,7 +2,7 @@ import { Member } from "@src/types/member"; import { motion, transform, useMotionValue } from "framer-motion"; import Link from "next/link"; import { useRef } from "react"; -import { FaGlobe, FaTwitter } from "react-icons/fa"; +import { FaGlobe } from "react-icons/fa"; interface PersonModalProps { member: Member; @@ -81,7 +81,7 @@ const PersonModal: React.FC = ({ member, onClose }) => { dragConstraints={{ top: 0 }} drag="y" style={{ x: "-50%" }} - className="xs:p-8 fixed bottom-0 left-[50%] z-50 flex w-full max-w-[480px] flex-col rounded-t-4xl bg-white px-5 py-7 before:absolute before:left-[50%] before:top-[10px] before:h-[4px] before:w-[60px] before:-translate-x-1/2 before:bg-gray-200" + className="xs:p-8 rounded-t-4xl fixed bottom-0 left-[50%] z-50 flex w-full max-w-[480px] flex-col bg-white px-5 py-7 before:absolute before:left-[50%] before:top-[10px] before:h-[4px] before:w-[60px] before:-translate-x-1/2 before:bg-gray-200" >

{member.name}議員の情報 @@ -127,10 +127,18 @@ const PersonModal: React.FC = ({ member, onClose }) => { {member.twitter && ( - @{member.twitter} + + + + @{member.twitter} )} diff --git a/frontend/src/app/(app)/face/page.tsx b/frontend/src/app/(app)/face/page.tsx index 8ccf6aa..a76bb7f 100644 --- a/frontend/src/app/(app)/face/page.tsx +++ b/frontend/src/app/(app)/face/page.tsx @@ -1,29 +1,29 @@ "use client"; import FaceDetection from "@src/app/(app)/face/FaceDetection"; +import PersonModal from "@src/app/(app)/face/PersonModal"; +import { getMember } from "@src/app/actions"; import { Member } from "@src/types/member"; import { AnimatePresence } from "framer-motion"; import { useState } from "react"; import { toast } from "sonner"; -import PersonModal from "./PersonModal"; - const useMember = () => { const [member, setMember] = useState(null); const fetchMember = async (name: string) => { - try { - const response = await fetch(`/api/members/${name}`); - if (response.ok) { - const foundMember: Member = await response.json(); - setMember(foundMember); - } else { + getMember(name) + .then((res) => { + console.log(res); + setMember(res); + + if (!res) { + toast.error("人物が見つかりませんでした"); + } + }) + .catch((e) => { toast.error("問題が発生しました"); - } - } catch (error) { - console.error(error); - toast.error("問題が発生しました"); - } + }); }; const clearMember = () => setMember(null); @@ -35,11 +35,8 @@ export default function Page() { const { clearMember, fetchMember, member } = useMember(); const handleFaceDetect = async (name: string) => { - if (name !== "unknown") { - await fetchMember(name); - } else { - toast.error("人物を検出できませんでした"); - } + console.log(name); + await fetchMember("岸田文雄"); }; return ( diff --git a/frontend/src/app/(app)/meetings/[id]/actions.ts b/frontend/src/app/(app)/meetings/[id]/actions.ts deleted file mode 100644 index d111b21..0000000 --- a/frontend/src/app/(app)/meetings/[id]/actions.ts +++ /dev/null @@ -1,113 +0,0 @@ -"use server"; - -import { auth } from "@auth"; -import { - hasDurationPassedSinceCreation, - twoWeeksInMilliseconds, -} from "@src/helper/utils"; -import prisma from "@src/lib/prisma"; -import { NoteSchema } from "@src/schema/note"; -import { revalidatePath } from "next/cache"; -import { zact } from "zact/server"; -import { z } from "zod"; - -export const createNote = zact(NoteSchema)(async (data) => { - const session = await auth(); - - if (!session) { - return { - error: "Unauthorized", - }; - } - - if ( - !hasDurationPassedSinceCreation( - session.user.createdAt, - twoWeeksInMilliseconds - ) - ) { - return { - error: "Unauthorized", - }; - } - - const { id, end, start, text } = data; - - if (end < start) { - return { - error: "終了時間が開始時間以下です。", - }; - } - - const res = await prisma.note.create({ - data: { - end, - meeting: { - connect: { - id: id, - }, - }, - start, - text, - }, - }); - - revalidatePath("/"); - - return res; -}); - -export const DeleteComment = zact(z.object({ id: z.string().cuid() }))( - async (data) => { - const session = await auth(); - - if (!session?.user?.id) { - return { - error: "Unauthorized", - }; - } - const comment = await prisma.videoComment.findUnique({ - where: { id: data.id }, - }); - - if (comment?.userId !== session.user.id) { - return { - error: "You are not authorized.", - }; - } - - const res = await prisma.videoComment.delete({ - where: { - id: data.id, - }, - }); - - revalidatePath("/"); - - return res; - } -); - -export const createComment = zact( - z.object({ id: z.string().cuid(), comment: z.string() }) -)(async (data) => { - const session = await auth(); - - if (!session?.user?.id) { - return { - error: "Unauthorized", - }; - } - - const res = await prisma.videoComment.create({ - data: { - comment: data.comment, - user: { connect: { id: session.user.id } }, - video: { connect: { id: data.id } }, - }, - }); - - revalidatePath("/"); - - return res; -}); diff --git a/frontend/src/app/(app)/members/[id]/edit/Form.tsx b/frontend/src/app/(app)/members/[id]/edit/Form.tsx index 7a507d1..8c38ec0 100644 --- a/frontend/src/app/(app)/members/[id]/edit/Form.tsx +++ b/frontend/src/app/(app)/members/[id]/edit/Form.tsx @@ -1,6 +1,7 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; +import { updateMember } from "@src/app/actions"; import Button from "@src/components/ui/button"; import { InputField, @@ -17,8 +18,6 @@ import { Session } from "next-auth"; import { useState, useTransition } from "react"; import { useForm } from "react-hook-form"; -import { updateMember } from "./actions"; - export default function Form({ groups, member, diff --git a/frontend/src/app/(app)/members/[id]/edit/actions.ts b/frontend/src/app/(app)/members/[id]/edit/actions.ts deleted file mode 100644 index 8eca1c6..0000000 --- a/frontend/src/app/(app)/members/[id]/edit/actions.ts +++ /dev/null @@ -1,125 +0,0 @@ -"use server"; - -import { auth } from "@auth"; -import { config } from "@site.config"; -import { - hasDurationPassedSinceCreation, - hiraToKana, - twoWeeksInMilliseconds, -} from "@src/helper/utils"; -import prisma from "@src/lib/prisma"; -import { MemberSchema } from "@src/schema/member"; -import { zact } from "zact/server"; - -export const updateMember = zact(MemberSchema)(async (data) => { - const session = await auth(); - - if (!session) { - return { - error: "Unauthorized", - }; - } - - if ( - !hasDurationPassedSinceCreation( - session.user.createdAt, - twoWeeksInMilliseconds - ) - ) { - return { - error: "Unauthorized", - }; - } - - const { - id, - name, - description, - firstName, - firstNameHira, - groupId, - house, - lastName, - lastNameHira, - twitter, - website, - } = data; - - const fullname = firstName && lastName ? firstName + lastName : null; - const nameHira = - firstNameHira && lastNameHira ? firstNameHira + lastNameHira : null; - const nameKana = hiraToKana(nameHira); - const firstNameKana = hiraToKana(firstNameHira); - const lastNameKana = hiraToKana(lastNameHira); - - const currentMember = await prisma.member.findUnique({ - select: { - group: true, - }, - where: { - id: id, - }, - }); - - let groupData; - - if (groupId) { - groupData = { connect: { id: groupId } }; - } else if (currentMember && currentMember.group) { - groupData = { disconnect: true }; - } - - const res = await prisma.member.update({ - data: { - name, - description, - firstName, - firstNameHira, - firstNameKana, - fullname, - group: groupData, - house, - lastName, - lastNameHira, - lastNameKana, - nameHira, - nameKana, - twitter, - website, - }, - where: { - id: id, - }, - }); - - if (res) { - const embed = { - title: `${name} (ID: ${id})`, - color: 1986741, - description, - fields: [ - { name: "Name", inline: true, value: name }, - { name: "House", inline: true, value: house }, - { name: "Group ID", inline: true, value: groupId ?? "無所属・その他" }, - ], - url: config.siteRoot + "members/" + id, - }; - - const discordData = { - content: "Member information has been updated!", - embeds: [embed], - }; - - const WEBHOOK_URL = process.env.WEBHOOK_URL as string; - - await fetch(WEBHOOK_URL, { - body: JSON.stringify(discordData), - headers: { - "Content-Type": "application/json", - }, - method: "POST", - }); - } - - return res; -}); diff --git a/frontend/src/app/(app)/members/[id]/page.tsx b/frontend/src/app/(app)/members/[id]/page.tsx index ffc310e..390a94e 100644 --- a/frontend/src/app/(app)/members/[id]/page.tsx +++ b/frontend/src/app/(app)/members/[id]/page.tsx @@ -12,7 +12,7 @@ import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { AiOutlineLink } from "react-icons/ai"; -import { FaFacebook, FaTwitter, FaWikipediaW, FaYoutube } from "react-icons/fa"; +import { FaFacebook, FaWikipediaW, FaYoutube } from "react-icons/fa"; dayjs.locale("ja"); dayjs.extend(relativeTime); @@ -169,7 +169,7 @@ export default async function Page({ params }: { params: { id: string } }) { {session?.user && ( 更新 @@ -194,9 +194,16 @@ export default async function Page({ params }: { params: { id: string } }) { {member.twitter && ( - + + + )} {member.facebook && ( diff --git a/frontend/src/app/actions.ts b/frontend/src/app/actions.ts new file mode 100644 index 0000000..877b908 --- /dev/null +++ b/frontend/src/app/actions.ts @@ -0,0 +1,382 @@ +"use server"; + +import { auth } from "@auth"; +import { config } from "@site.config"; +import { + hasDurationPassedSinceCreation, + hiraToKana, + twoWeeksInMilliseconds, +} from "@src/helper/utils"; +import prisma from "@src/lib/prisma"; +import { MemberSchema } from "@src/schema/member"; +import { NoteSchema } from "@src/schema/note"; +import { revalidatePath } from "next/cache"; +import { zact } from "zact/server"; +import { z } from "zod"; + +export const updateMember = zact(MemberSchema)(async (data) => { + const session = await auth(); + + if (!session) { + return { + error: "Unauthorized", + }; + } + + if ( + !hasDurationPassedSinceCreation( + session.user.createdAt, + twoWeeksInMilliseconds + ) + ) { + return { + error: "Unauthorized", + }; + } + + const { + id, + name, + description, + firstName, + firstNameHira, + groupId, + house, + lastName, + lastNameHira, + twitter, + website, + } = data; + + const fullname = firstName && lastName ? firstName + lastName : null; + const nameHira = + firstNameHira && lastNameHira ? firstNameHira + lastNameHira : null; + const nameKana = hiraToKana(nameHira); + const firstNameKana = hiraToKana(firstNameHira); + const lastNameKana = hiraToKana(lastNameHira); + + const currentMember = await prisma.member.findUnique({ + select: { + group: true, + }, + where: { + id: id, + }, + }); + + let groupData; + + if (groupId) { + groupData = { connect: { id: groupId } }; + } else if (currentMember && currentMember.group) { + groupData = { disconnect: true }; + } + + const res = await prisma.member.update({ + data: { + name, + description, + firstName, + firstNameHira, + firstNameKana, + fullname, + group: groupData, + house, + lastName, + lastNameHira, + lastNameKana, + nameHira, + nameKana, + twitter, + website, + }, + where: { + id: id, + }, + }); + + if (res) { + const embed = { + title: `${name} (ID: ${id})`, + color: 1986741, + description, + fields: [ + { name: "Name", inline: true, value: name }, + { name: "House", inline: true, value: house }, + { name: "Group ID", inline: true, value: groupId ?? "無所属・その他" }, + ], + url: config.siteRoot + "members/" + id, + }; + + const discordData = { + content: "Member information has been updated!", + embeds: [embed], + }; + + const WEBHOOK_URL = process.env.WEBHOOK_URL as string; + + await fetch(WEBHOOK_URL, { + body: JSON.stringify(discordData), + headers: { + "Content-Type": "application/json", + }, + method: "POST", + }); + } + + return res; +}); + +export const getMember = async (name: string) => { + const foundMember = await prisma.member.findFirst({ + include: { + group: true, + }, + where: { + name: name, + }, + }); + + if (!foundMember) return null; + + await prisma.member.update({ + data: { scannedCount: { increment: 1 } }, + where: { id: foundMember.id }, + }); + + return foundMember; +}; + +export const Vote = zact(z.object({ id: z.string().cuid() }))(async (data) => { + const session = await auth(); + + if (!session?.user?.id) { + return { + error: "Unauthorized", + }; + } + + const vote = await prisma.vote.findFirst({ + where: { + commentId: data.id, + userId: session.user.id, + }, + }); + + if (!vote) { + const res = await prisma.vote.create({ + data: { + comment: { connect: { id: data.id } }, + user: { connect: { id: session.user.id } }, + }, + }); + + revalidatePath("/"); + + return res; + } + + if (vote) { + const res = await prisma.vote.delete({ + where: { + id: vote.id, + }, + }); + + revalidatePath("/"); + + return res; + } +}); + +export async function addComment({ + bill_id, + comment, + type, +}: { + bill_id: string; + comment: string; + type: any; +}) { + const session = await auth(); + + if (!session?.user?.id) { + return { + error: "Unauthorized", + }; + } + + const res = await prisma.comment.create({ + data: { + bill: { connect: { id: bill_id } }, + comment, + type: type, + user: { connect: { id: session.user.id } }, + }, + }); + + revalidatePath("/"); + + return res; +} + +export async function updateUser({ kids }: { kids: boolean }) { + const session = await auth(); + + if (!session?.user?.id) { + return { + error: "Unauthorized", + }; + } + + const res = await prisma.user.update({ + data: { + kids: kids, + }, + where: { + id: session?.user.id, + }, + }); + + return res; +} + +export async function updatePrefecture({ prefecture }: { prefecture: number }) { + const session = await auth(); + + if (!session?.user?.id) { + return { + error: "Unauthorized", + }; + } + + const res = await prisma.user.update({ + data: { + prefectureId: prefecture, + }, + where: { + id: session?.user.id, + }, + }); + + return res; +} + +export async function DeleteAccount() { + const session = await auth(); + + if (!session?.user?.id) { + return { + error: "Unauthorized", + }; + } + + const res = await prisma.user.delete({ + where: { + id: session.user.id, + }, + }); + + return res; +} + +export const createNote = zact(NoteSchema)(async (data) => { + const session = await auth(); + + if (!session) { + return { + error: "Unauthorized", + }; + } + + if ( + !hasDurationPassedSinceCreation( + session.user.createdAt, + twoWeeksInMilliseconds + ) + ) { + return { + error: "Unauthorized", + }; + } + + const { id, end, start, text } = data; + + if (end < start) { + return { + error: "終了時間が開始時間以下です。", + }; + } + + const res = await prisma.note.create({ + data: { + end, + meeting: { + connect: { + id: id, + }, + }, + start, + text, + }, + }); + + revalidatePath("/"); + + return res; +}); + +export const DeleteComment = zact(z.object({ id: z.string().cuid() }))( + async (data) => { + const session = await auth(); + + if (!session?.user?.id) { + return { + error: "Unauthorized", + }; + } + const comment = await prisma.videoComment.findUnique({ + where: { id: data.id }, + }); + + if (comment?.userId !== session.user.id) { + return { + error: "You are not authorized.", + }; + } + + const res = await prisma.videoComment.delete({ + where: { + id: data.id, + }, + }); + + revalidatePath("/"); + + return res; + } +); + +export const createComment = zact( + z.object({ id: z.string().cuid(), comment: z.string() }) +)(async (data) => { + const session = await auth(); + + if (!session?.user?.id) { + return { + error: "Unauthorized", + }; + } + + const res = await prisma.videoComment.create({ + data: { + comment: data.comment, + user: { connect: { id: session.user.id } }, + video: { connect: { id: data.id } }, + }, + }); + + revalidatePath("/"); + + return res; +}); diff --git a/frontend/src/app/api/members/[name]/route.ts b/frontend/src/app/api/members/[name]/route.ts deleted file mode 100644 index c31b8fd..0000000 --- a/frontend/src/app/api/members/[name]/route.ts +++ /dev/null @@ -1,41 +0,0 @@ -import prisma from "@src/lib/prisma"; -import { NextResponse } from "next/server"; - -export async function GET( - request: Request, - { - params, - }: { - params: { name: string }; - } -) { - const name = params.name; - - try { - const foundMember = await prisma.member.findFirst({ - include: { - group: true, - }, - where: { - name: name, - }, - }); - - if (foundMember) { - // Increment the scannedCount and update the member - await prisma.member.update({ - data: { scannedCount: { increment: 1 } }, - where: { id: foundMember.id }, - }); - - return NextResponse.json(foundMember); - } else { - return new Response(JSON.stringify({ error: "Not found" }), { - status: 500, - }); - } - } catch (error) { - console.error(error); - return NextResponse.json({ error: "Internal server error" }); - } -} diff --git a/frontend/src/components/member-card/member-card.tsx b/frontend/src/components/member-card/member-card.tsx index 6ba0a68..a0c749b 100644 --- a/frontend/src/components/member-card/member-card.tsx +++ b/frontend/src/components/member-card/member-card.tsx @@ -36,7 +36,7 @@ export default function MemberCard({ member }: { member: Member }) { {member.twitter && (