generated from pricelees/issue-pr-template
122 lines
4.9 KiB
TypeScript
122 lines
4.9 KiB
TypeScript
import { isLoginRequiredError } from '@_api/apiClient';
|
|
import { createPendingReservation } from '@_api/reservation/reservationAPIV2';
|
|
import '@_css/reservation-v2-1.css';
|
|
import React, { useState } from 'react';
|
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
import { formatDate, formatTime } from 'src/util/DateTimeFormatter';
|
|
|
|
const ReservationFormPage: React.FC = () => {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const { scheduleId, theme, date, time } = location.state || {};
|
|
|
|
const [reserverName, setReserverName] = useState('');
|
|
const [reserverContact, setReserverContact] = useState('');
|
|
const [participantCount, setParticipantCount] = useState(2);
|
|
const [requirement, setRequirement] = useState('');
|
|
|
|
const handleError = (err: any) => {
|
|
if (isLoginRequiredError(err)) {
|
|
alert('로그인이 필요해요.');
|
|
navigate('/login', { state: { from: location } });
|
|
} else {
|
|
const message = err.response?.data?.message || '알 수 없는 오류가 발생했습니다.';
|
|
alert(message);
|
|
console.error(err);
|
|
}
|
|
};
|
|
|
|
const handleCountChange = (delta: number) => {
|
|
setParticipantCount(prev => Math.max(theme.minParticipants, Math.min(theme.maxParticipants, prev + delta)));
|
|
};
|
|
|
|
const handlePayment = () => {
|
|
if (!reserverName || !reserverContact) {
|
|
alert('예약자명과 연락처를 입력해주세요.');
|
|
return;
|
|
}
|
|
|
|
const reservationData = {
|
|
scheduleId,
|
|
reserverName,
|
|
reserverContact,
|
|
participantCount,
|
|
requirement,
|
|
};
|
|
|
|
createPendingReservation(reservationData)
|
|
.then(res => {
|
|
navigate('/v2-1/reservation/payment', {
|
|
state: {
|
|
reservationId: res.id,
|
|
themeName: theme.name,
|
|
date: date,
|
|
startAt: time,
|
|
price: theme.price * participantCount,
|
|
}
|
|
});
|
|
})
|
|
.catch(handleError);
|
|
};
|
|
|
|
if (!scheduleId || !theme) {
|
|
// Handle case where state is not passed correctly
|
|
return (
|
|
<div className="reservation-v21-container">
|
|
<h2 className="page-title">잘못된 접근</h2>
|
|
<p>예약 정보가 올바르지 않습니다. 예약 페이지로 다시 이동해주세요.</p>
|
|
<button onClick={() => navigate('/v2-1/reservation')} className="next-step-button">예약 페이지로</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="reservation-v21-container">
|
|
<h2 className="page-title">예약 정보 입력</h2>
|
|
|
|
<div className="step-section">
|
|
<h3>예약 내용 확인</h3>
|
|
<p><strong>테마:</strong> {theme.name}</p>
|
|
<p><strong>날짜:</strong> {formatDate(date)}</p>
|
|
<p><strong>시간:</strong> {formatTime(time)}</p>
|
|
</div>
|
|
|
|
<div className="step-section">
|
|
<h3>예약자 정보</h3>
|
|
<div className="form-group">
|
|
<label htmlFor="reserverName">예약자명</label>
|
|
<input type="text" id="reserverName" value={reserverName} onChange={e => setReserverName(e.target.value)} />
|
|
</div>
|
|
<div className="form-group">
|
|
<label htmlFor="reserverContact">연락처</label>
|
|
<input type="tel" id="reserverContact" value={reserverContact} onChange={e => setReserverContact(e.target.value)} placeholder="'-' 없이 입력"/>
|
|
</div>
|
|
<div className="form-group">
|
|
<label>인원</label>
|
|
<div className="participant-control">
|
|
<input
|
|
type="number"
|
|
value={participantCount}
|
|
onChange={e => setParticipantCount(Math.max(theme.minParticipants, Math.min(theme.maxParticipants, Number(e.target.value))))}
|
|
min={theme.minParticipants}
|
|
max={theme.maxParticipants}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="form-group">
|
|
<label htmlFor="requirement">요청사항</label>
|
|
<textarea id="requirement" value={requirement} onChange={e => setRequirement(e.target.value)} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="next-step-button-container">
|
|
<button onClick={handlePayment} className="next-step-button">
|
|
결제하기
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ReservationFormPage;
|