📌 feat: Implement Suitable model and API endpoints for managing suitable products, including creation and listing functionalities

This commit is contained in:
yoosangwook 2025-04-22 15:20:08 +09:00
parent 34611d3c00
commit 42b82fe7cb
9 changed files with 77005 additions and 0 deletions

View File

@ -18,3 +18,41 @@ model User {
created_at DateTime @default(now()) created_at DateTime @default(now())
updated_at DateTime @updatedAt updated_at DateTime @updatedAt
} }
model Suitable {
id Int @id @default(autoincrement())
product_name String
manufacturer String?
roof_material String?
shape String?
support_roof_tile String?
support_roof_tile_memo String?
support_roof_bracket String?
support_roof_bracket_memo String?
yg_anchor String?
yg_anchor_memo String?
rg_roof_tile_part String?
rg_roof_tile_part_memo String?
dido_hunt_support_tile_2 String?
dido_hunt_support_tile_2_memo String?
takashima_power_base String?
takashima_power_base_memo String?
takashima_tile_bracket String?
takashima_tile_bracket_memo String?
slate_bracket_4 String?
slate_bracket_4_memo String?
slate_single_metal_bracket String?
slate_single_metal_bracket_memo String?
dido_hunt_short_rack_4 String?
dido_hunt_short_rack_4_memo String?
takashima_slate_bracket_slate_single String?
takashima_slate_bracket_slate_single_memo String?
df_metal_bracket String?
df_metal_bracket_memo String?
slate_metal_bracket String?
slate_metal_bracket_memo String?
takashima_slate_bracket_metal_roof String?
takashima_slate_bracket_metal_roof_memo String?
created_at DateTime @default(now())
updated_at DateTime @updatedAt
}

90
src/api/suitable.ts Normal file
View File

@ -0,0 +1,90 @@
import { database } from '@/data'
import { axiosInstance } from '@/libs/axios'
export interface Suitable {
id?: number
product_name: string
manufacturer: string
roof_material: string
shape: string
support_roof_tile: string
support_roof_tile_memo: string
support_roof_bracket: string
support_roof_bracket_memo: string
yg_anchor: string
yg_anchor_memo: string
rg_roof_tile_part: string
rg_roof_tile_part_memo: string
dido_hunt_support_tile_2: string
dido_hunt_support_tile_2_memo: string
takashima_power_base: string
takashima_power_base_memo: string
takashima_tile_bracket: string
takashima_tile_bracket_memo: string
slate_bracket_4: string
slate_bracket_4_memo: string
slate_single_metal_bracket: string
slate_single_metal_bracket_memo: string
dido_hunt_short_rack_4: string
dido_hunt_short_rack_4_memo: string
takashima_slate_bracket_slate_single: string
takashima_slate_bracket_slate_single_memo: string
df_metal_bracket: string
df_metal_bracket_memo: string
slate_metal_bracket: string
slate_metal_bracket_memo: string
takashima_slate_bracket_metal_roof: string
takashima_slate_bracket_metal_roof_memo: string
}
export const suitableApi = {
getList: async (): Promise<Suitable[]> => {
const response = await axiosInstance.get<Suitable[]>('/api/suitable/list')
console.log('🚀 ~ getList: ~ response:', response)
return response.data
},
create: async () => {
const suitableData: Suitable[] = []
database.forEach((item) => {
suitableData.push({
product_name: item[1],
manufacturer: item[2],
roof_material: item[3],
shape: item[4],
support_roof_tile: item[5],
support_roof_tile_memo: item[6],
support_roof_bracket: item[7],
support_roof_bracket_memo: item[8],
yg_anchor: item[9],
yg_anchor_memo: item[10],
rg_roof_tile_part: item[11],
rg_roof_tile_part_memo: item[12],
dido_hunt_support_tile_2: item[13],
dido_hunt_support_tile_2_memo: item[14],
takashima_power_base: item[15],
takashima_power_base_memo: item[16],
takashima_tile_bracket: item[17],
takashima_tile_bracket_memo: item[18],
slate_bracket_4: item[19],
slate_bracket_4_memo: item[20],
slate_single_metal_bracket: item[21],
slate_single_metal_bracket_memo: item[22],
dido_hunt_short_rack_4: item[23],
dido_hunt_short_rack_4_memo: item[24],
takashima_slate_bracket_slate_single: item[25],
takashima_slate_bracket_slate_single_memo: item[26],
df_metal_bracket: item[27],
df_metal_bracket_memo: item[28],
slate_metal_bracket: item[29],
slate_metal_bracket_memo: item[30],
takashima_slate_bracket_metal_roof: item[31],
takashima_slate_bracket_metal_roof_memo: item[32],
})
})
const response = await axiosInstance.post<Suitable[]>('/api/suitable', suitableData)
return response.data
},
}

View File

@ -0,0 +1,8 @@
import { NextResponse } from 'next/server'
import { prisma } from '@/libs/prisma'
export async function GET() {
// @ts-ignore
const suitables = await prisma.suitable.findMany()
return NextResponse.json(suitables)
}

View File

@ -0,0 +1,12 @@
import { NextResponse } from 'next/server'
import { prisma } from '@/libs/prisma'
export async function POST(request: Request) {
const body = await request.json()
// @ts-ignore
const suitables = await prisma.suitable.createMany({
data: body,
})
return NextResponse.json({ message: 'Suitable created successfully' })
}

View File

@ -19,6 +19,12 @@ export default async function Home() {
</Link> </Link>
</div> </div>
<div className="p-4">
<Link href="/suitable">
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> </button>
</Link>
</div>
<User /> <User />
</div> </div>
</> </>

12
src/app/suitable/page.tsx Normal file
View File

@ -0,0 +1,12 @@
import Suitable from '@/components/Suitable'
import SuitableCreateBtn from '@/components/SuitableCreateBtn'
export default function suitablePage() {
return (
<>
<Suitable />
{/* 최초 한번 밀어넣음 */}
{/* <SuitableCreateBtn /> */}
</>
)
}

View File

@ -0,0 +1,20 @@
'use client'
import { suitableApi } from '@/api/suitable'
import { useQuery } from '@tanstack/react-query'
export default function Suitable() {
const { data, error, isPending } = useQuery({
queryKey: ['suitable-list'],
queryFn: suitableApi.getList,
})
return (
<>
<h1 className="text-4xl font-bold">Suitable</h1>
{error && <div>Error: {error.message}</div>}
{isPending && <div>Loading...</div>}
{data && data.map((item) => <div key={item.id}>{item.product_name}</div>)}
</>
)
}

View File

@ -0,0 +1,29 @@
'use client'
import { suitableApi } from '@/api/suitable'
import { useMutation, useQueryClient } from '@tanstack/react-query'
export default function SuitableCreateBtn() {
const queryClient = useQueryClient()
const {
mutate: createSuitable,
isPending,
error,
} = useMutation({
mutationFn: suitableApi.create,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['suitable-list'] })
},
})
return (
<>
<div>
<button className="bg-blue-500 text-white px-4 py-2 rounded-md" onClick={() => createSuitable()}>
suitable create!!
</button>
</div>
</>
)
}

76790
src/data.ts Normal file

File diff suppressed because it is too large Load Diff