fix: 매장 등록 폼 검증 실패 시 입력값 보존
서버 검증 에러 발생 시 fieldValues를 반환하고 각 입력 필드에 defaultValue로 바인딩하여 사용자 입력 유지
This commit is contained in:
@@ -8,17 +8,25 @@ import type { CreateStoreDraftInput } from '@startover/domain';
|
||||
|
||||
export type StoreFormState = {
|
||||
error?: string;
|
||||
fieldValues?: {
|
||||
listingTitle?: string;
|
||||
regionClusterCode?: string;
|
||||
industryLeafCode?: string;
|
||||
roadAddress?: string;
|
||||
depositAmount?: string;
|
||||
monthlyRentAmount?: string;
|
||||
premiumAmount?: string;
|
||||
remainingLeaseMonths?: string;
|
||||
exclusiveAreaSqm?: string;
|
||||
floorLevel?: string;
|
||||
kitchenEquipmentSummary?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export async function createStoreDraftAction(
|
||||
_prevState: StoreFormState,
|
||||
formData: FormData,
|
||||
): Promise<StoreFormState> {
|
||||
const session = await auth();
|
||||
if (!session?.user?.dbId) {
|
||||
return { error: '로그인이 필요합니다.' };
|
||||
}
|
||||
|
||||
const listingTitle = (formData.get('listingTitle') as string | null)?.trim() ?? '';
|
||||
const regionClusterCode = (formData.get('regionClusterCode') as string | null) ?? '';
|
||||
const industryLeafCode = (formData.get('industryLeafCode') as string | null) ?? '';
|
||||
@@ -32,6 +40,25 @@ export async function createStoreDraftAction(
|
||||
const kitchenEquipmentSummary =
|
||||
(formData.get('kitchenEquipmentSummary') as string | null)?.trim() ?? '';
|
||||
|
||||
const fieldValues = {
|
||||
listingTitle,
|
||||
regionClusterCode,
|
||||
industryLeafCode,
|
||||
roadAddress,
|
||||
depositAmount: depositAmount ?? undefined,
|
||||
monthlyRentAmount: monthlyRentAmount ?? undefined,
|
||||
premiumAmount: premiumAmount ?? undefined,
|
||||
remainingLeaseMonths: remainingLeaseMonths ?? undefined,
|
||||
exclusiveAreaSqm: exclusiveAreaSqm ?? undefined,
|
||||
floorLevel: floorLevel ?? undefined,
|
||||
kitchenEquipmentSummary,
|
||||
};
|
||||
|
||||
const session = await auth();
|
||||
if (!session?.user?.dbId) {
|
||||
return { error: '로그인이 필요합니다.', fieldValues };
|
||||
}
|
||||
|
||||
const input: CreateStoreDraftInput = {
|
||||
ownerUserId: session.user.dbId,
|
||||
listingTitle,
|
||||
@@ -66,7 +93,7 @@ export async function createStoreDraftAction(
|
||||
const result = await createStoreDraftService(prisma, input);
|
||||
|
||||
if (!result.ok) {
|
||||
return { error: result.error.message };
|
||||
return { error: result.error.message, fieldValues };
|
||||
}
|
||||
|
||||
redirect(`/stores/${result.value.publicId}`);
|
||||
|
||||
@@ -40,6 +40,7 @@ export default function NewStorePage() {
|
||||
name="listingTitle"
|
||||
placeholder="예: 강남역 카페 양도"
|
||||
required
|
||||
defaultValue={state.fieldValues?.listingTitle}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -49,6 +50,7 @@ export default function NewStorePage() {
|
||||
<select
|
||||
name="regionClusterCode"
|
||||
required
|
||||
defaultValue={state.fieldValues?.regionClusterCode}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
||||
>
|
||||
<option value="">지역 선택</option>
|
||||
@@ -61,6 +63,7 @@ export default function NewStorePage() {
|
||||
<select
|
||||
name="industryLeafCode"
|
||||
required
|
||||
defaultValue={state.fieldValues?.industryLeafCode}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
||||
>
|
||||
<option value="">업종 선택</option>
|
||||
@@ -78,6 +81,7 @@ export default function NewStorePage() {
|
||||
name="roadAddress"
|
||||
placeholder="예: 서울시 강남구 테헤란로 123"
|
||||
required
|
||||
defaultValue={state.fieldValues?.roadAddress}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -95,6 +99,7 @@ export default function NewStorePage() {
|
||||
type="number"
|
||||
name="depositAmount"
|
||||
placeholder="50000000"
|
||||
defaultValue={state.fieldValues?.depositAmount}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -104,6 +109,7 @@ export default function NewStorePage() {
|
||||
type="number"
|
||||
name="monthlyRentAmount"
|
||||
placeholder="3000000"
|
||||
defaultValue={state.fieldValues?.monthlyRentAmount}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -115,6 +121,7 @@ export default function NewStorePage() {
|
||||
type="number"
|
||||
name="premiumAmount"
|
||||
placeholder="30000000"
|
||||
defaultValue={state.fieldValues?.premiumAmount}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -126,6 +133,7 @@ export default function NewStorePage() {
|
||||
type="number"
|
||||
name="remainingLeaseMonths"
|
||||
placeholder="18"
|
||||
defaultValue={state.fieldValues?.remainingLeaseMonths}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -145,6 +153,7 @@ export default function NewStorePage() {
|
||||
name="exclusiveAreaSqm"
|
||||
placeholder="82.6"
|
||||
step="0.01"
|
||||
defaultValue={state.fieldValues?.exclusiveAreaSqm}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -154,6 +163,7 @@ export default function NewStorePage() {
|
||||
type="number"
|
||||
name="floorLevel"
|
||||
placeholder="1"
|
||||
defaultValue={state.fieldValues?.floorLevel}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -164,6 +174,7 @@ export default function NewStorePage() {
|
||||
rows={3}
|
||||
name="kitchenEquipmentSummary"
|
||||
placeholder="주방 시설, 인테리어 상태, 포함 장비 등을 자유롭게 작성해주세요"
|
||||
defaultValue={state.fieldValues?.kitchenEquipmentSummary}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user