df7857a8ef
Deploy Startover / deploy (push) Failing after 0s
AdSense 승인을 위한 콘텐츠 인프라와 점포라인형 매매 정보 모델을 도입. - 업종 분류 확장: 7개 대분류(휴게음식점/일반음식점/주류점/오락스포츠/판매업/서비스업/기타업종) 하위 소분류 - StoreSale 모델 추가: 월매출·월수익·창업비용·매물설명·입지특징·매매사유 - 매장 검색 카드 재설계(대표 사진 + 권리금 + 월수익), 등록/상세 페이지 매매정보 섹션 - 블로그 시스템: 17개 포스트(폐업/창업/지원금/인테리어), /blog, /blog/[slug] - 정보 페이지: /about, /terms, /privacy, /faq, /contact - SEO: sitemap.ts, robots.ts, 페이지별 메타데이터, Article·FAQ JSON-LD, OG 태그 - 주소 라벨 도로명 주소 → 주소 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
146 lines
5.4 KiB
TypeScript
146 lines
5.4 KiB
TypeScript
'use server';
|
|
|
|
import { redirect } from 'next/navigation';
|
|
import { createPrismaClient } from '@startover/database';
|
|
import { auth } from '@/lib/auth';
|
|
import { createStoreDraftService } from '@/services/store-service';
|
|
import type { CreateStoreDraftInput } from '@startover/domain';
|
|
|
|
export type StoreFormState = {
|
|
error?: string;
|
|
fieldValues?: {
|
|
listingTitle?: string;
|
|
regionClusterCode?: string;
|
|
industryMajorCode?: string;
|
|
industryLeafCode?: string;
|
|
roadAddress?: string;
|
|
depositAmount?: string;
|
|
monthlyRentAmount?: string;
|
|
premiumAmount?: string;
|
|
remainingLeaseMonths?: string;
|
|
monthlySalesAmount?: string;
|
|
monthlyProfitAmount?: string;
|
|
startupCostAmount?: string;
|
|
listingDescription?: string;
|
|
locationHighlight?: string;
|
|
saleReason?: string;
|
|
exclusiveAreaSqm?: string;
|
|
floorLevel?: string;
|
|
kitchenEquipmentSummary?: string;
|
|
};
|
|
};
|
|
|
|
export async function createStoreDraftAction(
|
|
_prevState: StoreFormState,
|
|
formData: FormData,
|
|
): Promise<StoreFormState> {
|
|
const listingTitle = (formData.get('listingTitle') as string | null)?.trim() ?? '';
|
|
const regionClusterCode = (formData.get('regionClusterCode') as string | null) ?? '';
|
|
const industryMajorCode = (formData.get('industryMajorCode') as string | null) ?? '';
|
|
const industryLeafCode = (formData.get('industryLeafCode') as string | null) ?? '';
|
|
const roadAddress = (formData.get('roadAddress') as string | null)?.trim() ?? '';
|
|
const depositAmount = formData.get('depositAmount') as string | null;
|
|
const monthlyRentAmount = formData.get('monthlyRentAmount') as string | null;
|
|
const premiumAmount = formData.get('premiumAmount') as string | null;
|
|
const remainingLeaseMonths = formData.get('remainingLeaseMonths') as string | null;
|
|
const monthlySalesAmount = formData.get('monthlySalesAmount') as string | null;
|
|
const monthlyProfitAmount = formData.get('monthlyProfitAmount') as string | null;
|
|
const startupCostAmount = formData.get('startupCostAmount') as string | null;
|
|
const listingDescription =
|
|
(formData.get('listingDescription') as string | null)?.trim() ?? '';
|
|
const locationHighlight =
|
|
(formData.get('locationHighlight') as string | null)?.trim() ?? '';
|
|
const saleReason = (formData.get('saleReason') as string | null)?.trim() ?? '';
|
|
const exclusiveAreaSqm = formData.get('exclusiveAreaSqm') as string | null;
|
|
const floorLevel = formData.get('floorLevel') as string | null;
|
|
const kitchenEquipmentSummary =
|
|
(formData.get('kitchenEquipmentSummary') as string | null)?.trim() ?? '';
|
|
|
|
const fieldValues = {
|
|
listingTitle,
|
|
regionClusterCode,
|
|
industryMajorCode,
|
|
industryLeafCode,
|
|
roadAddress,
|
|
depositAmount: depositAmount ?? undefined,
|
|
monthlyRentAmount: monthlyRentAmount ?? undefined,
|
|
premiumAmount: premiumAmount ?? undefined,
|
|
remainingLeaseMonths: remainingLeaseMonths ?? undefined,
|
|
monthlySalesAmount: monthlySalesAmount ?? undefined,
|
|
monthlyProfitAmount: monthlyProfitAmount ?? undefined,
|
|
startupCostAmount: startupCostAmount ?? undefined,
|
|
listingDescription,
|
|
locationHighlight,
|
|
saleReason,
|
|
exclusiveAreaSqm: exclusiveAreaSqm ?? undefined,
|
|
floorLevel: floorLevel ?? undefined,
|
|
kitchenEquipmentSummary,
|
|
};
|
|
|
|
const session = await auth();
|
|
if (!session?.user?.dbId) {
|
|
return { error: '로그인이 필요합니다.', fieldValues };
|
|
}
|
|
|
|
const hasSale =
|
|
premiumAmount ||
|
|
monthlySalesAmount ||
|
|
monthlyProfitAmount ||
|
|
startupCostAmount ||
|
|
listingDescription ||
|
|
locationHighlight ||
|
|
saleReason;
|
|
|
|
const input: CreateStoreDraftInput = {
|
|
ownerUserId: session.user.dbId,
|
|
listingTitle,
|
|
industryLeafCode,
|
|
regionClusterCode,
|
|
roadAddress,
|
|
...(depositAmount || monthlyRentAmount || premiumAmount || remainingLeaseMonths
|
|
? {
|
|
lease: {
|
|
depositAmount: depositAmount ? Number(depositAmount) : 0,
|
|
monthlyRentAmount: monthlyRentAmount ? Number(monthlyRentAmount) : 0,
|
|
premiumAmount: premiumAmount ? Number(premiumAmount) : 0,
|
|
remainingLeaseMonths: remainingLeaseMonths
|
|
? parseInt(remainingLeaseMonths, 10)
|
|
: undefined,
|
|
},
|
|
}
|
|
: {}),
|
|
...(hasSale
|
|
? {
|
|
sale: {
|
|
premiumAmount: premiumAmount ? Number(premiumAmount) : undefined,
|
|
monthlySalesAmount: monthlySalesAmount ? Number(monthlySalesAmount) : undefined,
|
|
monthlyProfitAmount: monthlyProfitAmount ? Number(monthlyProfitAmount) : undefined,
|
|
startupCostAmount: startupCostAmount ? Number(startupCostAmount) : undefined,
|
|
listingDescription: listingDescription || undefined,
|
|
locationHighlight: locationHighlight || undefined,
|
|
saleReason: saleReason || undefined,
|
|
},
|
|
}
|
|
: {}),
|
|
...(exclusiveAreaSqm || floorLevel || kitchenEquipmentSummary
|
|
? {
|
|
facility: {
|
|
exclusiveAreaSqm: exclusiveAreaSqm ? Number(exclusiveAreaSqm) : 0,
|
|
seatCount: 0,
|
|
floorLevel: floorLevel ? parseInt(floorLevel, 10) : undefined,
|
|
kitchenEquipmentSummary: kitchenEquipmentSummary || undefined,
|
|
},
|
|
}
|
|
: {}),
|
|
};
|
|
|
|
const prisma = createPrismaClient();
|
|
const result = await createStoreDraftService(prisma, input);
|
|
|
|
if (!result.ok) {
|
|
return { error: result.error.message, fieldValues };
|
|
}
|
|
|
|
redirect(`/stores/${result.value.publicId}`);
|
|
}
|