154 lines
6.6 KiB
TypeScript
154 lines
6.6 KiB
TypeScript
import useFetchHosting from "../utils/fetchHosting";
|
||
import { useNotification, type NotificationType } from "../NotificationContext";
|
||
import { useCookies } from "react-cookie";
|
||
import CenteredContainer from "./ChildrenContainer";
|
||
import { useState } from "react";
|
||
|
||
|
||
interface ReserveButtonProps {
|
||
update: (name: string, id: number) => void,
|
||
unreserve: (token: string, id: number) => void,
|
||
reservedBy: string,
|
||
notify: (message: string, type: NotificationType) => void,
|
||
id: number,
|
||
}
|
||
|
||
const ReserveButton: React.FC<ReserveButtonProps> = (props) => {
|
||
const { reservedBy, update, id, unreserve, notify } = props;
|
||
const [cookie] = useCookies<string>(['userName'])
|
||
const [tokenCookie] = useCookies<string>(['apiToken'])
|
||
const userName = cookie.userName;
|
||
const isReserved = reservedBy !== '';
|
||
|
||
const handleReserve = async (name: string) => {
|
||
try {
|
||
await update(name, id);
|
||
notify(`Успешно забронировано для ${name}`, 'success');
|
||
} catch (error) {
|
||
notify(`Не удалось забронировать: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error');
|
||
}
|
||
};
|
||
|
||
const handleUnreserve = async () => {
|
||
try {
|
||
await unreserve(tokenCookie.apiToken, id);
|
||
notify(`Удалось разбронировать ${name}`, 'success');
|
||
} catch (error) {
|
||
notify(`Не удалось разбронировать: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error');
|
||
}
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<button onClick={() => handleReserve(userName)} disabled={isReserved}>
|
||
{isReserved ? `${reservedBy}` : 'Занять'}
|
||
</button>
|
||
{(reservedBy == userName) && (
|
||
<button onClick={() => handleUnreserve()} disabled={false}>❌</button>
|
||
)}
|
||
</>
|
||
);
|
||
};
|
||
|
||
|
||
const Hosting = () => {
|
||
const { data, error, loading, update, unreserveHosting, createHosting } = useFetchHosting();
|
||
const [name, setName] = useState('');
|
||
const [capacity, setCapacity] = useState('');
|
||
const [tokenCookie] = useCookies<string>(['apiToken'])
|
||
const notify = useNotification();
|
||
|
||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||
event.preventDefault(); // Prevent the default form submission
|
||
|
||
if (!name || !capacity) {
|
||
notify('Надо заполнить все поля', 'error');
|
||
return;
|
||
}
|
||
try {
|
||
await createHosting(tokenCookie.apiToken, name, Number(capacity));
|
||
|
||
// Reset form fields
|
||
setName('');
|
||
setCapacity('');
|
||
notify('Удалось создать!', 'success');
|
||
} catch (error) {
|
||
notify(`Не удалось создать: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error');
|
||
}
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<CenteredContainer>
|
||
<h2>Поселение</h2>
|
||
<p>
|
||
Мы готовы приютить в наших 150 квадратах всех. У нас есть 6 спальных мест. При этом, если
|
||
вы не хотите тесниться, то рядом с нами есть
|
||
<a href="https://www.uoti.net/" target="_blank" rel="noopener noreferrer"> отель</a>, а так же
|
||
<a href="https://campingsysma.fi/" target="_blank" rel="noopener noreferrer"> кэмпинг-виллы </a>
|
||
(Лучше бронировать заранее если есть надобность. Оба в 1-1,5км от нашего дома).
|
||
Спальные места:
|
||
</p>
|
||
{loading && <div>Loading...</div>}
|
||
{error && <div>Error</div>}
|
||
{data && (
|
||
<div className="table-wrapper scroll-indicator">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Размещение</th>
|
||
<th>Спальных мест</th>
|
||
<th>Бронирование</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{data.furniture && data.furniture.map((item) => (
|
||
<tr key={item.id}>
|
||
<td>{item.name}</td>
|
||
<td>{item.capacity}</td>
|
||
<td>
|
||
<ReserveButton update={update} reservedBy={item.reservedBy} id={item.id} unreserve={unreserveHosting} notify={notify} />
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
<p className="scroll-instruction">Таблицу можно скроллить</p>
|
||
</div>
|
||
)}
|
||
Если вы хотите организовать себе свои спальные места и хотите, чтобы остальные это видели, вы можете добавить свое месо в таблицу.
|
||
<form onSubmit={handleSubmit}>
|
||
<div>
|
||
<label>
|
||
Размещение:
|
||
<input
|
||
type="text"
|
||
value={name}
|
||
onChange={(e) => setName(e.target.value)}
|
||
required
|
||
/>
|
||
</label>
|
||
</div>
|
||
<div>
|
||
<label>
|
||
Спальных мест:
|
||
<input
|
||
type="number"
|
||
value={capacity}
|
||
onChange={(e) => setCapacity(e.target.value)}
|
||
required
|
||
/>
|
||
</label>
|
||
</div>
|
||
<button type="submit">
|
||
{'Создать размещение'}
|
||
</button>
|
||
</form>
|
||
|
||
</CenteredContainer>
|
||
<br />
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default Hosting; |