Files
tripwithbonus/frontend/app/(urls)/account/create-as-sender/page.tsx
2025-05-21 17:36:10 +03:00

290 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import React from 'react'
import MultiSelect from '@/components/ui/Selector'
import TextInput from '@/components/ui/TextInput'
import PhoneInput from '@/components/ui/PhoneInput'
import Button from '@/components/ui/Button'
import TextAreaInput from '@/components/ui/TextAreaInput'
import CheckboxInput from '@/components/ui/CheckboxInput'
import { useForm } from '@/app/hooks/useForm'
import showToast from '@/components/ui/Toast'
import { SenderPageProps, SelectOption } from '@/app/types'
import {
cargo_types,
cargo_type_translations,
transport_types,
transport_translations,
} from '@/app/constants'
const formatDateToHTML = (date: Date) => {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
return `${year}-${month}-${day}T${hours}:${minutes}`
}
const validationRules = {
transport: { required: true },
country_from: { required: true, minLength: 2 },
city_from: { required: true, minLength: 2 },
country_to: { required: true, minLength: 2 },
city_to: { required: true, minLength: 2 },
cargo_type: { required: true },
departure: {
required: true,
pattern: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/,
},
arrival: {
required: true,
pattern: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/,
},
contact_number: {
required: true,
minLength: 11,
pattern: /^\+?[0-9]{11,}$/,
},
comment: { required: false, minLength: 10 },
email_notification: { required: false },
}
const SenderPage = () => {
const today = formatDateToHTML(new Date())
const initialValues: SenderPageProps = {
transport: '',
country_from: '',
city_from: '',
country_to: '',
city_to: '',
cargo_type: '',
departure: '',
arrival: '',
contact_number: '',
comment: '',
email_notification: false,
}
const cargoOptions: SelectOption[] = cargo_types.map((type, index) => ({
id: index + 1,
label: cargo_type_translations[type],
value: type,
}))
const transportOptions: SelectOption[] = transport_types.map((type, index) => ({
id: index + 1,
label: transport_translations[type],
value: type,
}))
const { values, handleChange, handleSubmit } = useForm<SenderPageProps>(
initialValues,
validationRules,
async values => {
try {
// await addNewSpecialist(values, selectedImage || undefined)
showToast({
type: 'success',
message: 'Маршрут успешно создан!',
})
} catch {
showToast({
type: 'error',
message: 'Упс, что то пошло не так...',
})
}
}
)
return (
<form onSubmit={handleSubmit} className="space-y-6">
<div className="overflow-hidden rounded-2xl bg-white shadow">
<div className="p-6 sm:p-8">
<div className="space-y-8">
<div>
<h1 className="text-2xl font-semibold text-gray-900">Отправить посылку</h1>
<p className="mt-1 text-sm text-gray-600">
Заполните информацию о вашей посылке и маршруте
</p>
</div>
{/* тип груза и транспорта */}
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label htmlFor="cargo_type" className="block text-sm font-medium text-gray-700">
Тип груза
</label>
<MultiSelect
value={values.cargo_type ? [parseInt(values.cargo_type)] : []}
handleChange={e => {
handleChange({
target: {
id: 'cargo_type',
value: e.target.value[0]?.toString() || '',
},
})
}}
name="cargo_type"
options={cargoOptions}
className="mt-1"
placeholder="Выберите тип груза"
noOptionsMessage="Нет доступных типов груза"
/>
</div>
<div>
<label htmlFor="transport" className="block text-sm font-medium text-gray-700">
Способ перевозки
</label>
<MultiSelect
value={values.transport ? [parseInt(values.transport)] : []}
handleChange={e => {
handleChange({
target: {
id: 'transport',
value: e.target.value[0]?.toString() || '',
},
})
}}
name="transport"
options={transportOptions}
className="mt-1"
placeholder="Выберите способ перевозки"
noOptionsMessage="Нет доступных способов перевозки"
/>
</div>
</div>
{/* маршрут */}
<div>
<h2 className="mb-2 text-xl font-medium text-gray-900">Маршрут</h2>
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div className="space-y-6">
<TextInput
name="country_from"
value={values.country_from}
handleChange={handleChange}
label="Страна отправления"
placeholder="Введите страну отправления"
style="register"
/>
<TextInput
name="country_to"
value={values.country_to}
handleChange={handleChange}
label="Страна назначения"
placeholder="Введите страну назначения"
style="register"
/>
</div>
<div className="space-y-6">
<TextInput
name="city_to"
value={values.city_to}
handleChange={handleChange}
label="Город назначения"
placeholder="Введите город назначения"
style="register"
/>
<TextInput
name="country_to"
value={values.country_to}
handleChange={handleChange}
label="Страна назначения"
placeholder="Введите страну назначения"
style="register"
/>
</div>
</div>
</div>
{/* даты */}
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label htmlFor="departure" className="block text-sm font-medium text-gray-700">
Дата отправления
</label>
<input
type="datetime-local"
name="departure"
id="departure"
value={values.departure}
onChange={handleChange}
min={today}
className="mt-1 block w-full rounded-xl border border-gray-300 px-3 py-2 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
/>
</div>
<div>
<label htmlFor="arrival" className="block text-sm font-medium text-gray-700">
Дата прибытия
</label>
<input
type="datetime-local"
name="arrival"
id="arrival"
value={values.arrival}
onChange={handleChange}
min={values.departure || today}
className="mt-1 block w-full rounded-xl border border-gray-300 px-3 py-2 focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
/>
</div>
</div>
{/* контактная информация */}
<h2 className="mb-2 text-xl font-medium text-gray-900">Контактная информация</h2>
<div className="space-y-6">
<PhoneInput
value={values.contact_number}
handleChange={handleChange}
label="Контактный телефон"
operatorsInfo={false}
/>
<TextAreaInput
value={values.comment}
handleChange={handleChange}
label="Комментарий"
placeholder="Дополнительная информация о грузе или пожелания"
name="comment"
/>
<CheckboxInput
name="email_notification"
label="Уведомления"
checked={values.email_notification}
handleChange={handleChange}
enabledText="Хочу получать уведомления по email"
disabledText="Не получать уведомления"
info="Вы будете получать уведомления о важных событиях на указанный email адрес"
/>
</div>
</div>
</div>
</div>
{/* кнопки действий */}
<div className="flex justify-end space-x-4">
<Button
type="button"
text="Отмена"
className="border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none"
/>
<Button
type="submit"
text="Создать маршрут"
className="bg-orange hover:bg-orange/80 focus:ring-red w-1/3 border border-gray-300 py-2 text-sm font-medium text-white shadow-sm focus:ring-2 focus:ring-offset-2 focus:outline-none"
/>
</div>
</form>
)
}
export default SenderPage