Initial commit
This commit is contained in:
26
src/App.js
Normal file
26
src/App.js
Normal 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
39
src/components/Footer.js
Normal 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
51
src/components/Header.js
Normal 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
38
src/components/Hero.js
Normal 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;
|
||||
114
src/components/MainContent.js
Normal file
114
src/components/MainContent.js
Normal 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;
|
||||
29
src/components/Navigation.js
Normal file
29
src/components/Navigation.js
Normal 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;
|
||||
43
src/components/NewsCard.js
Normal file
43
src/components/NewsCard.js
Normal 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
53
src/components/Sidebar.js
Normal 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
46
src/index.css
Normal 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
13
src/index.js
Normal 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>
|
||||
);
|
||||
Reference in New Issue
Block a user