サンプル
管理者の登録画面からデータを入力します。
登録が成功するとPostgreSQLにデータが反映されます。
登録済み管理者の場合は、下記のようにサーバ側からメッセージを返却します。
アラートにて登録済みの管理者を表示する仕様です。
スキーマモデル
管理者情報としてAdminUser
モデルを追加しました。
schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User{
userId Int @id @default(autoincrement())
userName String
email String @unique
password String
createdAt DateTime @default(now())
orders Order[] // 1人のユーザーは複数の注文を持つ
}
model AdminUser{
adminUserId Int @id @default(autoincrement())
adminUserName String
adminEmail String @unique
adminPassword String
createdAt DateTime @default(now())
}
model Product{
productId Int @id @default(autoincrement())
productName String
description String
productImagepath String
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
items Item[] // 1つの製品は複数のアイテムに関連付けられる
}
model Item{
itemId Int @id @default(autoincrement())
quantity Int
price Int
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
orderId Int // Order と 1対多 のリレーション
order Order @relation(fields: [orderId], references: [orderId])
productId Int // Product と 多対1 のリレーション
product Product @relation(fields: [productId], references: [productId])
}
model Order{
orderId Int @id @default(autoincrement())
total Int
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
userId Int // User と 1対多 のリレーション
user User @relation(fields: [userId], references: [userId])
items Item[] // 1つの注文には複数のアイテムが関連付けられる
}
ディレクトリ構成
NextProject
├─ app
│ ├─ admin
│ │ ├─ userRegister
│ │ │ └─ page.tsx
│ │ └─ adminUserRegister
│ │ └─ page.tsx
│ ├─ api
│ │ ├─ adminUserRegister
│ │ │ └─ route.ts
│ │ └─ userRegister
│ │ └─ route.ts
│ ├─ components
│ │ └─ headers
│ │ └─ navbar
│ │ └─ page.tsx
│ └─ prisma
│ └─ schema.prisma
├─ next.config.ts
├─ package.json
├─ package.lock.json
└─ tailwind.config.mjs
フロント側のコード
app/admin/adminUserRegister/page.tsx
'use client'
import { useForm } from "react-hook-form"
import { useState } from "react";
//付与すること
export default function AdminRegister(){
//初期値アを設定
const defaultValues = {
userName:'管理者太郎',
email:'authenticater@email.com',
password:''
}
//フォームを初期化する
const {register,handleSubmit,formState:{errors}} = useForm({
defaultValues
});
const [userName,setUserName] = useState("");
const [email,setEmail] = useState("");
const [password,setPassword] = useState("");
//フォーム送信時の実行される関数
const onSubmit = async(data:any)=>{
//POSTリクエスト送信
const response = await fetch('/api/adminUserRegister',{
method:'POST',
headers:{
'Content-Type':'application/json',
cache:'no-store'
},
body:JSON.stringify({
userName:data.userName,
email:data.email,
password:data.password
})
});
//レスポンスデータをJSON変換する
const returnResponse = await response.json();
console.log(returnResponse);
//レスポンスを画面に表示する
if(response.ok){
alert('管理者ユーザ登録成功しました');
}
if(returnResponse.status === 500){
alert(returnResponse.existAdminUser.adminUserName + "は、すでに塘路kされています");
}
}
return(
<div className="flex items-center justify-center min-h-screen rounded-md">
<form onSubmit={handleSubmit(onSubmit)} className="shadow-md w-96 px-8 py-8 border border-gray-300 rounded-md">
<div className="w-full">
<label className="font-bold">管理者名</label>
<input
type="text"
name="userName"
defaultValue={userName}
className="block rounded-md w-full text-sm border border-gray-300 text-gray-900 px-2 py-2"
placeholder=""
{...register('userName',{
required:'管理者名は必須です。',
maxLength:{
value:20,
message:'管理者名は20文字以内にしてください。'
}
})}
onChange={(e)=>setUserName(e.target.value)}
/>
<div className="text-red-500">{errors.userName?.message}</div>
</div>
<div className="w-full mt-4">
<label className="font-bold">管理者メールアドレス</label>
<input
type="email"
name="email"
defaultValue={email}
className="block rounded-md w-full text-sm border border-gray-300 text-gray-900 px-2 py-2"
{...register('email',{
required:'管理者メールアドレスは必須です。',
pattern:{
value:/([a-z\d+\-.]@[a-z\d-]+(?:\.[a-z]+)*)/i,
message:'管理写メールアドレスが必須です。'
}
})}
onChange={(e)=>setEmail(e.target.value)}
/>
</div>
<div className="w-full mt-4">
<label className="font-bold">管理者パスワード</label>
<input
type="password"
name="password"
defaultValue={password}
className="block rounded-md w-full text-sm border border-gray-300 text-gray-900 px-2 py-2"
{...register('password',{
required:'管理者パスワードは必須です。'
})}
onChange={(e)=>{e.target.value}}
/>
</div>
<div className="flex items-center justify-center mt-4 mb-4">
<button type="submit" className="shadow-md bg-blue-500 text-white font-bold rounded-md px-4 py-4">
登録
</button>
</div>
</form>
</div>
)
}
サーバ側のコード
app/api/adminUserRegister/route.ts
import { NextRequest,NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import bcrypt from 'bcryptjs'
const prisma = new PrismaClient();
export async function POST(req:NextRequest){
try{
let {userName,email,password} = await req.json();
console.log("受け取った管理者名は," + userName);
const hashedPassword:String = await bcrypt.hash(password,10);
//リクエストパラメータが不足している場合はエラーレスポンスを変化ykする
if(!userName || !email || !password){
return NextResponse.json({error:"全ての項目を入力してください",status:401});
}
//登録済みユーザの確認
const existAdminUser = await prisma.AdminUser.findUnique({
where:{
adminEmail: email
}
});
if(existAdminUser){
return NextResponse.json({message:"すでにこのユーザーは登録されています。",status:500,existAdminUser:existAdminUser},{status:500});
}
//管理ユーザを登録する
const newAdminUser = await prisma.AdminUser.create({
data:{
adminUserName: userName,
adminEmail: email,
adminPassword: hashedPassword
}
});
//成功レスポンセ鵜を変化yk数ル
return NextResponse.json({message:'管理者ユーザーを登録しました。',adminUser:newAdminUser});
}catch(error){
if(error instanceof Error){
console.log("エラー詳細:",error);
}
return NextResponse.json({error:"ユーザー登録中にエラーが発生しました。",status:500});
}
}
以上です。