Merge version_2 into main #2
186
src/app/page.tsx
186
src/app/page.tsx
@@ -10,8 +10,107 @@ import FaqDouble from "@/components/sections/faq/FaqDouble";
|
||||
import ContactText from "@/components/sections/contact/ContactText";
|
||||
import FooterCard from "@/components/sections/footer/FooterCard";
|
||||
import { Heart, HelpCircle, Mail, MapPin, Phone, Sparkles, Star } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function LandingPage() {
|
||||
const [servicesData, setServicesData] = useState([
|
||||
{
|
||||
id: "01", title: "Роскошный дом", description: "Просторный современный дом с высокотехнологичным оснащением, каминами и панорамными окнами для максимального комфорта", images: [
|
||||
{
|
||||
id: "img-01-01", src: "http://img.b2bpic.net/free-photo/modern-spacious-room-with-large-panoramic-window_7502-7289.jpg", alt: "Премиум дом для отдыха - вид 1"},
|
||||
{
|
||||
id: "img-01-02", src: "http://img.b2bpic.net/free-photo/modern-spacious-room-with-large-panoramic-window_7502-7289.jpg", alt: "Премиум дом для отдыха - вид 2"},
|
||||
{
|
||||
id: "img-01-03", src: "http://img.b2bpic.net/free-photo/modern-spacious-room-with-large-panoramic-window_7502-7289.jpg", alt: "Премиум дом для отдыха - вид 3"},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "02", title: "Баня премиум-класса", description: "Традиционная баня из натурального дерева с парной, прохладным бассейном и комнатой отдыха для полного расслабления", images: [
|
||||
{
|
||||
id: "img-02-01", src: "http://img.b2bpic.net/free-photo/sauna-with-stones-thermometer-warm-benches-light-nordic-wellness_169016-69368.jpg", alt: "Роскошная баня - вид 1"},
|
||||
{
|
||||
id: "img-02-02", src: "http://img.b2bpic.net/free-photo/sauna-with-stones-thermometer-warm-benches-light-nordic-wellness_169016-69368.jpg", alt: "Роскошная баня - вид 2"},
|
||||
{
|
||||
id: "img-02-03", src: "http://img.b2bpic.net/free-photo/sauna-with-stones-thermometer-warm-benches-light-nordic-wellness_169016-69368.jpg", alt: "Роскошная баня - вид 3"},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "03", title: "Бассейны", description: "Крытый и открытый бассейны с системой подогрева воды, джакузи и лежаками для семейного отдыха", images: [
|
||||
{
|
||||
id: "img-03-01", src: "http://img.b2bpic.net/free-photo/watermelon-glasses-near-pool_501050-961.jpg", alt: "Премиум бассейны - вид 1"},
|
||||
{
|
||||
id: "img-03-02", src: "http://img.b2bpic.net/free-photo/watermelon-glasses-near-pool_501050-961.jpg", alt: "Премиум бассейны - вид 2"},
|
||||
{
|
||||
id: "img-03-03", src: "http://img.b2bpic.net/free-photo/watermelon-glasses-near-pool_501050-961.jpg", alt: "Премиум бассейны - вид 3"},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "04", title: "Гастрономия", description: "Профессиональные повара готовят изысканные блюда из местных ингредиентов. Возможна организация банкетов и корпоративов", images: [
|
||||
{
|
||||
id: "img-04-01", src: "http://img.b2bpic.net/free-photo/table-set-dinning-table_1339-3458.jpg", alt: "Ресторан и столовая - вид 1"},
|
||||
{
|
||||
id: "img-04-02", src: "http://img.b2bpic.net/free-photo/table-set-dinning-table_1339-3458.jpg", alt: "Ресторан и столовая - вид 2"},
|
||||
{
|
||||
id: "img-04-03", src: "http://img.b2bpic.net/free-photo/table-set-dinning-table_1339-3458.jpg", alt: "Ресторан и столовая - вид 3"},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const handleUpdateServiceImage = (serviceId: string, imageIndex: number, newImageUrl: string) => {
|
||||
setServicesData((prevData) =>
|
||||
prevData.map((service) =>
|
||||
service.id === serviceId
|
||||
? {
|
||||
...service,
|
||||
images: service.images.map((img, idx) =>
|
||||
idx === imageIndex ? { ...img, src: newImageUrl } : img
|
||||
),
|
||||
}
|
||||
: service
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const handleUpdateServiceText = (serviceId: string, field: "title" | "description", newText: string) => {
|
||||
setServicesData((prevData) =>
|
||||
prevData.map((service) =>
|
||||
service.id === serviceId ? { ...service, [field]: newText } : service
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const handleAddServiceImage = (serviceId: string) => {
|
||||
setServicesData((prevData) =>
|
||||
prevData.map((service) =>
|
||||
service.id === serviceId
|
||||
? {
|
||||
...service,
|
||||
images: [
|
||||
...service.images,
|
||||
{
|
||||
id: `img-${service.id}-${service.images.length + 1}`,
|
||||
src: "http://img.b2bpic.net/free-photo/modern-spacious-room-with-large-panoramic-window_7502-7289.jpg", alt: `${service.title} - вид ${service.images.length + 1}`,
|
||||
},
|
||||
],
|
||||
}
|
||||
: service
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const handleRemoveServiceImage = (serviceId: string, imageIndex: number) => {
|
||||
setServicesData((prevData) =>
|
||||
prevData.map((service) =>
|
||||
service.id === serviceId
|
||||
? {
|
||||
...service,
|
||||
images: service.images.filter((_, idx) => idx !== imageIndex),
|
||||
}
|
||||
: service
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="hover-magnetic"
|
||||
@@ -80,16 +179,11 @@ export default function LandingPage() {
|
||||
|
||||
<div id="services" data-section="services">
|
||||
<FeatureCardThree
|
||||
features={[
|
||||
{
|
||||
id: "01", title: "Роскошный дом", description: "Просторный современный дом с высокотехнологичным оснащением, каминами и панорамными окнами для максимального комфорта", imageSrc: "http://img.b2bpic.net/free-photo/modern-spacious-room-with-large-panoramic-window_7502-7289.jpg", imageAlt: "Премиум дом для отдыха"},
|
||||
{
|
||||
id: "02", title: "Баня премиум-класса", description: "Традиционная баня из натурального дерева с парной, прохладным бассейном и комнатой отдыха для полного расслабления", imageSrc: "http://img.b2bpic.net/free-photo/sauna-with-stones-thermometer-warm-benches-light-nordic-wellness_169016-69368.jpg", imageAlt: "Роскошная баня"},
|
||||
{
|
||||
id: "03", title: "Бассейны", description: "Крытый и открытый бассейны с системой подогрева воды, джакузи и лежаками для семейного отдыха", imageSrc: "http://img.b2bpic.net/free-photo/watermelon-glasses-near-pool_501050-961.jpg", imageAlt: "Премиум бассейны"},
|
||||
{
|
||||
id: "04", title: "Гастрономия", description: "Профессиональные повара готовят изысканные блюда из местных ингредиентов. Возможна организация банкетов и корпоративов", imageSrc: "http://img.b2bpic.net/free-photo/table-set-dinning-table_1339-3458.jpg", imageAlt: "Ресторан и столовая"},
|
||||
]}
|
||||
features={servicesData.map((service) => ({
|
||||
id: service.id,
|
||||
title: service.title,
|
||||
description: service.description,
|
||||
imageSrc: service.images[0]?.src || "", imageAlt: service.images[0]?.alt || ""}))}
|
||||
textboxLayout="default"
|
||||
gridVariant="four-items-2x2-equal-grid"
|
||||
animationType="slide-up"
|
||||
@@ -102,6 +196,78 @@ export default function LandingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="admin-panel" data-section="admin-panel" className="py-12 px-4 bg-slate-100">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<h2 className="text-3xl font-bold mb-8 text-slate-900">Панель управления услугами</h2>
|
||||
|
||||
<div className="space-y-8">
|
||||
{servicesData.map((service) => (
|
||||
<div key={service.id} className="bg-white rounded-lg shadow-md p-6">
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm font-medium text-slate-700 mb-2">
|
||||
Название услуги
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={service.title}
|
||||
onChange={(e) => handleUpdateServiceText(service.id, "title", e.target.value)}
|
||||
className="w-full px-3 py-2 border border-slate-300 rounded-md text-slate-900"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm font-medium text-slate-700 mb-2">
|
||||
Описание услуги
|
||||
</label>
|
||||
<textarea
|
||||
value={service.description}
|
||||
onChange={(e) => handleUpdateServiceText(service.id, "description", e.target.value)}
|
||||
rows={3}
|
||||
className="w-full px-3 py-2 border border-slate-300 rounded-md text-slate-900"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4">Фотографии ({service.images.length})</h3>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 mb-4">
|
||||
{service.images.map((image, idx) => (
|
||||
<div key={image.id} className="relative">
|
||||
<img
|
||||
src={image.src}
|
||||
alt={image.alt}
|
||||
className="w-full h-32 object-cover rounded-md border border-slate-300"
|
||||
/>
|
||||
<div className="mt-2 space-y-2">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="URL изображения"
|
||||
value={image.src}
|
||||
onChange={(e) => handleUpdateServiceImage(service.id, idx, e.target.value)}
|
||||
className="w-full px-2 py-1 text-sm border border-slate-300 rounded-md text-slate-900"
|
||||
/>
|
||||
<button
|
||||
onClick={() => handleRemoveServiceImage(service.id, idx)}
|
||||
className="w-full px-3 py-1 bg-red-500 text-white text-sm rounded-md hover:bg-red-600"
|
||||
>
|
||||
Удалить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<button
|
||||
onClick={() => handleAddServiceImage(service.id)}
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
|
||||
>
|
||||
+ Добавить фото
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="testimonials" data-section="testimonials">
|
||||
<TestimonialCardFifteen
|
||||
testimonial="Прекрасное место для семейного отдыха! Персонал очень внимателен, еда вкусная, все объекты идеально содержатся. Мы вернемся снова и рекомендуем друзьям."
|
||||
|
||||
Reference in New Issue
Block a user