feat: bootstrap TitipIn application with fullstack architecture, Prisma ORM, and shadcn/ui components
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
'use server'
|
||||
|
||||
import prisma from '@/lib/prisma'
|
||||
import { revalidatePath } from 'next/cache'
|
||||
|
||||
// === USER ACTIONS ===
|
||||
export async function checkUser(id: string) {
|
||||
return await prisma.user.findUnique({ where: { id } })
|
||||
}
|
||||
|
||||
export async function registerUser(id: string, name: string, photo?: string) {
|
||||
try {
|
||||
const user = await prisma.user.create({
|
||||
data: { id, name, photo }
|
||||
})
|
||||
return { success: true, user }
|
||||
} catch (error: any) {
|
||||
if (error.code === 'P2002') return { success: false, error: 'Nama sudah digunakan.' }
|
||||
return { success: false, error: 'Terjadi kesalahan.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateProfile(id: string, name: string, photo?: string) {
|
||||
try {
|
||||
const user = await prisma.user.update({
|
||||
where: { id },
|
||||
data: { name, photo }
|
||||
})
|
||||
revalidatePath('/')
|
||||
revalidatePath('/profile')
|
||||
return { success: true, user }
|
||||
} catch (error: any) {
|
||||
if (error.code === 'P2002') return { success: false, error: 'Nama sudah digunakan.' }
|
||||
return { success: false, error: 'Gagal memperbarui profil.' }
|
||||
}
|
||||
}
|
||||
|
||||
// === ORDER ACTIONS (DASHBOARD & CREATE) ===
|
||||
export async function getAvailableOrders() {
|
||||
const startOfDay = new Date()
|
||||
startOfDay.setHours(0, 0, 0, 0)
|
||||
|
||||
const endOfDay = new Date()
|
||||
endOfDay.setHours(23, 59, 59, 999)
|
||||
|
||||
return await prisma.order.findMany({
|
||||
where: {
|
||||
status: 'OPEN',
|
||||
date: { gte: startOfDay, lte: endOfDay }
|
||||
},
|
||||
include: {
|
||||
creator: true,
|
||||
available_items: true,
|
||||
submissions: { select: { user_id: true } }
|
||||
},
|
||||
orderBy: { date: 'desc' }
|
||||
})
|
||||
}
|
||||
|
||||
export async function getMyOrders(creator_id: string) {
|
||||
return await prisma.order.findMany({
|
||||
where: { creator_id },
|
||||
include: {
|
||||
available_items: true,
|
||||
submissions: { select: { id: true } }
|
||||
},
|
||||
orderBy: { date: 'desc' }
|
||||
})
|
||||
}
|
||||
|
||||
export async function createOrder(data: {
|
||||
creator_id: string;
|
||||
title: string;
|
||||
date: Date;
|
||||
allow_custom: boolean;
|
||||
available_items: string[];
|
||||
}) {
|
||||
try {
|
||||
const order = await prisma.order.create({
|
||||
data: {
|
||||
title: data.title,
|
||||
date: data.date,
|
||||
allow_custom: data.allow_custom,
|
||||
creator_id: data.creator_id,
|
||||
status: 'DRAFT',
|
||||
available_items: {
|
||||
create: data.available_items.map(name => ({ name }))
|
||||
}
|
||||
}
|
||||
})
|
||||
revalidatePath('/my-orders')
|
||||
return { success: true, order }
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Gagal membuat order.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function duplicateOrder(order_id: string) {
|
||||
try {
|
||||
const oldOrder = await prisma.order.findUnique({
|
||||
where: { id: order_id },
|
||||
include: { available_items: true }
|
||||
})
|
||||
if (!oldOrder) return { success: false, error: 'Order tidak ditemukan' }
|
||||
|
||||
const newOrder = await prisma.order.create({
|
||||
data: {
|
||||
title: oldOrder.title + ' (Copy)',
|
||||
date: new Date(),
|
||||
allow_custom: oldOrder.allow_custom,
|
||||
creator_id: oldOrder.creator_id,
|
||||
status: 'DRAFT',
|
||||
available_items: {
|
||||
create: oldOrder.available_items.map(ai => ({ name: ai.name }))
|
||||
}
|
||||
}
|
||||
})
|
||||
revalidatePath('/my-orders')
|
||||
return { success: true, order: newOrder }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal menduplikasi order.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateOrder(order_id: string, data: {
|
||||
title: string;
|
||||
allow_custom: boolean;
|
||||
available_items: string[];
|
||||
}) {
|
||||
try {
|
||||
const order = await prisma.order.findUnique({
|
||||
where: { id: order_id }
|
||||
})
|
||||
if (!order) return { success: false, error: 'Order tidak ditemukan' }
|
||||
if (order.status === 'CLOSE') {
|
||||
return { success: false, error: 'Order dengan status CLOSE tidak dapat diedit.' }
|
||||
}
|
||||
|
||||
// Delete existing available items and insert updated ones
|
||||
await prisma.availableItem.deleteMany({
|
||||
where: { order_id }
|
||||
})
|
||||
|
||||
const updatedOrder = await prisma.order.update({
|
||||
where: { id: order_id },
|
||||
data: {
|
||||
title: data.title,
|
||||
allow_custom: data.allow_custom,
|
||||
available_items: {
|
||||
create: data.available_items.map(name => ({ name }))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
revalidatePath('/my-orders')
|
||||
revalidatePath(`/my-orders/${order_id}`)
|
||||
revalidatePath('/')
|
||||
return { success: true, order: updatedOrder }
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Gagal memperbarui order.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateOrderStatus(order_id: string, status: string) {
|
||||
try {
|
||||
await prisma.order.update({
|
||||
where: { id: order_id },
|
||||
data: { status }
|
||||
})
|
||||
revalidatePath('/my-orders')
|
||||
revalidatePath('/')
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal mengubah status.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteOrder(order_id: string) {
|
||||
try {
|
||||
const order = await prisma.order.findUnique({
|
||||
where: { id: order_id }
|
||||
})
|
||||
if (!order) return { success: false, error: 'Order tidak ditemukan.' }
|
||||
if (order.status === 'OPEN') {
|
||||
return { success: false, error: 'Order berstatus OPEN tidak dapat dihapus. Silakan tutup (CLOSE) terlebih dahulu.' }
|
||||
}
|
||||
|
||||
await prisma.order.delete({
|
||||
where: { id: order_id }
|
||||
})
|
||||
|
||||
revalidatePath('/my-orders')
|
||||
revalidatePath('/')
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal menghapus order.' }
|
||||
}
|
||||
}
|
||||
|
||||
// === ORDER DETAIL ===
|
||||
export async function getOrderDetail(order_id: string) {
|
||||
return await prisma.order.findUnique({
|
||||
where: { id: order_id },
|
||||
include: {
|
||||
creator: true,
|
||||
available_items: true,
|
||||
submissions: {
|
||||
include: {
|
||||
user: true,
|
||||
items: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateSubmissionPayment(submission_id: string, bill: number | null, payment_status: string) {
|
||||
try {
|
||||
await prisma.submission.update({
|
||||
where: { id: submission_id },
|
||||
data: { bill, payment_status }
|
||||
})
|
||||
revalidatePath(`/my-orders`)
|
||||
revalidatePath(`/my-purchases`)
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal menyimpan tagihan.' }
|
||||
}
|
||||
}
|
||||
|
||||
// === SUBMISSION (PESANAN SAYA) ===
|
||||
export async function getUserSubmission(order_id: string, user_id: string) {
|
||||
return await prisma.submission.findFirst({
|
||||
where: { order_id, user_id },
|
||||
include: { items: true }
|
||||
})
|
||||
}
|
||||
|
||||
export async function getMyPurchases(user_id: string) {
|
||||
return await prisma.submission.findMany({
|
||||
where: { user_id },
|
||||
include: {
|
||||
order: {
|
||||
include: {
|
||||
creator: true,
|
||||
available_items: true
|
||||
}
|
||||
},
|
||||
items: true
|
||||
},
|
||||
orderBy: {
|
||||
order: { date: 'desc' }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function submitOrder(data: {
|
||||
order_id: string;
|
||||
user_id: string;
|
||||
items: Array<{ name: string; qty: number; is_custom: boolean }>;
|
||||
}) {
|
||||
try {
|
||||
if (data.items.length === 0) {
|
||||
return { success: false, error: 'Pilih minimal 1 item.' }
|
||||
}
|
||||
|
||||
const existing = await prisma.submission.findFirst({
|
||||
where: { order_id: data.order_id, user_id: data.user_id }
|
||||
})
|
||||
|
||||
if (existing) {
|
||||
await prisma.submissionItem.deleteMany({ where: { submission_id: existing.id } })
|
||||
await prisma.submission.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
items: {
|
||||
create: data.items
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await prisma.submission.create({
|
||||
data: {
|
||||
order_id: data.order_id,
|
||||
user_id: data.user_id,
|
||||
items: {
|
||||
create: data.items
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
revalidatePath('/')
|
||||
revalidatePath('/my-purchases')
|
||||
revalidatePath(`/my-orders/${data.order_id}`)
|
||||
|
||||
return { success: true }
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return { success: false, error: 'Gagal mengirim pesanan.' }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user