Добавлено модальное окно выбора города с сохранением выбора в localStorage. Обновлена логика управления состоянием для выбора города в компоненте Home, улучшено взаимодействие с пользователем при загрузке страницы.

This commit is contained in:
Bivekich
2025-04-22 15:08:33 +03:00
parent ff16a39b2a
commit 91837b705a
2 changed files with 165 additions and 1 deletions

View File

@ -0,0 +1,134 @@
'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { MapPin, X } from 'lucide-react';
import { Button } from '@/components/ui/button';
interface CitySelectModalProps {
isOpen: boolean;
onClose: () => void;
onSelectCity: (city: 'Москва' | 'Чебоксары') => void;
currentCity: 'Москва' | 'Чебоксары';
}
const CitySelectModal = ({
isOpen,
onClose,
onSelectCity,
currentCity,
}: CitySelectModalProps) => {
if (!isOpen) return null;
const overlayVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
};
const modalVariants = {
hidden: { opacity: 0, y: 50, scale: 0.95 },
visible: {
opacity: 1,
y: 0,
scale: 1,
transition: { duration: 0.3, ease: [0.16, 1, 0.3, 1] },
},
exit: {
opacity: 0,
y: 50,
scale: 0.95,
transition: { duration: 0.2 },
},
};
return (
<AnimatePresence mode="wait">
{isOpen && (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<motion.div
initial="hidden"
animate="visible"
exit="hidden"
variants={overlayVariants}
className="absolute inset-0 bg-black/50"
onClick={onClose}
/>
<motion.div
initial="hidden"
animate="visible"
exit="exit"
variants={modalVariants}
className="bg-white rounded-xl shadow-xl p-6 w-full max-w-md z-10 mx-4"
>
<div className="flex justify-between items-center mb-6">
<h2 className="text-2xl font-bold text-gray-900">
Выберите город
</h2>
<button
onClick={onClose}
className="w-8 h-8 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 text-gray-600"
>
<X className="h-5 w-5" />
</button>
</div>
<p className="text-gray-600 mb-6">
Пожалуйста, выберите ваш город для получения актуальной информации
о наших услугах и контактах
</p>
<div className="space-y-3 mb-6">
<button
onClick={() => {
onSelectCity('Москва');
onClose();
}}
className={`w-full py-3 px-4 rounded-lg text-left flex items-center ${
currentCity === 'Москва'
? 'bg-blue-50 text-blue-700 border border-blue-200'
: 'text-gray-700 hover:bg-gray-100 border border-gray-200'
}`}
>
<MapPin className="h-5 w-5 mr-3 flex-shrink-0" />
<div>
<span className="font-medium">Москва</span>
<p className="text-sm text-gray-500">
ул. Космонавта Волкова, д. 29к1
</p>
</div>
</button>
<button
onClick={() => {
onSelectCity('Чебоксары');
onClose();
}}
className={`w-full py-3 px-4 rounded-lg text-left flex items-center ${
currentCity === 'Чебоксары'
? 'bg-blue-50 text-blue-700 border border-blue-200'
: 'text-gray-700 hover:bg-gray-100 border border-gray-200'
}`}
>
<MapPin className="h-5 w-5 mr-3 flex-shrink-0" />
<div>
<span className="font-medium">Чебоксары</span>
<p className="text-sm text-gray-500">
ул. Зои Яковлевой, д. 54
</p>
</div>
</button>
</div>
<Button
onClick={onClose}
className="w-full bg-blue-700 hover:bg-blue-800 text-white"
>
Продолжить
</Button>
</motion.div>
</div>
)}
</AnimatePresence>
);
};
export default CitySelectModal;

View File

@ -13,12 +13,35 @@ import Contacts from './components/Contacts';
import ContactForm from './components/ContactForm';
import Footer from './components/Footer';
import Loader from './components/Loader';
import CitySelectModal from './components/CitySelectModal';
export default function Home() {
const [selectedCity, setSelectedCity] = useState<'Москва' | 'Чебоксары'>(
'Москва'
);
const [isLoading, setIsLoading] = useState(true);
const [isCityModalOpen, setIsCityModalOpen] = useState(false);
useEffect(() => {
// Проверяем, выбирал ли пользователь город ранее
const savedCity = localStorage.getItem('selectedCity');
if (savedCity) {
setSelectedCity(savedCity as 'Москва' | 'Чебоксары');
} else {
// Если город не выбран, показываем модальное окно после загрузки
// Устанавливаем таймер, чтобы сначала загрузка прошла, а потом показалось модальное окно
const timer = setTimeout(() => {
setIsCityModalOpen(true);
}, 2300); // Чуть больше времени, чем таймер загрузки
return () => clearTimeout(timer);
}
}, []);
// Сохраняем выбор города в localStorage
const handleCityChange = (city: 'Москва' | 'Чебоксары') => {
setSelectedCity(city);
localStorage.setItem('selectedCity', city);
};
useEffect(() => {
// Имитация загрузки ресурсов
@ -44,7 +67,7 @@ export default function Home() {
>
<Header
selectedCity={selectedCity}
onCityChange={setSelectedCity}
onCityChange={handleCityChange}
/>
<main className="flex-1">
<Hero selectedCity={selectedCity} />
@ -60,6 +83,13 @@ export default function Home() {
</motion.div>
)}
</AnimatePresence>
<CitySelectModal
isOpen={isCityModalOpen}
onClose={() => setIsCityModalOpen(false)}
onSelectCity={handleCityChange}
currentCity={selectedCity}
/>
</>
);
}