Initial commit

This commit is contained in:
dk
2025-12-29 13:05:50 +02:00
commit ee163b0c18
83 changed files with 1927 additions and 0 deletions

26
src/App.js Normal file
View File

@@ -0,0 +1,26 @@
import React from 'react';
import Header from './components/Header';
import Hero from './components/Hero';
import Navigation from './components/Navigation';
import MainContent from './components/MainContent';
import Sidebar from './components/Sidebar';
import Footer from './components/Footer';
function App() {
return (
<div className="min-h-screen bg-gray-50">
<Header />
<Hero />
<Navigation />
<div className="container mx-auto px-4 py-8">
<div className="flex flex-col lg:flex-row gap-8">
<MainContent />
<Sidebar />
</div>
</div>
<Footer />
</div>
);
}
export default App;

39
src/components/Footer.js Normal file
View File

@@ -0,0 +1,39 @@
import React from 'react';
import { Facebook, Instagram } from 'lucide-react';
function Footer() {
return (
<footer className="bg-gray-800 text-white py-8">
<div className="container mx-auto px-4">
<div className="text-center">
<p className="text-sm mb-4">©2025 ТОВ "Запоріжжяелектропостачання"</p>
<div className="flex justify-center items-center gap-4 mb-4">
<div className="flex items-center gap-2">
<span className="text-sm">ЗАВАНТАЖИТИ З</span>
<div className="flex gap-2">
<div className="bg-black rounded px-3 py-1">
<span className="text-xs text-white">App Store</span>
</div>
<div className="bg-black rounded px-3 py-1">
<span className="text-xs text-white">Google Play</span>
</div>
</div>
</div>
</div>
<div className="flex justify-center gap-4">
<a href="#" className="text-gray-400 hover:text-white transition-colors">
<Facebook className="w-6 h-6" />
</a>
<a href="#" className="text-gray-400 hover:text-white transition-colors">
<Instagram className="w-6 h-6" />
</a>
</div>
</div>
</div>
</footer>
);
}
export default Footer;

51
src/components/Header.js Normal file
View File

@@ -0,0 +1,51 @@
import React from 'react';
import { Search } from 'lucide-react';
function Header() {
return (
<header className="bg-white shadow-sm">
<div className="container mx-auto px-4 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<div className="w-12 h-12 bg-gradient-to-r from-orange-400 to-yellow-400 rounded flex items-center justify-center">
<span className="text-white font-bold text-xl">З</span>
</div>
<div>
<h1 className="text-xl font-bold text-orange-500">ЗАПОРІЖЖЯЕЛЕКТРОПОСТАЧАННЯ</h1>
<p className="text-sm text-primary-600">Ваш партнер з постачання електричної енергії</p>
</div>
</div>
</div>
<div className="flex items-center gap-8">
<div className="text-right">
<p className="text-sm font-medium text-primary-600">Кол-центр:</p>
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<p className="text-primary-600">📞 061 228 22 20</p>
<p className="text-primary-600">📞 063 228 22 20</p>
</div>
<div>
<p className="text-primary-600">📞 066 228 22 20</p>
<p className="text-primary-600">📞 068 228 22 20</p>
</div>
</div>
</div>
<div className="relative">
<Search className="w-5 h-5 text-gray-400 absolute left-3 top-1/2 transform -translate-y-1/2" />
<input
type="text"
placeholder="Пошук..."
className="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"
/>
</div>
</div>
</div>
</div>
</header>
);
}
export default Header;

38
src/components/Hero.js Normal file
View File

@@ -0,0 +1,38 @@
import React from 'react';
import { motion, useReducedMotion } from 'framer-motion';
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
initial: { opacity: 0, y: 20 },
whileInView: { opacity: 1, y: 0 },
viewport: { once: true, amount: 0.2 },
transition: { delay, duration, ease: "easeOut" }
});
function Hero() {
const shouldReduce = useReducedMotion();
if (shouldReduce) {
return (
<section className="hero-bg h-64 flex items-center justify-center">
<div className="text-center text-white">
<h2 className="text-4xl font-bold mb-4">Електроенергія для вашого дому</h2>
<p className="text-xl">Надійне постачання електричної енергії</p>
</div>
</section>
);
}
return (
<motion.section
{...fadeUpPreset(0.1, 0.8)}
className="hero-bg h-64 flex items-center justify-center"
>
<div className="text-center text-white">
<h2 className="text-4xl font-bold mb-4">Електроенергія для вашого дому</h2>
<p className="text-xl">Надійне постачання електричної енергії</p>
</div>
</motion.section>
);
}
export default Hero;

View File

@@ -0,0 +1,114 @@
import React from 'react';
import { motion, useReducedMotion } from 'framer-motion';
import NewsCard from './NewsCard';
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
initial: { opacity: 0, y: 20 },
whileInView: { opacity: 1, y: 0 },
viewport: { once: true, amount: 0.2 },
transition: { delay, duration, ease: "easeOut" }
});
function MainContent() {
const shouldReduce = useReducedMotion();
const newsItems = [
{
title: "Вітаємо з Різдвом Христовим!",
date: "25.12.2023",
category: "Новини",
image: "https://zpep.com.ua/images/news/christmas.jpg",
excerpt: "Дорогі українці! Від щирого серця вітаємо вас із світлим святом Різдва Христового! Нехай у кожному домі панують любов, мир і злагода, а в серці стовпиться надія та радість. Бажаємо міцного здоров'я та радості, щоб кожен день приносив щастя та натхнення! Щирих вітань!"
},
{
title: "Вітаємо із професійним святом Днем енергетика!",
date: "22.12.2023",
category: "Новини",
image: "https://zpep.com.ua/images/news/energy-day.jpg",
excerpt: "Шановні енергетики! Вітаємо вас із професійним святом! Дякуємо енергетикам України за їх професіоналізм, відданість справі та невтомну працю. Бажаємо Вам здоров'я та безпеки!"
},
{
title: "ЧАС СПЛАТИТИ РАХУНКИ ЗА ЕЛЕКТРОЕНЕРГІЮ",
date: "08.12.2023",
category: "Послуги",
image: "https://zpep.com.ua/images/news/payment.jpg",
excerpt: "Шановні споживачі електричної енергії! ТОВ «Запоріжжяелектропостачання» інформує, що розрахунок за спожиту електроенергію здійснюється щомісячно до 20 числа місяця, наступного за місяцем споживання."
},
{
title: "Тариф на послуги постачальника універсальних послуг ТОВ «ЗАПОРІЖЖЯЕЛЕКТРОПОСТАЧАННЯ»",
date: "08.12.2023",
category: "Тариф",
image: "https://zpep.com.ua/images/news/tariff.jpg",
excerpt: "Шановні споживачі! ТОВ «Запоріжжяелектропостачання» повідомляє актуальні тарифи на постачання електричної енергії."
},
{
title: "З Днем Збройних Сил України!",
date: "06.12.2023",
category: "Новини",
image: "https://zpep.com.ua/images/news/armed-forces.jpg",
excerpt: "6 грудня Україна святкує День Збройних Сил України! Шановні захисники та захисниці України! Ви є щитом нашої держави."
}
];
if (shouldReduce) {
return (
<main className="flex-1">
<div className="space-y-8">
{newsItems.map((item, index) => (
<NewsCard key={index} {...item} />
))}
</div>
<div className="flex justify-center mt-8">
<div className="flex items-center space-x-2">
<span className="text-sm text-gray-600">Сторінка 1 з 10</span>
<div className="flex space-x-1">
<button className="pagination-btn pagination-active">1</button>
<button className="pagination-btn">2</button>
<button className="pagination-btn">3</button>
<button className="pagination-btn">4</button>
<button className="pagination-btn">5</button>
<span className="px-2">...</span>
<button className="pagination-btn">Остання »</button>
</div>
</div>
</div>
</main>
);
}
return (
<motion.main
{...fadeUpPreset(0.2, 1.0)}
className="flex-1"
>
<div className="space-y-8">
{newsItems.map((item, index) => (
<motion.div
key={index}
{...fadeUpPreset(0.1 + index * 0.1, 0.8)}
>
<NewsCard {...item} />
</motion.div>
))}
</div>
<div className="flex justify-center mt-8">
<div className="flex items-center space-x-2">
<span className="text-sm text-gray-600">Сторінка 1 з 10</span>
<div className="flex space-x-1">
<button className="pagination-btn pagination-active">1</button>
<button className="pagination-btn">2</button>
<button className="pagination-btn">3</button>
<button className="pagination-btn">4</button>
<button className="pagination-btn">5</button>
<span className="px-2">...</span>
<button className="pagination-btn">Остання »</button>
</div>
</div>
</div>
</motion.main>
);
}
export default MainContent;

View File

@@ -0,0 +1,29 @@
import React from 'react';
function Navigation() {
const navItems = [
'ЕЛЕКТРОЕНЕРГІЯ',
'ПРИРОДНИЙ ГАЗ',
'НОРМАТИВНО-ПРАВОВІ АКТИ',
'ДОКУМЕНТИ ТА ІНФОРМАЦІЯ',
'ПОШИРЕНІ ЗАПИТАННЯ',
'КОНТАКТИ'
];
return (
<nav className="bg-white border-t border-b border-gray-200">
<div className="container mx-auto px-4">
<div className="flex flex-wrap items-center py-3">
<div className="nav-link text-sm font-medium mr-8">МАПА САЙТУ</div>
{navItems.map((item, index) => (
<div key={index} className="nav-link text-sm mr-6 py-2">
{item}
</div>
))}
</div>
</div>
</nav>
);
}
export default Navigation;

View File

@@ -0,0 +1,43 @@
import React from 'react';
import { Calendar, User } from 'lucide-react';
function NewsCard({ title, date, category, image, excerpt }) {
return (
<article className="news-card">
<div className="p-6">
<div className="flex items-start gap-4">
<div className="flex-shrink-0">
<img
src={image}
alt={title}
className="w-32 h-24 object-cover rounded"
/>
</div>
<div className="flex-1">
<h3 className="text-xl font-bold text-gray-900 mb-2 hover:text-primary-600 cursor-pointer">
{title}
</h3>
<div className="flex items-center gap-4 text-sm text-gray-500 mb-3">
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
<span>{date}</span>
</div>
<div className="flex items-center gap-1">
<User className="w-4 h-4" />
<span>{category}</span>
</div>
</div>
<p className="text-gray-700 leading-relaxed mb-4">
{excerpt}
</p>
<button className="btn-primary text-sm">
ЧИТАТИ ДАЛІ
</button>
</div>
</div>
</div>
</article>
);
}
export default NewsCard;

53
src/components/Sidebar.js Normal file
View File

@@ -0,0 +1,53 @@
import React from 'react';
import { User, Package, TrendingUp, Zap, FileText, Phone, MessageCircle } from 'lucide-react';
function Sidebar() {
const sidebarItems = [
{ icon: User, text: "ОСОБИСТИЙ КАБІНЕТ", color: "bg-orange-500" },
{ icon: Package, text: "ПЕРЕДАТИ ПОКАЗИ", color: "bg-yellow-500" },
{ icon: TrendingUp, text: "ТАРИФИ АКТУАЛЬНІ", color: "bg-yellow-600" },
{ icon: Zap, text: "СПЛАТИТИ ОНЛАЙН", color: "bg-orange-600" },
{ icon: FileText, text: "ЕЛЕКТРОННІ НА РАХУНОК", color: "bg-gray-600" },
{ icon: Phone, text: "РОЗРАХУВАТИ РОЗСТРОЧКУ", color: "bg-yellow-500" }
];
return (
<aside className="w-full lg:w-80">
<div className="space-y-2">
{sidebarItems.map((item, index) => {
const Icon = item.icon;
return (
<button key={index} className={`sidebar-btn w-full justify-start ${item.color}`}>
<Icon className="w-5 h-5" />
<span>{item.text}</span>
</button>
);
})}
</div>
<div className="mt-8 bg-white rounded-lg p-6 shadow-md">
<div className="text-center">
<div className="w-20 h-20 bg-yellow-400 rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-2xl font-bold text-white">ISO</span>
</div>
<p className="text-sm text-gray-600">Сертифікат якості</p>
<p className="text-lg font-bold text-gray-900">ISO 9001</p>
</div>
</div>
<div className="mt-6 bg-white rounded-lg p-6 shadow-md">
<h3 className="font-bold text-gray-900 mb-4">Корисні посилання</h3>
<div className="space-y-2">
<a href="#" className="block text-primary-600 hover:text-primary-800 text-sm">
Відділення нових Особових рахунків
</a>
<a href="#" className="block text-primary-600 hover:text-primary-800 text-sm">
Інструкція до особистого кабінету
</a>
</div>
</div>
</aside>
);
}
export default Sidebar;

46
src/index.css Normal file
View File

@@ -0,0 +1,46 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
body {
@apply font-sans;
}
}
@layer components {
.hero-bg {
background: linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)), url('https://zpep.com.ua/images/bg.jpg');
background-size: cover;
background-position: center;
background-attachment: fixed;
}
.nav-link {
@apply text-gray-800 hover:text-primary-600 transition-colors duration-200 font-medium;
}
.btn-primary {
@apply bg-primary-600 text-white px-6 py-2 rounded hover:bg-primary-700 transition-colors duration-200;
}
.btn-orange {
@apply bg-orange-500 text-white px-4 py-2 rounded hover:bg-orange-600 transition-colors duration-200;
}
.sidebar-btn {
@apply bg-orange-500 text-white px-3 py-2 rounded-r text-sm font-medium hover:bg-orange-600 transition-colors duration-200 flex items-center gap-2;
}
.news-card {
@apply bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-200;
}
.pagination-btn {
@apply px-3 py-1 mx-1 rounded hover:bg-primary-100 transition-colors duration-200;
}
.pagination-active {
@apply bg-primary-600 text-white;
}
}

13
src/index.js Normal file
View File

@@ -0,0 +1,13 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);