diff --git a/frontend/src/NotificationContext.tsx b/frontend/src/NotificationContext.tsx new file mode 100644 index 0000000..baeb8ac --- /dev/null +++ b/frontend/src/NotificationContext.tsx @@ -0,0 +1,81 @@ +// src/NotificationContext.tsx + +import React, { createContext, useContext, useState } from 'react'; + +type NotificationType = 'success' | 'error'; + +interface NotificationContextType { + notify: (message: string, type: NotificationType) => void; +} + +const NotificationContext = createContext(undefined); + +export const NotificationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [notification, setNotification] = useState(null); + const [notificationType, setNotificationType] = useState(null); + + const notify = (message: string, type: NotificationType) => { + setNotification(message); + setNotificationType(type); + + // Automatically dismiss notification after 3 seconds + setTimeout(() => { + setNotification(null); + setNotificationType(null); + }, 3000); + }; + + return ( + + {children} + {notification && ( + setNotification(null)} type={notificationType!} /> + )} + + ); +}; + +export const useNotification = () => { + const context = useContext(NotificationContext); + if (!context) { + throw new Error('useNotification must be used within a NotificationProvider'); + } + return context.notify; +}; + + +interface NotificationProps { + message: string; + onClose: () => void; + type: 'success' | 'error'; // Define notification types +} + +// Notification Component +const Notification: React.FC = ({ message, onClose, type }) => { + return ( +
+

{message}

+ +
+ ); +}; + +// Notification styles remain the same... +const styles: { [key: string]: React.CSSProperties } = { + notification: { + position: 'fixed', + top: '20px', + right: '20px', + color: 'white', + padding: '15px', + borderRadius: '5px', + zIndex: 1000, + }, + closeButton: { + background: 'transparent', + border: 'none', + color: 'white', + cursor: 'pointer', + marginLeft: '10px', + }, +}; diff --git a/frontend/src/components/Hosting.tsx b/frontend/src/components/Hosting.tsx index 66c0164..410cf28 100644 --- a/frontend/src/components/Hosting.tsx +++ b/frontend/src/components/Hosting.tsx @@ -1,5 +1,6 @@ import { useState } from "react"; import useFetchHosting from "../utils/fetchHosting"; +import { useNotification } from "../NotificationContext"; interface ReserveButtonProps { @@ -10,12 +11,21 @@ interface ReserveButtonProps { const ReserveButton: React.FC = (props) => { const { reservedBy, update, id } = props; - const [name, setName] = useState(reservedBy); + const [name, setName] = useState(reservedBy || ''); // Default to empty if not reserved const isReserved = reservedBy !== ''; + const notify = useNotification(); const handleReserve = async () => { - if (name.trim()) { - await update(name, id); // Call the update function from props with the name and id + if (!name.trim()) { + notify('Поле имени не может быть пустым', 'error'); + return; + } + + try { + await update(name, id); // Await the update call + notify(`Успешно забронировано для ${name}`, 'success'); // Move success notification here + } catch (error) { + notify(`Не удалось забронировать: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error'); } }; @@ -26,7 +36,7 @@ const ReserveButton: React.FC = (props) => { value={name} onChange={(e) => setName(e.target.value)} placeholder="Введите ваше имя" - disabled={isReserved} // Disable if already reserved + disabled={isReserved} // Disable input if already reserved />