This commit is contained in:
2025-12-26 14:03:18 +01:00
parent 846379eccc
commit 235e1d9b52
18 changed files with 3334 additions and 2290 deletions

View File

@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { X, Info, CheckCircle, AlertTriangle, MessageSquare, Calendar, ChevronDown, ChevronUp } from 'lucide-react'; import React, { useState, useEffect } from 'react';
import { X, Info, CheckCircle, AlertTriangle, MessageSquare, Calendar, ChevronDown, ChevronUp, Wallet, ArrowLeft, RefreshCw, CreditCard } from 'lucide-react';
import { Button } from './Button'; import { Button } from './Button';
interface FeedbackModalProps { interface FeedbackModalProps {
@@ -7,11 +8,13 @@ interface FeedbackModalProps {
onClose: () => void; onClose: () => void;
onSubmit: (feedbackData: any) => Promise<void>; onSubmit: (feedbackData: any) => Promise<void>;
loading: boolean; loading: boolean;
order?: any;
} }
export const FeedbackModal: React.FC<FeedbackModalProps> = ({ isOpen, onClose, onSubmit, loading }) => { export const FeedbackModal: React.FC<FeedbackModalProps> = ({ isOpen, onClose, onSubmit, loading, order }) => {
// --- STATE --- // --- STATE ---
const [mainDecision, setMainDecision] = useState<'approved' | 'minor' | 'major' | null>(null); const [mainDecision, setMainDecision] = useState<'approved' | 'minor' | 'major' | null>(null);
const [showPayment, setShowPayment] = useState(false);
// Approval Flow // Approval Flow
const [approvalConfirmed, setApprovalConfirmed] = useState(false); const [approvalConfirmed, setApprovalConfirmed] = useState(false);
@@ -38,8 +41,28 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({ isOpen, onClose, o
const [revisionConfirmed, setRevisionConfirmed] = useState(false); const [revisionConfirmed, setRevisionConfirmed] = useState(false);
useEffect(() => {
if (isOpen) {
setMainDecision(null);
setShowPayment(false);
setApprovalConfirmed(false);
setRevisionConfirmed(false);
// Reset other fields if needed
}
}, [isOpen]);
if (!isOpen) return null; if (!isOpen) return null;
// --- LOGIC ---
const paymentDetails = order?.details?.payment_summary;
const totalAmount = paymentDetails?.total || 0;
const advanceAmount = paymentDetails?.advance || 0;
const remainingAmount = paymentDetails?.remaining || 0;
const isCustomPrice = paymentDetails?.is_custom;
// We show payment step ONLY if Approved AND there is a remaining amount AND it's not custom price (unless handled)
const shouldShowPaymentStep = mainDecision === 'approved' && remainingAmount > 0 && !isCustomPrice;
// --- HANDLERS --- // --- HANDLERS ---
const handleCheckbox = ( const handleCheckbox = (
currentList: string[], currentList: string[],
@@ -71,7 +94,8 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({ isOpen, onClose, o
decision: mainDecision, decision: mainDecision,
submittedAt: new Date().toISOString(), submittedAt: new Date().toISOString(),
approval: mainDecision === 'approved' ? { approval: mainDecision === 'approved' ? {
confirmed: approvalConfirmed confirmed: approvalConfirmed,
paymentComplete: showPayment // Flag that payment step was shown
} : null, } : null,
revision: isRevision ? { revision: isRevision ? {
design: { selected: designCheckboxes, comment: designText }, design: { selected: designCheckboxes, comment: designText },
@@ -88,7 +112,12 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({ isOpen, onClose, o
onSubmit(feedbackData); onSubmit(feedbackData);
}; };
const handleProceedToPayment = () => {
setShowPayment(true);
};
const commonInputStyles = "w-full p-4 border border-gray-300 rounded-xl text-sm font-medium text-black placeholder-gray-400 focus:ring-4 focus:ring-primary/10 focus:border-primary outline-none bg-white transition-all shadow-sm"; const commonInputStyles = "w-full p-4 border border-gray-300 rounded-xl text-sm font-medium text-black placeholder-gray-400 focus:ring-4 focus:ring-primary/10 focus:border-primary outline-none bg-white transition-all shadow-sm";
const formatPrice = (num: number) => num.toLocaleString('hu-HU') + ' Ft';
const renderFeedbackCategory = ( const renderFeedbackCategory = (
title: string, title: string,
@@ -133,157 +162,233 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({ isOpen, onClose, o
return ( return (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-gray-900/75 backdrop-blur-sm overflow-y-auto"> <div className="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-gray-900/75 backdrop-blur-sm overflow-y-auto">
<div className="bg-white rounded-3xl shadow-2xl w-full max-w-3xl flex flex-col my-8 relative animate-fade-in-up border border-white/20"> <div className="bg-white rounded-3xl shadow-2xl w-full max-w-3xl flex flex-col my-8 relative animate-fade-in-up border border-white/20 min-h-[600px]">
<button onClick={onClose} className="absolute top-6 right-6 p-2 hover:bg-gray-100 rounded-full transition-colors z-10 bg-white shadow-sm border border-gray-100"> <button onClick={onClose} className="absolute top-6 right-6 p-2 hover:bg-gray-100 rounded-full transition-colors z-10 bg-white shadow-sm border border-gray-100">
<X className="w-5 h-5 text-gray-500" /> <X className="w-5 h-5 text-gray-500" />
</button> </button>
<div className="p-8 border-b border-gray-100 bg-gradient-to-r from-blue-50/50 to-purple-50/50 rounded-t-3xl"> {showPayment ? (
<div className="flex items-start gap-4"> /* PAYMENT SUMMARY VIEW */
<div className="bg-white p-3 rounded-2xl shadow-md text-primary border border-gray-100"> <div className="flex flex-col h-full animate-fade-in">
<MessageSquare className="w-6 h-6" /> <div className="p-8 border-b border-gray-100 bg-gradient-to-r from-blue-50/50 to-purple-50/50 rounded-t-3xl">
</div> <div className="flex items-center gap-4">
<div> <button onClick={() => setShowPayment(false)} className="p-2 bg-white rounded-xl shadow-sm border border-gray-100 hover:bg-gray-50 transition-colors text-gray-600">
<h2 className="text-2xl font-black text-gray-900 tracking-tighter">Visszajelzés a Weboldalról</h2> <ArrowLeft className="w-5 h-5" />
<p className="text-sm text-gray-500 font-medium mt-1">A bemutató verzió alapján kérjük jelezd, ha valamit módosítanál.</p> </button>
</div> <div>
<h2 className="text-2xl font-black text-gray-900 tracking-tighter">Véglegesítés & Fizetés</h2>
<p className="text-sm text-gray-500 font-medium mt-1">A fennmaradó összeg rendezése a projekt lezárásához.</p>
</div>
</div>
</div>
<div className="p-8 md:p-12 flex-grow space-y-10">
<div className="text-center">
<div className="w-20 h-20 bg-green-50 rounded-3xl flex items-center justify-center mx-auto mb-6 text-green-600 shadow-sm border border-green-100">
<Wallet className="w-10 h-10" />
</div>
<h3 className="text-xl font-bold text-gray-900 mb-2">Projekt Elszámolás</h3>
<p className="text-gray-500 text-sm max-w-md mx-auto">A demó oldal jóváhagyásával a projekt a befejező szakaszba lép. Kérjük, egyenlítse ki a fennmaradó összeget.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="bg-gray-50 p-6 rounded-[24px] border border-gray-100 flex flex-col items-center text-center">
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest mb-2">Projekt Teljes Ára</p>
<p className="text-lg font-bold text-gray-900">{formatPrice(totalAmount)}</p>
</div>
<div className="bg-green-50/50 p-6 rounded-[24px] border border-green-100 flex flex-col items-center text-center">
<p className="text-[10px] font-black text-green-600 uppercase tracking-widest mb-2">Már Befizetve (Előleg)</p>
<p className="text-lg font-bold text-green-700">{formatPrice(advanceAmount)}</p>
</div>
</div>
<div className="bg-primary/5 p-10 rounded-[32px] border-2 border-primary/20 text-center shadow-xl shadow-primary/5 relative overflow-hidden">
<div className="absolute -top-10 -right-10 w-40 h-40 bg-primary/10 rounded-full blur-3xl"></div>
<p className="text-[11px] font-black text-primary uppercase tracking-[0.3em] mb-4">Most Fizetendő (Fennmaradó)</p>
<div className="text-4xl md:text-5xl font-black text-primary mb-6 tracking-tighter">
{formatPrice(remainingAmount)}
</div>
<div className="flex justify-center">
<Button
onClick={handleSubmit}
disabled={loading}
className="font-black uppercase text-[10px] tracking-widest px-12 py-4 h-auto shadow-2xl shadow-primary/40"
>
{loading ? <RefreshCw className="w-4 h-4 animate-spin mr-2" /> : <CreditCard className="w-4 h-4 mr-2" />}
FIZETÉS & JÓVÁHAGYOM
</Button>
</div>
</div>
<div className="bg-amber-50 border border-amber-200 p-6 rounded-2xl flex gap-4">
<div className="shrink-0"><Info className="w-5 h-5 text-amber-500" /></div>
<p className="text-xs text-amber-800 font-medium leading-relaxed">
<strong>Fontos:</strong> A befizetés után a rendszer automatikusan kiállítja a végszámlát és elküldi e-mailben. A fejlesztő csapat értesítést kap a jóváhagyásról és megkezdi a végleges élesítést.
</p>
</div>
</div>
</div> </div>
</div> ) : (
/* STANDARD FEEDBACK FORM */
<div className="p-8 md:p-10 space-y-10"> <>
<div> <div className="p-8 border-b border-gray-100 bg-gradient-to-r from-blue-50/50 to-purple-50/50 rounded-t-3xl">
<h3 className="text-lg font-bold text-gray-900 mb-5 flex items-center gap-2"> <div className="flex items-start gap-4">
Döntés a továbblépésről <span className="text-red-500">*</span> <div className="bg-white p-3 rounded-2xl shadow-md text-primary border border-gray-100">
</h3> <MessageSquare className="w-6 h-6" />
<div className="grid grid-cols-1 gap-4"> </div>
{[ <div>
{ id: 'approved', label: 'Igen, jóváhagyom a terveket', color: 'green', icon: '✅' }, <h2 className="text-2xl font-black text-gray-900 tracking-tighter">Visszajelzés a Weboldalról</h2>
{ id: 'minor', label: 'Alapvetően jó, de kisebb javításokat kérek', color: 'yellow', icon: '🔧' }, <p className="text-sm text-gray-500 font-medium mt-1">A bemutató verzió alapján kérjük jelezd, ha valamit módosítanál.</p>
{ id: 'major', label: 'Nem megfelelő, jelentős módosításra van szükség', color: 'red', icon: '❌' } </div>
].map(opt => ( </div>
<label key={opt.id} className={`flex items-center p-5 border-2 rounded-2xl cursor-pointer transition-all ${mainDecision === opt.id ? `border-${opt.color}-500 bg-${opt.color}-50 shadow-lg ring-1 ring-${opt.color}-500` : 'border-gray-100 hover:border-gray-200'}`}>
<input
type="radio"
name="decision"
checked={mainDecision === opt.id}
onChange={() => setMainDecision(opt.id as any)}
className={`w-6 h-6 text-${opt.color}-600 focus:ring-${opt.color}-500 border-gray-300`}
/>
<span className="ml-4 font-bold text-gray-900">{opt.icon} {opt.label}</span>
</label>
))}
</div> </div>
</div>
{mainDecision === 'approved' && ( <div className="p-8 md:p-10 space-y-10 flex-grow overflow-y-auto">
<div className="animate-fade-in bg-green-50 p-6 rounded-2xl border-2 border-green-200 shadow-inner"> <div>
<h3 className="text-green-900 font-black mb-4 flex items-center gap-2 uppercase text-sm tracking-widest"> <h3 className="text-lg font-bold text-gray-900 mb-5 flex items-center gap-2">
<CheckCircle className="w-5 h-5" /> Megerősítés Döntés a továbblépésről <span className="text-red-500">*</span>
</h3> </h3>
<label className="flex items-start cursor-pointer group"> <div className="grid grid-cols-1 gap-4">
<input {[
type="checkbox" { id: 'approved', label: 'Igen, jóváhagyom a terveket', color: 'green', icon: '✅' },
checked={approvalConfirmed} { id: 'minor', label: 'Alapvetően jó, de kisebb javításokat kérek', color: 'yellow', icon: '🔧' },
onChange={(e) => setApprovalConfirmed(e.target.checked)} { id: 'major', label: 'Nem megfelelő, jelentős módosításra van szükség', color: 'red', icon: '❌' }
className="mt-1 w-6 h-6 text-green-600 rounded-lg focus:ring-green-500 border-green-300" ].map(opt => (
/> <label key={opt.id} className={`flex items-center p-5 border-2 rounded-2xl cursor-pointer transition-all ${mainDecision === opt.id ? `border-${opt.color}-500 bg-${opt.color}-50 shadow-lg ring-1 ring-${opt.color}-500` : 'border-gray-100 hover:border-gray-200'}`}>
<span className="ml-4 text-sm text-green-800 font-bold leading-relaxed"> <input
Tudomásul veszem, hogy a jóváhagyás után a végleges fejlesztés megkezdődik a tervek alapján. type="radio"
</span> name="decision"
</label> checked={mainDecision === opt.id}
onChange={() => setMainDecision(opt.id as any)}
className={`w-6 h-6 text-${opt.color}-600 focus:ring-${opt.color}-500 border-gray-300`}
/>
<span className="ml-4 font-bold text-gray-900">{opt.icon} {opt.label}</span>
</label>
))}
</div>
</div>
{mainDecision === 'approved' && (
<div className="animate-fade-in bg-green-50 p-6 rounded-2xl border-2 border-green-200 shadow-inner">
<h3 className="text-green-900 font-black mb-4 flex items-center gap-2 uppercase text-sm tracking-widest">
<CheckCircle className="w-5 h-5" /> Megerősítés
</h3>
<label className="flex items-start cursor-pointer group">
<input
type="checkbox"
checked={approvalConfirmed}
onChange={(e) => setApprovalConfirmed(e.target.checked)}
className="mt-1 w-6 h-6 text-green-600 rounded-lg focus:ring-green-500 border-green-300"
/>
<span className="ml-4 text-sm text-green-800 font-bold leading-relaxed">
Tudomásul veszem, hogy a jóváhagyással elfogadom a jelenlegi állapotot, és a folyamat a végleges elszámolással folytatódik.
</span>
</label>
</div>
)}
{isRevision && (
<div className="animate-fade-in space-y-8 border-t border-gray-100 pt-10">
{renderFeedbackCategory(
"Dizájn módosítások",
["Színek", "Betűtípusok", "Elrendezés", "Képek / Illusztrációk", "Nem szeretnék dizájn módosítást"],
designCheckboxes, setDesignCheckboxes,
designText, setDesignText,
"Írd le pontosan, mit változtatnál a megjelenésen..."
)}
{renderFeedbackCategory(
"Tartalmi változtatások",
["Szövegek stílusa", "Adatok pontosítása", "Hiányzó tartalom", "Nem szeretnék tartalmi módosítást"],
contentCheckboxes, setContentCheckboxes,
contentText, setContentText,
"Írd le a szöveges módosításokat..."
)}
<div>
<h3 className="text-sm font-black text-gray-900 mb-3 uppercase tracking-widest">Mi a legfontosabb kérésed? <span className="text-red-500">*</span></h3>
<textarea
value={priorityText}
onChange={(e) => setPriorityText(e.target.value)}
className={commonInputStyles}
rows={2}
placeholder="A legkritikusabb pont, amin változtatni kell..."
></textarea>
</div>
<div>
<h3 className="text-sm font-black text-gray-900 mb-3 uppercase tracking-widest">Egyéb észrevételek</h3>
<textarea
value={extraNotes}
onChange={(e) => setExtraNotes(e.target.value)}
className={commonInputStyles}
rows={4}
placeholder="Bármi egyéb megjegyzés..."
></textarea>
</div>
<div className="bg-yellow-50 p-6 rounded-2xl border-2 border-yellow-200 shadow-inner">
<label className="flex items-start cursor-pointer">
<input
type="checkbox"
checked={revisionConfirmed}
onChange={(e) => setRevisionConfirmed(e.target.checked)}
className="mt-1 w-6 h-6 text-yellow-600 rounded-lg focus:ring-yellow-500 border-yellow-300"
/>
<span className="ml-4 text-sm text-yellow-900 font-bold leading-relaxed">
Tudomásul veszem, hogy a kért módosítások feldolgozása után kollégáik keresni fognak az újabb verzióval.
</span>
</label>
</div>
</div>
)}
</div> </div>
)}
{isRevision && ( <div className="p-8 border-t border-gray-100 bg-gray-50/50 rounded-b-3xl flex flex-col sm:flex-row justify-end gap-4">
<div className="animate-fade-in space-y-8 border-t border-gray-100 pt-10"> <Button variant="white" onClick={onClose} disabled={loading} className="px-10 border-gray-200">Mégse</Button>
{renderFeedbackCategory( {mainDecision === 'approved' && (
"Dizájn módosítások", shouldShowPaymentStep ? (
["Színek", "Betűtípusok", "Elrendezés", "Képek / Illusztrációk", "Nem szeretnék dizájn módosítást"], <Button
designCheckboxes, setDesignCheckboxes, onClick={handleProceedToPayment}
designText, setDesignText, disabled={loading || !approvalConfirmed}
"Írd le pontosan, mit változtatnál a megjelenésen..." className="bg-primary hover:bg-primary-dark text-white font-black uppercase tracking-widest px-10 shadow-lg shadow-primary/20"
>
Tovább a fizetéshez
</Button>
) : (
<Button
onClick={handleSubmit}
disabled={loading || !approvalConfirmed}
className="bg-green-600 hover:bg-green-700 text-white font-black uppercase tracking-widest px-10 shadow-lg shadow-green-200"
>
{loading ? 'Küldés...' : 'Végleges Jóváhagyás'}
</Button>
)
)} )}
{renderFeedbackCategory( {isRevision && (
"Tartalmi változtatások", <Button
["Szövegek stílusa", "Adatok pontosítása", "Hiányzó tartalom", "Nem szeretnék tartalmi módosítást"], onClick={handleSubmit}
contentCheckboxes, setContentCheckboxes, disabled={loading || !revisionConfirmed || !priorityText.trim()}
contentText, setContentText, className="font-black uppercase tracking-widest px-10 shadow-lg shadow-primary/20"
"Írd le a szöveges módosításokat..." >
{loading ? 'Küldés...' : 'Visszajelzés Elküldése'}
</Button>
)} )}
<div> {!mainDecision && (
<h3 className="text-sm font-black text-gray-900 mb-3 uppercase tracking-widest">Mi a legfontosabb kérésed? <span className="text-red-500">*</span></h3> <Button disabled className="opacity-50 cursor-not-allowed font-black uppercase tracking-widest px-10">
<textarea Válasszon opciót
value={priorityText} </Button>
onChange={(e) => setPriorityText(e.target.value)} )}
className={commonInputStyles}
rows={2}
placeholder="A legkritikusabb pont, amin változtatni kell..."
></textarea>
</div>
<div>
<h3 className="text-sm font-black text-gray-900 mb-3 uppercase tracking-widest">Egyéb észrevételek</h3>
<textarea
value={extraNotes}
onChange={(e) => setExtraNotes(e.target.value)}
className={commonInputStyles}
rows={4}
placeholder="Bármi egyéb megjegyzés..."
></textarea>
</div>
<div className="bg-yellow-50 p-6 rounded-2xl border-2 border-yellow-200 shadow-inner">
<label className="flex items-start cursor-pointer">
<input
type="checkbox"
checked={revisionConfirmed}
onChange={(e) => setRevisionConfirmed(e.target.checked)}
className="mt-1 w-6 h-6 text-yellow-600 rounded-lg focus:ring-yellow-500 border-yellow-300"
/>
<span className="ml-4 text-sm text-yellow-900 font-bold leading-relaxed">
Tudomásul veszem, hogy a kért módosítások feldolgozása után kollégáik keresni fognak az újabb verzióval.
</span>
</label>
</div>
</div> </div>
)} </>
</div> )}
<div className="p-8 border-t border-gray-100 bg-gray-50/50 rounded-b-3xl flex flex-col sm:flex-row justify-end gap-4">
<Button variant="white" onClick={onClose} disabled={loading} className="px-10 border-gray-200">Mégse</Button>
{mainDecision === 'approved' && (
<Button
onClick={handleSubmit}
disabled={loading || !approvalConfirmed}
className="bg-green-600 hover:bg-green-700 text-white font-black uppercase tracking-widest px-10 shadow-lg shadow-green-200"
>
{loading ? 'Küldés...' : 'Végleges Jóváhagyás'}
</Button>
)}
{isRevision && (
<Button
onClick={handleSubmit}
disabled={loading || !revisionConfirmed || !priorityText.trim()}
className="font-black uppercase tracking-widest px-10 shadow-lg shadow-primary/20"
>
{loading ? 'Küldés...' : 'Visszajelzés Elküldése'}
</Button>
)}
{!mainDecision && (
<Button disabled className="opacity-50 cursor-not-allowed font-black uppercase tracking-widest px-10">
Válasszon opciót
</Button>
)}
</div>
</div> </div>
</div> </div>
); );
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -23,48 +23,39 @@ export const ProfileCompleter: React.FC = () => {
const checkProfile = async () => { const checkProfile = async () => {
setChecking(true); setChecking(true);
// --- DEMO MODE --- const checkMetadataFallback = () => {
if (!isSupabaseConfigured) {
const meta = user.user_metadata || {}; const meta = user.user_metadata || {};
if (!meta.first_name || !meta.last_name || !meta.date_of_birth) { const hasRequiredData = meta.first_name && meta.last_name && meta.date_of_birth;
if (!hasRequiredData) {
setIsOpen(true); setIsOpen(true);
if (meta.first_name) setFirstName(meta.first_name); if (meta.first_name) setFirstName(meta.first_name);
if (meta.last_name) setLastName(meta.last_name); if (meta.last_name) setLastName(meta.last_name);
if (meta.date_of_birth) setDateOfBirth(meta.date_of_birth); if (meta.date_of_birth) setDateOfBirth(meta.date_of_birth);
} }
};
if (!isSupabaseConfigured) {
checkMetadataFallback();
setChecking(false); setChecking(false);
return; return;
} }
// -----------------
try { try {
const { data, error } = await supabase const { data, error: fetchError } = await supabase
.from('profiles') .from('profiles')
.select('first_name, last_name, date_of_birth') .select('first_name, last_name, date_of_birth')
.eq('id', user.id) .eq('id', user.id)
.maybeSingle(); .maybeSingle();
if (error) { if (fetchError) {
console.error('Error checking profile:', error.message || error); // Ha hálózati hiba van (pl. adblocker vagy CORS), a metadata-ra hagyatkozunk csendben
// If DB check fails, fallback to metadata to see if we should block the user. checkMetadataFallback();
// This prevents locking the user out if the DB is temporarily unavailable or misconfigured,
// provided they have the data in their auth metadata.
const meta = user.user_metadata || {};
const hasMetadata = meta.first_name && meta.last_name && meta.date_of_birth;
if (!hasMetadata) {
setIsOpen(true);
if (meta.first_name) setFirstName(meta.first_name);
if (meta.last_name) setLastName(meta.last_name);
if (meta.date_of_birth) setDateOfBirth(meta.date_of_birth);
}
return; return;
} }
// If no profile exists, or names/dob are missing
if (!data || !data.first_name || !data.last_name || !data.date_of_birth) { if (!data || !data.first_name || !data.last_name || !data.date_of_birth) {
setIsOpen(true); setIsOpen(true);
// Pre-fill if partial data exists
if (data?.first_name) setFirstName(data.first_name); if (data?.first_name) setFirstName(data.first_name);
else if (user.user_metadata?.first_name) setFirstName(user.user_metadata.first_name); else if (user.user_metadata?.first_name) setFirstName(user.user_metadata.first_name);
@@ -75,7 +66,13 @@ export const ProfileCompleter: React.FC = () => {
else if (user.user_metadata?.date_of_birth) setDateOfBirth(user.user_metadata.date_of_birth); else if (user.user_metadata?.date_of_birth) setDateOfBirth(user.user_metadata.date_of_birth);
} }
} catch (err: any) { } catch (err: any) {
console.error('Unexpected error in ProfileCompleter:', err); // Hálózat-specifikus hibák esetén nem logolunk noisyt
if (err instanceof TypeError && err.message.includes('fetch')) {
checkMetadataFallback();
} else {
console.debug('Supabase connection issue, using metadata fallback.');
checkMetadataFallback();
}
} finally { } finally {
setChecking(false); setChecking(false);
} }
@@ -96,11 +93,8 @@ export const ProfileCompleter: React.FC = () => {
} }
try { try {
// --- DEMO MODE UPDATE ---
if (!isSupabaseConfigured && user) { if (!isSupabaseConfigured && user) {
await new Promise(resolve => setTimeout(resolve, 800)); // Fake delay await new Promise(resolve => setTimeout(resolve, 800));
// Update local storage session
const storedSession = localStorage.getItem('demo_user_session'); const storedSession = localStorage.getItem('demo_user_session');
if (storedSession) { if (storedSession) {
const parsed = JSON.parse(storedSession); const parsed = JSON.parse(storedSession);
@@ -111,15 +105,13 @@ export const ProfileCompleter: React.FC = () => {
date_of_birth: dateOfBirth date_of_birth: dateOfBirth
}; };
localStorage.setItem('demo_user_session', JSON.stringify(parsed)); localStorage.setItem('demo_user_session', JSON.stringify(parsed));
refreshDemoUser(); // Refresh context refreshDemoUser();
} }
setIsOpen(false); setIsOpen(false);
return; return;
} }
// ------------------------
if (user) { if (user) {
// 1. Update Profile Table
const { error: dbError } = await supabase const { error: dbError } = await supabase
.from('profiles') .from('profiles')
.upsert({ .upsert({
@@ -133,7 +125,6 @@ export const ProfileCompleter: React.FC = () => {
if (dbError) throw dbError; if (dbError) throw dbError;
// 2. Update Auth Metadata (optional, but good for consistency)
await supabase.auth.updateUser({ await supabase.auth.updateUser({
data: { data: {
first_name: firstName, first_name: firstName,
@@ -143,8 +134,6 @@ export const ProfileCompleter: React.FC = () => {
}); });
setIsOpen(false); setIsOpen(false);
// We do not reload here to avoid infinite loops if checks fail on reload.
// The state close is enough.
} }
} catch (err: any) { } catch (err: any) {
console.error('Error updating profile:', err); console.error('Error updating profile:', err);
@@ -164,9 +153,7 @@ export const ProfileCompleter: React.FC = () => {
<User className="w-8 h-8 text-white" /> <User className="w-8 h-8 text-white" />
</div> </div>
<h2 className="text-2xl font-bold">Hiányzó Adatok</h2> <h2 className="text-2xl font-bold">Hiányzó Adatok</h2>
<p className="text-blue-100 text-sm mt-2"> <p className="text-blue-100 text-sm mt-2">Kérjük, a folytatáshoz adja meg a hiányzó adatait.</p>
Kérjük, a folytatáshoz adja meg a hiányzó adatait.
</p>
</div> </div>
<div className="p-8"> <div className="p-8">
@@ -177,71 +164,33 @@ export const ProfileCompleter: React.FC = () => {
<span>{error}</span> <span>{error}</span>
</div> </div>
)} )}
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label htmlFor="comp_lastname" className="block text-sm font-medium text-gray-700 mb-1"> <label htmlFor="comp_lastname" className="block text-sm font-medium text-gray-700 mb-1">Vezetéknév</label>
Vezetéknév <input id="comp_lastname" type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition-all bg-white text-gray-900" placeholder="Kovács" required />
</label>
<input
id="comp_lastname"
type="text"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition-all bg-white text-gray-900"
placeholder="Kovács"
required
/>
</div> </div>
<div> <div>
<label htmlFor="comp_firstname" className="block text-sm font-medium text-gray-700 mb-1"> <label htmlFor="comp_firstname" className="block text-sm font-medium text-gray-700 mb-1">Keresztnév</label>
Keresztnév <input id="comp_firstname" type="text" value={firstName} onChange={(e) => setFirstName(e.target.value)} className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition-all bg-white text-gray-900" placeholder="János" required />
</label>
<input
id="comp_firstname"
type="text"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition-all bg-white text-gray-900"
placeholder="János"
required
/>
</div> </div>
<div> <div>
<label htmlFor="comp_dob" className="block text-sm font-medium text-gray-700 mb-1"> <label htmlFor="comp_dob" className="block text-sm font-medium text-gray-700 mb-1">Születési dátum</label>
Születési dátum
</label>
<div className="relative"> <div className="relative">
<input <input id="comp_dob" type="date" value={dateOfBirth} onChange={(e) => setDateOfBirth(e.target.value)} className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition-all bg-white text-gray-900" required />
id="comp_dob"
type="date"
value={dateOfBirth}
onChange={(e) => setDateOfBirth(e.target.value)}
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent outline-none transition-all bg-white text-gray-900"
required
/>
<div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none"> <div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
<Calendar className="h-5 w-5 text-gray-400" /> <Calendar className="h-5 w-5 text-gray-400" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="pt-2"> <div className="pt-2">
<Button type="submit" fullWidth disabled={loading} className="flex justify-center items-center"> <Button type="submit" fullWidth disabled={loading} className="flex justify-center items-center">
{loading ? 'Mentés...' : ( {loading ? 'Mentés...' : (
<> <>Adatok Mentése <Save className="ml-2 w-4 h-4" /></>
Adatok Mentése <Save className="ml-2 w-4 h-4" />
</>
)} )}
</Button> </Button>
</div> </div>
<p className="text-xs text-center text-gray-500">Ezekre az adatokra a számlázáshoz és a kapcsolattartáshoz van szükségünk.</p>
<p className="text-xs text-center text-gray-500">
Ezekre az adatokra a számlázáshoz és a kapcsolattartáshoz van szükségünk.
</p>
</form> </form>
</div> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@
<html lang="hu"> <html lang="hu">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="https://picsum.photos/id/48/32/32" /> <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cdefs%3E%3ClinearGradient id='grad' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' style='stop-color:%237c3aed;stop-opacity:1' /%3E%3Cstop offset='100%25' style='stop-color:%233b82f6;stop-opacity:1' /%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='32' height='32' rx='8' fill='url(%23grad)'/%3E%3Cpath d='M22 20l4-4-4-4M10 12l-4 4 4 4M18.5 8l-5 16' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Motion Web Stúdió - Professzionális Webfejlesztés</title> <title>Motion Web Stúdió - Professzionális Webfejlesztés</title>

View File

@@ -4,7 +4,9 @@ export const defaultPlans: ProductPackage[] = [
{ {
id: 'start', id: 'start',
name: "Landing Page", name: "Landing Page",
price: "190.000 Ft-tól", price: "190.000 Ft",
total_price: 190000,
advance_price: 40000,
desc: "Ideális induló vállalkozásoknak és személyes brandeknek.", desc: "Ideális induló vállalkozásoknak és személyes brandeknek.",
features: [ features: [
"Egyoldalas Landing Page", "Egyoldalas Landing Page",
@@ -20,7 +22,9 @@ export const defaultPlans: ProductPackage[] = [
{ {
id: 'pro', id: 'pro',
name: "Pro Web", name: "Pro Web",
price: "350.000 Ft-tól", price: "350.000 Ft",
total_price: 350000,
advance_price: 80000,
desc: "A legnépszerűbb választás kis- és középvállalkozások számára.", desc: "A legnépszerűbb választás kis- és középvállalkozások számára.",
features: [ features: [
"Max 5 aloldal (Rólunk, Szolgáltatások...)", "Max 5 aloldal (Rólunk, Szolgáltatások...)",
@@ -38,6 +42,9 @@ export const defaultPlans: ProductPackage[] = [
id: 'enterprise', id: 'enterprise',
name: "Enterprise", name: "Enterprise",
price: "Egyedi árazás", price: "Egyedi árazás",
total_price: 0,
advance_price: 0,
is_custom_price: true,
desc: "Komplex rendszerek és webáruházak nagyvállalati igényekre.", desc: "Komplex rendszerek és webáruházak nagyvállalati igényekre.",
features: [ features: [
"Korlátlan aloldalak", "Korlátlan aloldalak",

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,13 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useAuth } from '../context/AuthContext'; import { useAuth } from '../context/AuthContext';
import { Button } from '../components/Button'; import { Button } from '../components/Button';
import { LogOut, User, Settings as SettingsIcon, CreditCard, Layout, Cake, ShieldAlert, Clock, Activity, CheckCircle, XCircle, MessageSquare, ArrowRight, Edit2, Download, FileText, ExternalLink, History, RefreshCw } from 'lucide-react'; import { LogOut, User, Settings as SettingsIcon, CreditCard, Layout, Cake, ShieldAlert, Clock, Activity, CheckCircle, XCircle, MessageSquare, ArrowRight, Edit2, Download, FileText, ExternalLink, History, RefreshCw, FileDown, ShieldCheck, Calendar } from 'lucide-react';
import { Link, useNavigate } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import { supabase, isSupabaseConfigured } from '../lib/supabaseClient'; import { supabase, isSupabaseConfigured } from '../lib/supabaseClient';
import { SettingsModal } from '../components/SettingsModal'; import { SettingsModal } from '../components/SettingsModal';
import { FeedbackModal } from '../components/FeedbackModal'; import { FeedbackModal } from '../components/FeedbackModal';
import { Invoice } from '../types'; import { Invoice, MaintenanceSubscription } from '../types';
interface UserProfile { interface UserProfile {
id: string; id: string;
@@ -22,6 +23,14 @@ interface OrderHistoryEntry {
changed_at: string; changed_at: string;
} }
interface Bill {
id: string;
order_id: string;
type: 'advance' | 'final';
file_url: string;
created_at: string;
}
interface UserOrder { interface UserOrder {
id: string; id: string;
created_at: string; created_at: string;
@@ -31,6 +40,8 @@ interface UserOrder {
displayId?: string; displayId?: string;
details?: any; details?: any;
history?: OrderHistoryEntry[]; history?: OrderHistoryEntry[];
bills?: Bill[];
subscription?: MaintenanceSubscription;
} }
export const Dashboard: React.FC = () => { export const Dashboard: React.FC = () => {
@@ -60,6 +71,34 @@ export const Dashboard: React.FC = () => {
} }
}; };
const fetchOrderBills = async (orderId: string) => {
if (!isSupabaseConfigured) return [];
try {
const { data } = await supabase
.from('bills')
.select('*')
.eq('order_id', orderId)
.order('created_at', { ascending: false });
return data || [];
} catch (e) {
return [];
}
};
const fetchSubscription = async (orderId: string) => {
if (!isSupabaseConfigured) return undefined;
try {
const { data } = await supabase
.from('maintenance_subscriptions')
.select('*')
.eq('order_id', orderId)
.maybeSingle();
return data as MaintenanceSubscription | undefined;
} catch (e) {
return undefined;
}
}
const fetchData = async () => { const fetchData = async () => {
if (!user) return; if (!user) return;
setLoadingOrders(true); setLoadingOrders(true);
@@ -67,7 +106,25 @@ export const Dashboard: React.FC = () => {
if (!isSupabaseConfigured) { if (!isSupabaseConfigured) {
const meta = user.user_metadata || {}; const meta = user.user_metadata || {};
setProfile({ id: user.id, email: user.email || '', first_name: meta.first_name || '', last_name: meta.last_name || '', date_of_birth: meta.date_of_birth || '1990-01-01' }); setProfile({ id: user.id, email: user.email || '', first_name: meta.first_name || '', last_name: meta.last_name || '', date_of_birth: meta.date_of_birth || '1990-01-01' });
setOrders([{ id: 'demo-order-1', created_at: new Date().toISOString(), package: 'Pro Web', status: 'pending_feedback', amount: '350.000 Ft', displayId: 'DEMO-123', details: { demoUrl: 'https://example.com' }, history: [{ id: 'h1', status: 'new', changed_at: new Date().toISOString() }] }]); setOrders([{
id: 'demo-order-1',
created_at: new Date().toISOString(),
package: 'Pro Web',
status: 'pending_feedback',
amount: '350.000 Ft',
displayId: 'DEMO-123',
details: {
demoUrl: 'https://example.com',
payment_summary: {
total: 350000,
advance: 80000,
remaining: 270000,
currency: 'HUF'
}
},
history: [{ id: 'h1', status: 'new', changed_at: new Date().toISOString() }],
bills: []
}]);
setLoadingOrders(false); setLoadingOrders(false);
return; return;
} }
@@ -81,10 +138,14 @@ export const Dashboard: React.FC = () => {
if (orderData) { if (orderData) {
const enrichedOrders = await Promise.all(orderData.map(async (o) => { const enrichedOrders = await Promise.all(orderData.map(async (o) => {
const history = await fetchOrderHistory(o.id); const history = await fetchOrderHistory(o.id);
const bills = await fetchOrderBills(o.id);
const sub = await fetchSubscription(o.id);
return { return {
...o, ...o,
displayId: o.id.substring(0, 8).toUpperCase(), displayId: o.id.substring(0, 8).toUpperCase(),
history: history history: history,
bills: bills,
subscription: sub
}; };
})); }));
setOrders(enrichedOrders as UserOrder[]); setOrders(enrichedOrders as UserOrder[]);
@@ -130,7 +191,6 @@ export const Dashboard: React.FC = () => {
const { data: currentOrder } = await supabase.from('orders').select('details').eq('id', selectedOrderId).single(); const { data: currentOrder } = await supabase.from('orders').select('details').eq('id', selectedOrderId).single();
const updatedDetails = { ...(currentOrder?.details || {}), latestFeedback: feedbackData, feedbackDate: new Date().toISOString() }; const updatedDetails = { ...(currentOrder?.details || {}), latestFeedback: feedbackData, feedbackDate: new Date().toISOString() };
// Approved status also goes to in_progress now, admin will set to completed later
const { error: updateError } = await supabase.from('orders').update({ const { error: updateError } = await supabase.from('orders').update({
status: 'in_progress', status: 'in_progress',
details: updatedDetails details: updatedDetails
@@ -138,7 +198,6 @@ export const Dashboard: React.FC = () => {
if (updateError) throw updateError; if (updateError) throw updateError;
// Log history
await supabase.from('order_status_history').insert({ order_id: selectedOrderId, status: 'in_progress' }); await supabase.from('order_status_history').insert({ order_id: selectedOrderId, status: 'in_progress' });
await fetchData(); await fetchData();
@@ -166,29 +225,37 @@ export const Dashboard: React.FC = () => {
} }
}; };
const selectedOrder = orders.find(o => o.id === selectedOrderId);
return ( return (
<div className="pt-24 bg-gray-50 min-h-screen"> <div className="pt-24 bg-gray-50 min-h-screen pb-12">
<SettingsModal isOpen={showSettings} onClose={() => setShowSettings(false)} userProfile={profile} onUpdate={fetchData} /> <SettingsModal isOpen={showSettings} onClose={() => setShowSettings(false)} userProfile={profile} onUpdate={fetchData} />
<FeedbackModal isOpen={feedbackModalOpen} onClose={() => setFeedbackModalOpen(false)} onSubmit={handleSubmitFeedback} loading={feedbackLoading} /> <FeedbackModal
isOpen={feedbackModalOpen}
onClose={() => setFeedbackModalOpen(false)}
onSubmit={handleSubmitFeedback}
loading={feedbackLoading}
order={selectedOrder}
/>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="bg-white rounded-[24px] shadow-lg border border-gray-100 overflow-hidden mb-8"> <div className="bg-white rounded-[24px] shadow-lg border border-gray-100 overflow-hidden mb-8">
<div className="bg-gradient-to-r from-gray-900 to-gray-800 p-8 text-white flex flex-col md:flex-row justify-between items-center gap-4"> <div className="bg-gradient-to-r from-gray-900 to-gray-800 p-6 md:p-8 text-white flex flex-col md:flex-row justify-between items-center gap-4 text-center md:text-left">
<div> <div>
<h1 className="text-3xl font-bold mb-2">Fiók Áttekintése</h1> <h1 className="text-2xl md:text-3xl font-bold mb-2">Fiók Áttekintése</h1>
<p className="text-gray-300">Üdvözöljük, {getFullName()}!</p> <p className="text-gray-300 text-sm md:text-base">Üdvözöljük, {getFullName()}!</p>
</div> </div>
<div className="h-12 w-12 bg-white/10 rounded-full flex items-center justify-center border border-white/20"> <div className="h-12 w-12 bg-white/10 rounded-full flex items-center justify-center border border-white/20 shrink-0">
<User className="h-6 w-6 text-white" /> <User className="h-6 w-6 text-white" />
</div> </div>
</div> </div>
<div className="p-8"> <div className="p-6 md:p-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-8"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-8">
{/* ORDERS COLUMN */} {/* ORDERS COLUMN */}
<div className="lg:col-span-2 space-y-6"> <div className="lg:col-span-2 space-y-6">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<h3 className="font-bold text-gray-900 flex items-center gap-2 text-xl"> <h3 className="font-bold text-gray-900 flex items-center gap-2 text-lg md:text-xl">
<Layout className="w-5 h-5 text-primary" /> Aktív Projektjeim <Layout className="w-5 h-5 text-primary" /> Aktív Projektjeim
</h3> </h3>
</div> </div>
@@ -203,54 +270,112 @@ export const Dashboard: React.FC = () => {
return ( return (
<div key={order.id} className="bg-white rounded-2xl border border-gray-100 shadow-sm overflow-hidden hover:shadow-md transition-shadow"> <div key={order.id} className="bg-white rounded-2xl border border-gray-100 shadow-sm overflow-hidden hover:shadow-md transition-shadow">
<div className="p-6 flex flex-col sm:flex-row justify-between gap-6 border-b border-gray-50 bg-gray-50/30"> <div className="p-5 md:p-6 flex flex-col sm:flex-row justify-between gap-4 border-b border-gray-50 bg-gray-50/30">
<div> <div>
<p className="text-xs font-black text-primary uppercase tracking-widest mb-1">{order.package}</p> <p className="text-[10px] font-black text-primary uppercase tracking-widest mb-1">{order.package}</p>
<h4 className="text-xl font-bold text-gray-900">ID: {order.displayId}</h4> <h4 className="text-lg md:text-xl font-bold text-gray-900">ID: {order.displayId}</h4>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex flex-wrap items-center gap-3">
{needsFeedback && ( {needsFeedback && (
<div className="flex gap-2"> <>
<a href={order.details?.demoUrl || '#'} target="_blank" rel="noreferrer" className="text-xs px-4 py-2 rounded-xl font-black bg-blue-600 text-white flex items-center gap-2 shadow-lg shadow-blue-200"> <a href={order.details?.demoUrl || '#'} target="_blank" rel="noreferrer" className="flex-grow sm:flex-grow-0 text-[10px] px-4 py-2.5 rounded-xl font-black bg-blue-600 text-white flex items-center justify-center gap-2 shadow-lg shadow-blue-200">
<ExternalLink className="w-3 h-3" /> Demó oldal megnyitása <ExternalLink className="w-3 h-3" /> DEMÓ MEGNYITÁSA
</a> </a>
<button onClick={() => openFeedbackModal(order.id)} className="text-xs px-4 py-2 rounded-xl font-black bg-purple-100 text-purple-700 hover:bg-purple-200"> <button onClick={() => openFeedbackModal(order.id)} className="flex-grow sm:flex-grow-0 text-[10px] px-4 py-2.5 rounded-xl font-black bg-purple-100 text-purple-700 hover:bg-purple-200 uppercase tracking-wider">
VISSZAJELZÉS Visszajelzés
</button> </button>
</div> </>
)} )}
{!needsFeedback && ( {!needsFeedback && (
<span className={`text-xs px-4 py-2 rounded-xl font-black flex items-center gap-2 ${statusConfig.color}`}> <span className={`text-[10px] px-4 py-2.5 rounded-xl font-black flex items-center justify-center gap-2 ${statusConfig.color} uppercase tracking-wider`}>
<statusConfig.icon className="w-4 h-4" /> {statusConfig.label.toUpperCase()} <statusConfig.icon className="w-3.5 h-3.5" /> {statusConfig.label}
</span> </span>
)} )}
</div> </div>
</div> </div>
{/* PROJECT TIMELINE */} <div className="grid grid-cols-1 md:grid-cols-2 divide-y md:divide-y-0 md:divide-x divide-gray-100">
<div className="p-6 bg-white"> {/* PROJECT TIMELINE */}
<div className="flex items-center gap-2 mb-4 text-xs font-black text-gray-400 uppercase tracking-[0.2em]"> <div className="p-5 md:p-6 bg-white">
<History className="w-3 h-3" /> Projekt Történet <div className="flex items-center gap-2 mb-4 text-[10px] font-black text-gray-400 uppercase tracking-[0.2em]">
</div> <History className="w-3 h-3" /> Projekt Történet
<div className="flex flex-col gap-4 relative before:absolute before:left-[7px] before:top-2 before:bottom-2 before:w-0.5 before:bg-gray-50"> </div>
{order.history && order.history.length > 0 ? ( <div className="flex flex-col gap-4 relative before:absolute before:left-[7px] before:top-2 before:bottom-2 before:w-0.5 before:bg-gray-50">
order.history.map((h, idx) => ( {order.history && order.history.length > 0 ? (
<div key={h.id} className="relative pl-6 flex justify-between items-center group"> order.history.map((h, idx) => (
<div className={`absolute left-0 top-1.5 w-3.5 h-3.5 rounded-full border-2 border-white shadow-sm z-10 ${idx === 0 ? 'bg-primary' : 'bg-gray-200'}`}></div> <div key={h.id} className="relative pl-6 flex justify-between items-center group">
<div className="flex flex-col"> <div className={`absolute left-0 top-1.5 w-3.5 h-3.5 rounded-full border-2 border-white shadow-sm z-10 ${idx === 0 ? 'bg-primary' : 'bg-gray-200'}`}></div>
<span className={`text-xs font-bold ${idx === 0 ? 'text-gray-900' : 'text-gray-500'}`}> <div className="flex flex-col">
{getStatusConfig(h.status).label} <span className={`text-xs font-bold ${idx === 0 ? 'text-gray-900' : 'text-gray-500'}`}>
</span> {getStatusConfig(h.status).label}
<span className="text-[10px] text-gray-400 font-medium"> </span>
{new Date(h.changed_at).toLocaleString('hu-HU')} <span className="text-[10px] text-gray-400 font-medium">
</span> {new Date(h.changed_at).toLocaleString('hu-HU')}
</span>
</div>
</div>
))
) : (
<p className="text-xs text-gray-400 italic pl-6">Nincs korábbi bejegyzés.</p>
)}
</div>
</div>
{/* BILLS & DOCUMENTS / MAINTENANCE */}
<div className="p-5 md:p-6 bg-white flex flex-col justify-between">
<div>
<div className="flex items-center gap-2 mb-4 text-[10px] font-black text-gray-400 uppercase tracking-[0.2em]">
<FileText className="w-3 h-3" /> Dokumentumok
</div>
<div className="space-y-3">
{order.bills && order.bills.length > 0 ? (
order.bills.map((bill) => (
<a
key={bill.id}
href={bill.file_url}
target="_blank"
rel="noreferrer"
className="flex items-center justify-between p-3 rounded-xl border border-gray-100 hover:border-primary/30 hover:bg-purple-50/30 transition-all group"
>
<div className="flex items-center gap-3">
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${bill.type === 'advance' ? 'bg-blue-50 text-blue-600' : 'bg-green-50 text-green-600'}`}>
<CreditCard className="w-4 h-4" />
</div>
<div>
<p className="text-xs font-bold text-gray-900">{bill.type === 'advance' ? 'Előleg számla' : 'Végszámla'}</p>
<p className="text-[9px] text-gray-400 font-black uppercase tracking-widest">{new Date(bill.created_at).toLocaleDateString('hu-HU')}</p>
</div>
</div>
<FileDown className="w-4 h-4 text-gray-300 group-hover:text-primary group-hover:translate-y-0.5 transition-all flex-shrink-0" />
</a>
))
) : (
<div className="p-4 text-center bg-gray-50/50 rounded-2xl border border-dashed border-gray-100">
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest leading-relaxed">Még nincs számla.</p>
</div>
)}
</div>
</div>
{/* Maintenance Subscription Status (If Completed) */}
{order.subscription && (
<div className="mt-6 pt-4 border-t border-gray-50">
<div className="flex items-center gap-2 mb-3 text-[10px] font-black text-gray-400 uppercase tracking-[0.2em]">
<ShieldCheck className="w-3 h-3 text-primary" /> Karbantartás
</div>
<div className={`p-3 rounded-xl border flex items-center justify-between ${order.subscription.status === 'overdue' ? 'bg-red-50 border-red-100' : 'bg-green-50 border-green-100'}`}>
<div className="flex items-center gap-2">
<Calendar className={`w-4 h-4 ${order.subscription.status === 'overdue' ? 'text-red-500' : 'text-green-500'}`} />
<div>
<p className={`text-[10px] font-black uppercase tracking-wider ${order.subscription.status === 'overdue' ? 'text-red-700' : 'text-green-700'}`}>
{order.subscription.status === 'active' ? 'Aktív szolgáltatás' : 'Esedékes díj'}
</p>
<p className="text-xs font-bold text-gray-700">Fordulónap: {new Date(order.subscription.next_billing_date).toLocaleDateString('hu-HU')}</p>
</div>
</div>
</div> </div>
{idx === 0 && <span className="text-[9px] font-black text-primary bg-primary/5 px-2 py-0.5 rounded uppercase tracking-tighter">Aktuális</span>}
</div> </div>
)) )}
) : (
<p className="text-xs text-gray-400 italic pl-6">Nincs korábbi bejegyzés.</p>
)}
</div> </div>
</div> </div>
</div> </div>
@@ -265,43 +390,36 @@ export const Dashboard: React.FC = () => {
)} )}
</div> </div>
{/* SETTINGS & INVOICES COLUMN */} {/* SETTINGS COLUMN */}
<div className="space-y-8"> <div className="space-y-6 md:space-y-8">
<div className="bg-white p-8 rounded-[32px] border border-gray-100 shadow-sm"> <div className="bg-white p-6 md:p-8 rounded-[32px] border border-gray-100 shadow-sm">
<div className="flex justify-between items-center mb-6"> <div className="flex justify-between items-center mb-6">
<h3 className="font-bold text-gray-900">Beállítások</h3> <h3 className="font-bold text-gray-900">Beállítások</h3>
<button onClick={() => setShowSettings(true)} className="p-2 hover:bg-gray-50 rounded-xl transition-colors"><SettingsIcon className="w-5 h-5 text-gray-400" /></button> <button onClick={() => setShowSettings(true)} className="p-2 hover:bg-gray-50 rounded-xl transition-colors"><SettingsIcon className="w-5 h-5 text-gray-400" /></button>
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
<div className="bg-gray-50 p-4 rounded-2xl"> <div className="bg-gray-50 p-4 rounded-2xl overflow-hidden">
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest mb-1">E-mail</p> <p className="text-[10px] font-black text-gray-400 uppercase tracking-widest mb-1">E-mail</p>
<p className="text-sm font-bold text-gray-900">{user?.email}</p> <p className="text-sm font-bold text-gray-900 truncate">{user?.email}</p>
</div> </div>
<Button fullWidth variant="outline" size="sm" onClick={() => setShowSettings(true)}>Profil szerkesztése</Button> <Button fullWidth variant="outline" size="sm" onClick={() => setShowSettings(true)}>Profil szerkesztése</Button>
</div> </div>
</div> </div>
<div className="bg-white p-8 rounded-[32px] border border-gray-100 shadow-sm"> <div className="bg-gradient-to-br from-primary/10 to-secondary/10 p-6 md:p-8 rounded-[32px] border border-primary/10 shadow-sm">
<h3 className="font-bold text-gray-900 mb-6 flex items-center gap-2"><CreditCard className="w-5 h-5 text-primary" /> Számlák</h3> <h3 className="font-bold text-gray-900 mb-4 flex items-center gap-2 text-lg"><CheckCircle className="w-5 h-5 text-primary" /> Ügyfélközpont</h3>
{invoices.length > 0 ? ( <p className="text-xs text-gray-600 leading-relaxed mb-6">
<div className="space-y-3"> Bármilyen kérdése van a számlázással vagy a fejlesztéssel kapcsolatban, írjon nekünk közvetlenül.
{invoices.map(inv => ( </p>
<div key={inv.id} className="flex items-center justify-between p-3 bg-gray-50 rounded-xl group hover:bg-gray-100 transition-colors"> <a href="mailto:motionstudiohq@gmail.com" className="block text-center py-3 bg-white border border-gray-200 rounded-xl text-xs font-black text-primary uppercase tracking-widest hover:shadow-md transition-all shadow-sm">
<div className="flex items-center gap-3"> Kapcsolatfelvétel
<FileText className="w-5 h-5 text-gray-300" /> </a>
<span className="text-xs font-bold text-gray-700">{inv.invoice_number}</span>
</div>
<button className="p-2 text-gray-400 hover:text-primary"><Download className="w-4 h-4" /></button>
</div>
))}
</div>
) : <p className="text-xs text-gray-400 italic text-center">Nincs számlázott tétel.</p>}
</div> </div>
</div> </div>
</div> </div>
<div className="border-t border-gray-100 pt-6 flex justify-end"> <div className="border-t border-gray-100 pt-6 flex justify-center md:justify-end">
<Button variant="outline" onClick={handleLogout} className="border-red-200 text-red-600 hover:bg-red-50 hover:text-red-700 hover:border-red-300"> <Button variant="outline" onClick={handleLogout} className="w-full md:w-auto border-red-200 text-red-600 hover:bg-red-50 hover:text-red-700 hover:border-red-300">
<LogOut className="w-4 h-4 mr-2" /> Kijelentkezés <LogOut className="w-4 h-4 mr-2" /> Kijelentkezés
</Button> </Button>
</div> </div>
@@ -310,4 +428,4 @@ export const Dashboard: React.FC = () => {
</div> </div>
</div> </div>
); );
}; };

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { ArrowRight, Monitor, Search, ExternalLink, Check, Star, Smartphone, PenTool } from 'lucide-react'; import { ArrowRight, Monitor, Search, ExternalLink, Check, Star, Smartphone, PenTool, ShieldCheck, Clock, Info } from 'lucide-react';
import { Button } from '../components/Button'; import { Button } from '../components/Button';
import { ServiceCard } from '../components/ServiceCard'; import { ServiceCard } from '../components/ServiceCard';
import { OrderForm } from '../components/OrderForm'; import { OrderForm } from '../components/OrderForm';
@@ -17,11 +18,22 @@ export const Home: React.FC = () => {
try { try {
const { data, error } = await supabase const { data, error } = await supabase
.from('plans') .from('plans')
.select('*') .select('*');
.order('price', { ascending: true }); // Simple text ordering, ideally numerical but works for default prices somewhat
if (!error && data && data.length > 0) { if (!error && data && data.length > 0) {
setPackages(data); const sortedData = [...data].sort((a, b) => {
const priceA = a.is_custom_price ? Infinity : (a.total_price || 0);
const priceB = b.is_custom_price ? Infinity : (b.total_price || 0);
return priceA - priceB;
});
setPackages(sortedData);
} else {
const sortedDefaults = [...defaultPlans].sort((a, b) => {
const priceA = a.is_custom_price ? Infinity : (a.total_price || 0);
const priceB = b.is_custom_price ? Infinity : (b.total_price || 0);
return priceA - priceB;
});
setPackages(sortedDefaults);
} }
} catch (e) { } catch (e) {
console.error("Error fetching plans:", e); console.error("Error fetching plans:", e);
@@ -30,60 +42,60 @@ export const Home: React.FC = () => {
fetchPlans(); fetchPlans();
}, []); }, []);
const formatPrice = (num: number) => num.toLocaleString('hu-HU') + ' Ft';
return ( return (
<div className="overflow-x-hidden"> <div className="overflow-x-hidden">
{/* Hero Section */} {/* Hero Section */}
<section className="relative min-h-screen flex items-center justify-center pt-20 bg-gray-900 overflow-hidden"> <section className="relative min-h-screen flex items-center justify-center pt-20 bg-gray-900 overflow-hidden px-4">
{/* Background Elements */} {/* Background Elements */}
<div className="absolute inset-0 z-0"> <div className="absolute inset-0 z-0">
<div className="absolute inset-0 bg-gradient-to-br from-gray-900 via-[#0f172a] to-purple-900"></div> <div className="absolute inset-0 bg-gradient-to-br from-gray-900 via-[#0f172a] to-purple-900"></div>
{/* Subtle texture overlay */}
<div className="absolute inset-0 opacity-10 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')]"></div> <div className="absolute inset-0 opacity-10 bg-[url('https://www.transparenttextures.com/patterns/cubes.png')]"></div>
{/* Animated glow effects */} <div className="absolute top-[-20%] left-[-10%] w-[300px] md:w-[500px] h-[300px] md:h-[500px] bg-purple-600/20 rounded-full blur-[80px] md:blur-[100px] animate-pulse"></div>
<div className="absolute top-[-20%] left-[-10%] w-[500px] h-[500px] bg-purple-600/20 rounded-full blur-[100px] animate-pulse"></div> <div className="absolute bottom-[-20%] right-[-10%] w-[300px] md:w-[500px] h-[300px] md:h-[500px] bg-blue-600/20 rounded-full blur-[80px] md:blur-[100px] animate-pulse"></div>
<div className="absolute bottom-[-20%] right-[-10%] w-[500px] h-[500px] bg-blue-600/20 rounded-full blur-[100px] animate-pulse"></div>
</div> </div>
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10 py-12 text-center"> <div className="max-w-5xl mx-auto relative z-10 py-12 text-center">
<div <div
className="inline-block px-4 py-2 bg-white/5 backdrop-blur-sm rounded-full border border-white/10 animate-fade-in-up mb-8" className="inline-block px-4 py-2 bg-white/5 backdrop-blur-sm rounded-full border border-white/10 animate-fade-in-up mb-6 md:mb-8"
style={{ animationDelay: '0.1s' }} style={{ animationDelay: '0.1s' }}
> >
<span className="text-blue-300 font-medium text-sm tracking-wide uppercase">Innovatív Megoldások Neked</span> <span className="text-blue-300 font-medium text-xs md:text-sm tracking-wide uppercase">Innovatív Megoldások Neked</span>
</div> </div>
<h1 <h1
className="text-5xl md:text-7xl lg:text-8xl font-extrabold text-white leading-tight animate-fade-in-up mb-6 tracking-tight" className="text-4xl sm:text-5xl md:text-7xl lg:text-8xl font-extrabold text-white leading-tight animate-fade-in-up mb-4 md:mb-6 tracking-tight"
style={{ animationDelay: '0.2s' }} style={{ animationDelay: '0.2s' }}
> >
Motion Web Stúdió Motion Web Stúdió
</h1> </h1>
<h2 <h2
className="text-2xl md:text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400 animate-fade-in-up mb-8" className="text-xl sm:text-2xl md:text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400 animate-fade-in-up mb-8"
style={{ animationDelay: '0.3s' }} style={{ animationDelay: '0.3s' }}
> >
Vigye vállalkozását a következő szintre Vigye vállalkozását a következő szintre
</h2> </h2>
<p <p
className="text-lg text-gray-400 max-w-2xl mx-auto leading-relaxed animate-fade-in-up mb-12" className="text-base md:text-lg text-gray-400 max-w-2xl mx-auto leading-relaxed animate-fade-in-up mb-10 md:mb-12 px-2"
style={{ animationDelay: '0.5s' }} style={{ animationDelay: '0.5s' }}
> >
A MotionWeb csapata prémium minőségű weboldalakat és webáruházakat fejleszt, amelyek nemcsak szépek, de vevőket is hoznak. A MotionWeb csapata prémium minőségű weboldalakat és webáruházakat fejleszt, amelyek nemcsak szépek, de vevőket is hoznak.
</p> </p>
<div <div
className="flex flex-col sm:flex-row gap-5 justify-center animate-fade-in-up" className="flex flex-col sm:flex-row gap-4 md:gap-5 justify-center animate-fade-in-up px-4 sm:px-0"
style={{ animationDelay: '0.7s' }} style={{ animationDelay: '0.7s' }}
> >
<Link to="/#rendeles"> <Link to="/#rendeles" className="w-full sm:w-auto">
<Button size="lg" className="w-full sm:w-auto shadow-lg shadow-purple-900/20"> <Button size="lg" className="w-full shadow-lg shadow-purple-900/20">
Kezdjük el <ArrowRight className="ml-2 w-5 h-5" /> Kezdjük el <ArrowRight className="ml-2 w-5 h-5" />
</Button> </Button>
</Link> </Link>
<Link to="/#references"> <Link to="/#references" className="w-full sm:w-auto">
<Button variant="outline" size="lg" className="border-white/20 text-white hover:bg-white/10 hover:border-white w-full sm:w-auto backdrop-blur-sm"> <Button variant="outline" size="lg" className="border-white/20 text-white hover:bg-white/10 hover:border-white w-full backdrop-blur-sm">
Referenciák Referenciák
</Button> </Button>
</Link> </Link>
@@ -92,19 +104,19 @@ export const Home: React.FC = () => {
</section> </section>
{/* Services Section */} {/* Services Section */}
<section id="services" className="py-24 bg-gray-50 scroll-mt-20"> <section id="services" className="py-20 md:py-24 bg-gray-50 scroll-mt-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center max-w-3xl mx-auto mb-16"> <div className="text-center max-w-3xl mx-auto mb-12 md:mb-16">
<h2 className="text-base font-semibold text-primary tracking-wide uppercase">Szolgáltatásaink</h2> <h2 className="text-sm md:text-base font-semibold text-primary tracking-wide uppercase">Szolgáltatásaink</h2>
<p className="mt-2 text-3xl font-extrabold text-gray-900 sm:text-4xl"> <p className="mt-2 text-2xl sm:text-3xl md:text-4xl font-extrabold text-gray-900">
Minden, ami a sikeres online jelenléthez kell Minden, ami a sikeres online jelenléthez kell
</p> </p>
<p className="mt-4 text-xl text-gray-500"> <p className="mt-4 text-lg md:text-xl text-gray-500 px-2">
Teljeskörű digitális kivitelezés a tervezéstől az üzemeltetésig. Teljeskörű digitális kivitelezés a tervezéstől az üzemeltetésig.
</p> </p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 md:gap-8">
<ServiceCard <ServiceCard
title="Egyedi Weboldal" title="Egyedi Weboldal"
description="Modern, gyors és reszponzív weboldalak, amelyek tükrözik márkája értékeit." description="Modern, gyors és reszponzív weboldalak, amelyek tükrözik márkája értékeit."
@@ -130,115 +142,59 @@ export const Home: React.FC = () => {
</section> </section>
{/* References Section */} {/* References Section */}
<section id="references" className="py-24 bg-white scroll-mt-20"> <section id="references" className="py-20 md:py-24 bg-white scroll-mt-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16"> <div className="text-center mb-12 md:mb-16">
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">Referenciák</h2> <h2 className="text-2xl md:text-4xl font-bold text-gray-900 mb-4">Referenciák</h2>
<p className="text-lg text-gray-600 max-w-2xl mx-auto"> <p className="text-base md:text-lg text-gray-600 max-w-2xl mx-auto">
Tekintsd meg, milyen modern és reszponzív weboldalakat készítünk ügyfeleink számára. Tekintsd meg, milyen modern és reszponzív weboldalakat készítünk ügyfeleink számára.
</p> </p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8">
{/* Card 1: SweetCraving */}
<div className="bg-white rounded-2xl overflow-hidden shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300 flex flex-col"> <div className="bg-white rounded-2xl overflow-hidden shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300 flex flex-col">
<div className="h-64 overflow-hidden"> <div className="h-48 sm:h-64 overflow-hidden">
<img <img src="https://images.unsplash.com/photo-1563729784474-d77dbb933a9e?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="SweetCraving" className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-500" />
src="https://images.unsplash.com/photo-1563729784474-d77dbb933a9e?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80"
alt="SweetCraving Desszertműhely"
className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-500"
/>
</div> </div>
<div className="p-8 flex flex-col flex-grow"> <div className="p-6 md:p-8 flex flex-col flex-grow">
<h3 className="text-xl font-bold text-gray-900 mb-2">SweetCraving Desszertműhely</h3> <h3 className="text-xl font-bold text-gray-900 mb-2">SweetCraving</h3>
<p className="text-sm text-gray-500 font-medium mb-4">Kézműves desszertek Landing Page csomag</p> <p className="text-xs text-gray-500 font-medium mb-4 uppercase tracking-wider">Landing Page csomag</p>
<p className="text-gray-600 mb-6 flex-grow leading-relaxed"> <p className="text-gray-600 mb-6 flex-grow leading-relaxed text-sm md:text-base">Fiatalos, barátságos hangulatú bemutatkozó oldalt hoztunk létre.</p>
A SweetCraving számára egy fiatalos, barátságos hangulatú bemutatkozó oldalt hoztunk létre. <Link to="/demos/sweetcraving">
</p> <Button variant="outline" fullWidth className="group justify-between text-gray-700 border-gray-300">
Oldal megtekintése <ExternalLink className="w-4 h-4 ml-2" />
<div className="flex items-center gap-3 mb-8"> </Button>
<span className="text-sm text-gray-500 mr-2">Színek:</span> </Link>
<div className="w-6 h-6 rounded-full bg-pink-300 border border-gray-200"></div>
<div className="w-6 h-6 rounded-full bg-yellow-200 border border-gray-200"></div>
<div className="w-6 h-6 rounded-full bg-white border border-gray-200"></div>
</div>
<div className="w-full">
<Link to="/demos/sweetcraving">
<Button variant="outline" fullWidth className="group justify-between text-gray-700 border-gray-300 hover:border-gray-400 hover:bg-gray-50">
Oldal megtekintése
<ExternalLink className="w-4 h-4 ml-2" />
</Button>
</Link>
</div>
</div> </div>
</div> </div>
{/* Card 2: BlueWave */}
<div className="bg-white rounded-2xl overflow-hidden shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300 flex flex-col"> <div className="bg-white rounded-2xl overflow-hidden shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300 flex flex-col">
<div className="h-64 overflow-hidden"> <div className="h-48 sm:h-64 overflow-hidden">
<img <img src="https://images.unsplash.com/photo-1509391366360-2e959784a276?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="BlueWave" className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-500" />
src="https://images.unsplash.com/photo-1509391366360-2e959784a276?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80"
alt="BlueWave Solar Kft."
className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-500"
/>
</div> </div>
<div className="p-8 flex flex-col flex-grow"> <div className="p-6 md:p-8 flex flex-col flex-grow">
<h3 className="text-xl font-bold text-gray-900 mb-2">BlueWave Solar Kft.</h3> <h3 className="text-xl font-bold text-gray-900 mb-2">BlueWave Solar Kft.</h3>
<p className="text-sm text-gray-500 font-medium mb-4">Zöld energia megoldások Pro Web csomag</p> <p className="text-xs text-gray-500 font-medium mb-4 uppercase tracking-wider">Pro Web csomag</p>
<p className="text-gray-600 mb-6 flex-grow leading-relaxed"> <p className="text-gray-600 mb-6 flex-grow leading-relaxed text-sm md:text-base">Modern, üzleti stílusú, reszponzív weboldal kalkulátorral.</p>
A BlueWave Solar számára modern, üzleti stílusú, reszponzív weboldalt készítettünk. <Link to="/demos/bluewave">
</p> <Button variant="outline" fullWidth className="group justify-between text-gray-700 border-gray-300">
Oldal megtekintése <ExternalLink className="w-4 h-4 ml-2" />
<div className="flex items-center gap-3 mb-8"> </Button>
<span className="text-sm text-gray-500 mr-2">Színek:</span> </Link>
<div className="w-6 h-6 rounded-full bg-sky-600 border border-gray-200"></div>
<div className="w-6 h-6 rounded-full bg-green-500 border border-gray-200"></div>
<div className="w-6 h-6 rounded-full bg-white border border-gray-200"></div>
</div>
<div className="w-full">
<Link to="/demos/bluewave">
<Button variant="outline" fullWidth className="group justify-between text-gray-700 border-gray-300 hover:border-gray-400 hover:bg-gray-50">
Oldal megtekintése
<ExternalLink className="w-4 h-4 ml-2" />
</Button>
</Link>
</div>
</div> </div>
</div> </div>
<div className="bg-white rounded-2xl overflow-hidden shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300 flex flex-col md:col-span-2 lg:col-span-1">
{/* Card 3: Steelguard */} <div className="h-48 sm:h-64 overflow-hidden">
<div className="bg-white rounded-2xl overflow-hidden shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300 flex flex-col"> <img src="https://images.unsplash.com/photo-1518770660439-4636190af475?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Steelguard" className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-500" />
<div className="h-64 overflow-hidden">
<img
src="https://images.unsplash.com/photo-1518770660439-4636190af475?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80"
alt="Steelguard Biztonságtechnika"
className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-500"
/>
</div> </div>
<div className="p-8 flex flex-col flex-grow"> <div className="p-6 md:p-8 flex flex-col flex-grow">
<h3 className="text-xl font-bold text-gray-900 mb-2">Steelguard Biztonságtechnika</h3> <h3 className="text-xl font-bold text-gray-900 mb-2">Steelguard</h3>
<p className="text-sm text-gray-500 font-medium mb-4">Biztonságtechnika és IT rendszerek Enterprise csomag</p> <p className="text-xs text-gray-500 font-medium mb-4 uppercase tracking-wider">Enterprise csomag</p>
<p className="text-gray-600 mb-6 flex-grow leading-relaxed"> <p className="text-gray-600 mb-6 flex-grow leading-relaxed text-sm md:text-base">Technológiai, sötét tónusú enterprise weboldal.</p>
A Steelguard számára technológiai, sötét tónusú weboldalt készítettünk. <Link to="/demos/steelguard">
</p> <Button variant="outline" fullWidth className="group justify-between text-gray-700 border-gray-300">
Oldal megtekintése <ExternalLink className="w-4 h-4 ml-2" />
<div className="flex items-center gap-3 mb-8"> </Button>
<span className="text-sm text-gray-500 mr-2">Színek:</span> </Link>
<div className="w-6 h-6 rounded-full bg-black border border-gray-200"></div>
<div className="w-6 h-6 rounded-full bg-blue-600 border border-gray-200"></div>
<div className="w-6 h-6 rounded-full bg-gray-300 border border-gray-200"></div>
</div>
<div className="w-full">
<Link to="/demos/steelguard">
<Button variant="outline" fullWidth className="group justify-between text-gray-700 border-gray-300 hover:border-gray-400 hover:bg-gray-50">
Oldal megtekintése
<ExternalLink className="w-4 h-4 ml-2" />
</Button>
</Link>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -246,58 +202,98 @@ export const Home: React.FC = () => {
</section> </section>
{/* Products/Packages Section */} {/* Products/Packages Section */}
<section id="products" className="py-24 bg-gray-50 scroll-mt-20"> <section id="products" className="py-20 md:py-24 bg-gray-50 scroll-mt-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16"> <div className="text-center mb-12 md:mb-16">
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">Csomagajánlataink</h2> <h2 className="text-2xl md:text-4xl font-bold text-gray-900 mb-4">Csomagajánlataink</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto"> <p className="text-lg md:text-xl text-gray-600 max-w-2xl mx-auto">
Átlátható árazás, rejtett költségek nélkül. Válassza az Ön céljaihoz leginkább illeszkedő csomagot. Átlátható árazás, rejtett költségek nélkül.
</p> </p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6 md:gap-8">
{packages.map((pkg, index) => ( {packages.map((pkg, index) => {
<div const remaining = (pkg.total_price || 0) - (pkg.advance_price || 0);
key={index}
className={`relative bg-white rounded-2xl shadow-xl flex flex-col p-8 transition-transform hover:-translate-y-2 duration-300 ${pkg.isPopular ? 'border-2 border-primary ring-4 ring-purple-100' : 'border border-gray-100'}`} return (
> <div
{pkg.isPopular && ( key={index}
<div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-gradient-to-r from-primary to-secondary text-white px-4 py-1 rounded-full text-sm font-bold shadow-lg flex items-center gap-1"> className={`relative bg-white rounded-2xl shadow-xl flex flex-col p-6 md:p-8 transition-transform hover:-translate-y-2 duration-300 ${pkg.isPopular ? 'border-2 border-primary ring-4 ring-purple-100' : 'border border-gray-100'}`}
<Star className="w-4 h-4 fill-current" /> Legnépszerűbb >
{pkg.isPopular && (
<div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-gradient-to-r from-primary to-secondary text-white px-4 py-1 rounded-full text-xs md:text-sm font-bold shadow-lg flex items-center gap-1">
<Star className="w-3 h-3 md:w-4 h-4 fill-current" /> Legnépszerűbb
</div>
)}
<div className="mb-6">
<h3 className="text-xl md:text-2xl font-bold text-gray-900">{pkg.name}</h3>
<p className="text-gray-500 mt-2 text-xs md:text-sm min-h-[40px]">{pkg.desc}</p>
</div>
<div className="mb-8">
<span className="text-2xl md:text-3xl font-extrabold text-gray-900 block">
{pkg.is_custom_price ? 'Egyedi árazás' : (pkg.price || 'Egyedi árazás')}
</span>
{!pkg.is_custom_price && pkg.advance_price && pkg.advance_price > 0 ? (
<div className="mt-3 space-y-1 border-t border-gray-100 pt-3">
<div className="flex items-center text-[10px] md:text-xs font-bold text-gray-400 uppercase tracking-tight">
<div className="w-1.5 h-1.5 rounded-full bg-blue-400 mr-2"></div>
<span>Előleg: {formatPrice(pkg.advance_price)}</span>
</div>
<div className="flex items-center text-[10px] md:text-xs font-bold text-gray-400 uppercase tracking-tight">
<div className="w-1.5 h-1.5 rounded-full bg-primary mr-2"></div>
<span>Fennmaradó: {formatPrice(remaining)} (demó elfogadása után)</span>
</div>
</div>
) : null}
</div>
<ul className="space-y-3 md:space-y-4 mb-8 flex-grow">
{pkg.features.map((feature, i) => (
<li key={i} className="flex items-start text-gray-600">
<Check className="w-4 h-4 md:w-5 h-5 text-green-500 mr-2 md:mr-3 flex-shrink-0 mt-0.5" />
<span className="text-xs md:text-sm">{feature}</span>
</li>
))}
</ul>
<div className="mt-auto">
<Link to="/#rendeles" className="w-full">
<Button
variant={pkg.isPopular ? 'primary' : 'outline'}
fullWidth
>
{pkg.cta}
</Button>
</Link>
</div> </div>
)}
<div className="mb-6">
<h3 className="text-2xl font-bold text-gray-900">{pkg.name}</h3>
<p className="text-gray-500 mt-2 text-sm min-h-[40px]">{pkg.desc}</p>
</div> </div>
);
})}
</div>
<div className="mb-8"> {/* Maintenance Info Panel */}
<span className="text-3xl font-extrabold text-gray-900">{pkg.price}</span> <div className="mt-12 w-full animate-fade-in">
{pkg.price.includes('Ft') && <span className="text-gray-500 text-sm font-normal"> + ÁFA</span>} <div className="bg-gradient-to-br from-white to-gray-50 border border-gray-200 rounded-[32px] p-6 md:p-10 shadow-sm flex flex-col md:flex-row items-center gap-6 md:gap-10">
</div> <div className="w-16 h-16 md:w-20 md:h-20 bg-primary/10 rounded-3xl flex items-center justify-center text-primary shrink-0 shadow-inner">
<ShieldCheck className="w-8 h-8 md:w-10 md:h-10" />
<ul className="space-y-4 mb-8 flex-grow"> </div>
{pkg.features.map((feature, i) => ( <div className="flex-grow text-center md:text-left">
<li key={i} className="flex items-start text-gray-600"> <h4 className="text-lg md:text-xl font-black text-gray-900 mb-2 uppercase tracking-tighter">Éves üzemeltetés és karbantartás</h4>
<Check className="w-5 h-5 text-green-500 mr-3 flex-shrink-0 mt-0.5" /> <p className="text-sm md:text-base text-gray-600 leading-relaxed mb-4">
<span className="text-sm">{feature}</span> A weboldal stabil működéséhez, a tárhely biztosításához és a folyamatos biztonsági frissítésekhez éves díjat alkalmazunk. <strong>A rendelés ára tartalmazza az első év üzemeltetését, így az éves díj megfizetése csak az átadást követő egy év múlva válik először esedékessé.</strong>
</li> </p>
))} <div className="flex flex-wrap justify-center md:justify-start gap-4 text-[10px] md:text-xs font-bold uppercase tracking-widest text-gray-400">
</ul> <span className="flex items-center gap-1.5"><Clock className="w-3.5 h-3.5 text-primary" /> 2026-ig garantált ár</span>
<span className="flex items-center gap-1.5"><Info className="w-3.5 h-3.5 text-primary" /> Évente inflációkövető módosítás lehetséges</span>
<div className="mt-auto">
<Link to="/#rendeles">
<Button
variant={pkg.isPopular ? 'primary' : 'outline'}
fullWidth
>
{pkg.cta}
</Button>
</Link>
</div> </div>
</div> </div>
))} <div className="bg-white border-2 border-primary/20 rounded-[24px] px-8 py-6 text-center shadow-lg shadow-primary/5 min-w-[200px]">
<p className="text-[10px] font-black text-gray-400 uppercase tracking-[0.2em] mb-1">Díj / Év</p>
<p className="text-2xl md:text-3xl font-black text-primary">59 990 Ft</p>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
@@ -306,11 +302,11 @@ export const Home: React.FC = () => {
<ProcessSection /> <ProcessSection />
{/* Order Form Section */} {/* Order Form Section */}
<section id="rendeles" className="py-20 bg-white scroll-mt-20"> <section id="rendeles" className="py-16 md:py-20 bg-white scroll-mt-20">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<OrderForm /> <OrderForm />
</div> </div>
</section> </section>
</div> </div>
); );
}; };

View File

@@ -1,3 +1,4 @@
import React from 'react'; import React from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { ArrowLeft, Shield, Mail, Globe, Database, Cookie, UserCheck, Scale, Lock } from 'lucide-react'; import { ArrowLeft, Shield, Mail, Globe, Database, Cookie, UserCheck, Scale, Lock } from 'lucide-react';
@@ -84,7 +85,7 @@ export const Privacy: React.FC = () => {
</div> </div>
</section> </section>
{/* Section 2 */} {/* Section 2 - UPDATED */}
<section> <section>
<h3 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-3"> <h3 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-3">
<span className="flex items-center justify-center w-8 h-8 rounded-lg bg-secondary/10 text-secondary text-sm">2</span> <span className="flex items-center justify-center w-8 h-8 rounded-lg bg-secondary/10 text-secondary text-sm">2</span>
@@ -94,11 +95,10 @@ export const Privacy: React.FC = () => {
<p>Az adatkezelés a GDPR 6. cikk (1) bekezdése alapján történik, az alábbi jogalapokon:</p> <p>Az adatkezelés a GDPR 6. cikk (1) bekezdése alapján történik, az alábbi jogalapokon:</p>
<ul className="grid grid-cols-1 md:grid-cols-2 gap-3"> <ul className="grid grid-cols-1 md:grid-cols-2 gap-3">
{[ {[
'szerződés teljesítése, valamint', 'szerződés teljesítése, valamint szerződés megkötését megelőző lépések,',
'szerződés megkötését megelőző lépések,',
'jogi kötelezettség teljesítése (számlázás),', 'jogi kötelezettség teljesítése (számlázás),',
'jogos érdek (a szolgáltatás működtetése és biztonsága),', 'jogos érdek (a szolgáltatás működtetése és biztonsága),',
'érintetti hozzájárulás (cookie-k alkalmazása).' 'érintetti hozzájárulás (marketing célú hírlevélre való feliratkozás és cookie-k alkalmazása).'
].map((item, i) => ( ].map((item, i) => (
<li key={i} className="flex items-center gap-3 text-sm bg-gray-50 p-3 rounded-lg border border-gray-100"> <li key={i} className="flex items-center gap-3 text-sm bg-gray-50 p-3 rounded-lg border border-gray-100">
<UserCheck className="w-4 h-4 text-secondary flex-shrink-0" /> <UserCheck className="w-4 h-4 text-secondary flex-shrink-0" />
@@ -106,10 +106,14 @@ export const Privacy: React.FC = () => {
</li> </li>
))} ))}
</ul> </ul>
<p className="bg-blue-50 p-4 rounded-xl border border-blue-100 text-gray-700 mt-4"> <div className="mt-6 space-y-3">
A MotionWeb szolgáltatásai fix csomagárakon érhetők el. A megrendelés leadásával és az előleg megfizetésével a felek között szerződés jön létre. <p className="bg-blue-50 p-4 rounded-xl border border-blue-100 text-gray-700">
</p> A MotionWeb szolgáltatásai fix csomagárakon érhetők el. A megrendelés leadásával és az előleg megfizetésével a felek között szerződés jön létre.
<p className="font-bold text-gray-800">A MotionWeb nem végez marketing célú adatkezelést.</p> </p>
<p className="text-gray-700">
A hírlevélre való feliratkozás önkéntes, az erre vonatkozó hozzájárulás bármikor korlátozás és indokolás nélkül, ingyenesen visszavonható.
</p>
</div>
</div> </div>
</section> </section>
@@ -339,4 +343,4 @@ export const Privacy: React.FC = () => {
</div> </div>
</div> </div>
); );
}; };

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Check, Star } from 'lucide-react'; import { Check, Star, ShieldCheck, Clock, Info } from 'lucide-react';
import { Button } from '../components/Button'; import { Button } from '../components/Button';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { supabase } from '../lib/supabaseClient'; import { supabase } from '../lib/supabaseClient';
@@ -14,11 +15,22 @@ export const Products: React.FC = () => {
try { try {
const { data, error } = await supabase const { data, error } = await supabase
.from('plans') .from('plans')
.select('*') .select('*');
.order('price', { ascending: true });
if (!error && data && data.length > 0) { if (!error && data && data.length > 0) {
setPackages(data); const sortedData = [...data].sort((a, b) => {
const priceA = a.is_custom_price ? Infinity : (a.total_price || 0);
const priceB = b.is_custom_price ? Infinity : (b.total_price || 0);
return priceA - priceB;
});
setPackages(sortedData);
} else {
const sortedDefaults = [...defaultPlans].sort((a, b) => {
const priceA = a.is_custom_price ? Infinity : (a.total_price || 0);
const priceB = b.is_custom_price ? Infinity : (b.total_price || 0);
return priceA - priceB;
});
setPackages(sortedDefaults);
} }
} catch (e) { } catch (e) {
console.error("Error fetching plans:", e); console.error("Error fetching plans:", e);
@@ -27,6 +39,8 @@ export const Products: React.FC = () => {
fetchPlans(); fetchPlans();
}, []); }, []);
const formatPrice = (num: number) => num.toLocaleString('hu-HU') + ' Ft';
return ( return (
<div className="pt-20 bg-gray-50 min-h-screen"> <div className="pt-20 bg-gray-50 min-h-screen">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
@@ -38,48 +52,88 @@ export const Products: React.FC = () => {
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{packages.map((pkg, index) => ( {packages.map((pkg, index) => {
<div const remaining = (pkg.total_price || 0) - (pkg.advance_price || 0);
key={index}
className={`relative bg-white rounded-2xl shadow-xl flex flex-col p-8 transition-transform hover:-translate-y-2 duration-300 ${pkg.isPopular ? 'border-2 border-primary ring-4 ring-purple-100' : 'border border-gray-100'}`} return (
> <div
{pkg.isPopular && ( key={index}
<div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-gradient-to-r from-primary to-secondary text-white px-4 py-1 rounded-full text-sm font-bold shadow-lg flex items-center gap-1"> className={`relative bg-white rounded-2xl shadow-xl flex flex-col p-8 transition-transform hover:-translate-y-2 duration-300 ${pkg.isPopular ? 'border-2 border-primary ring-4 ring-purple-100' : 'border border-gray-100'}`}
<Star className="w-4 h-4 fill-current" /> Legnépszerűbb >
{pkg.isPopular && (
<div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-gradient-to-r from-primary to-secondary text-white px-4 py-1 rounded-full text-sm font-bold shadow-lg flex items-center gap-1">
<Star className="w-4 h-4 fill-current" /> Legnépszerűbb
</div>
)}
<div className="mb-6">
<h3 className="text-2xl font-bold text-gray-900">{pkg.name}</h3>
<p className="text-gray-500 mt-2 text-sm min-h-[40px]">{pkg.desc}</p>
</div>
<div className="mb-8">
<span className="text-3xl font-extrabold text-gray-900 block">
{pkg.is_custom_price ? 'Egyedi árazás' : (pkg.price || 'Egyedi árazás')}
</span>
{!pkg.is_custom_price && pkg.advance_price && pkg.advance_price > 0 ? (
<div className="mt-3 p-3 bg-gray-50 rounded-xl border border-gray-100">
<p className="text-xs font-bold text-gray-400 uppercase tracking-widest mb-1 text-center border-b border-gray-200 pb-1">Fizetési ütemezés</p>
<div className="mt-2 space-y-1">
<p className="text-sm font-bold text-gray-700 flex justify-between"><span>Előleg:</span> <span>{formatPrice(pkg.advance_price)}</span></p>
<p className="text-sm font-medium text-gray-500 flex flex-col pt-1 border-t border-gray-100 mt-1">
<span className="text-[10px] font-bold text-primary uppercase">Demó elfogadása után:</span>
<span className="font-bold text-gray-700">{formatPrice(remaining)}</span>
</p>
</div>
</div>
) : null}
</div>
<ul className="space-y-4 mb-8 flex-grow">
{pkg.features.map((feature, i) => (
<li key={i} className="flex items-start text-gray-600">
<Check className="w-5 h-5 text-green-500 mr-3 flex-shrink-0 mt-0.5" />
<span className="text-sm">{feature}</span>
</li>
))}
</ul>
<div className="mt-auto">
<Link to="/contact">
<Button
variant={pkg.isPopular ? 'primary' : 'outline'}
fullWidth
>
{pkg.cta}
</Button>
</Link>
</div> </div>
)}
<div className="mb-6">
<h3 className="text-2xl font-bold text-gray-900">{pkg.name}</h3>
<p className="text-gray-500 mt-2 text-sm min-h-[40px]">{pkg.desc}</p>
</div> </div>
);
})}
</div>
<div className="mb-8"> {/* Maintenance Info Panel */}
<span className="text-3xl font-extrabold text-gray-900">{pkg.price}</span> <div className="mt-12 w-full">
{pkg.price.includes('Ft') && <span className="text-gray-500 text-sm font-normal"> + ÁFA</span>} <div className="bg-white border border-gray-200 rounded-[32px] p-6 md:p-10 shadow-sm flex flex-col md:flex-row items-center gap-6 md:gap-10">
</div> <div className="w-16 h-16 md:w-20 md:h-20 bg-primary/5 rounded-3xl flex items-center justify-center text-primary shrink-0 border border-primary/10">
<ShieldCheck className="w-8 h-8 md:w-10 md:h-10" />
<ul className="space-y-4 mb-8 flex-grow"> </div>
{pkg.features.map((feature, i) => ( <div className="flex-grow text-center md:text-left">
<li key={i} className="flex items-start text-gray-600"> <h4 className="text-lg md:text-xl font-bold text-gray-900 mb-2 uppercase tracking-tight">Éves üzemeltetés és karbantartás</h4>
<Check className="w-5 h-5 text-green-500 mr-3 flex-shrink-0 mt-0.5" /> <p className="text-sm md:text-base text-gray-600 leading-relaxed mb-4">
<span className="text-sm">{feature}</span> Minden csomagunkhoz egységes, kedvező üzemeltetési díj tartozik, amely tartalmazza a tárhelyet, a biztonsági mentéseket és a folyamatos monitorozást. <strong>A csomagár tartalmazza az első év üzemeltetését, így az első éves díj megfizetése csak a projekt átadását követő egy év múlva válik esedékessé.</strong>
</li> </p>
))} <div className="flex flex-wrap justify-center md:justify-start gap-4 text-[10px] md:text-xs font-bold uppercase tracking-widest text-gray-400">
</ul> <span className="flex items-center gap-1.5"><Clock className="w-3.5 h-3.5 text-primary" /> 2026-ig rögzített ár</span>
<span className="flex items-center gap-1.5"><Info className="w-3.5 h-3.5 text-primary" /> Éves inflációkövető korrekció lehetséges</span>
<div className="mt-auto">
<Link to="/contact">
<Button
variant={pkg.isPopular ? 'primary' : 'outline'}
fullWidth
>
{pkg.cta}
</Button>
</Link>
</div> </div>
</div> </div>
))} <div className="bg-primary text-white rounded-[24px] px-8 py-6 text-center shadow-xl shadow-primary/20 min-w-[220px]">
<p className="text-[10px] font-bold opacity-70 uppercase tracking-[0.2em] mb-1">Éves Fenntartás</p>
<p className="text-2xl md:text-3xl font-black">59 990 Ft</p>
</div>
</div>
</div> </div>
<div className="mt-20 bg-white rounded-2xl p-8 md:p-12 shadow-sm border border-gray-100 flex flex-col md:flex-row items-center justify-between gap-8"> <div className="mt-20 bg-white rounded-2xl p-8 md:p-12 shadow-sm border border-gray-100 flex flex-col md:flex-row items-center justify-between gap-8">

View File

@@ -2,7 +2,7 @@
import React from 'react'; import React from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
// Add XCircle to the import list // Add XCircle to the import list
import { ArrowLeft, FileText, Globe, Mail, Shield, XCircle } from 'lucide-react'; import { ArrowLeft, FileText, Globe, Mail, Shield, XCircle, BellRing, Settings2 } from 'lucide-react';
import { Button } from '../components/Button'; import { Button } from '../components/Button';
export const Terms: React.FC = () => { export const Terms: React.FC = () => {
@@ -207,19 +207,27 @@ export const Terms: React.FC = () => {
</div> </div>
</section> </section>
{/* Section 10 */} {/* Section 10 - UPDATED */}
<section> <section>
<h3 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-3"> <h3 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-3">
<span className="flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary text-sm">10</span> <span className="flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary text-sm">10</span>
Admin felület és utólagos módosítások Fenntartás és technikai szolgáltatások
</h3> </h3>
<div className="space-y-4"> <div className="space-y-4">
<p>Az admin felület kizárólag azokat a funkciókat tartalmazza, amelyek a megrendelés során előzetesen egyeztetésre kerültek.</p> <p>A weboldalak üzemeltetése éves fenntartási díjhoz kötött, amely tartalmazza a tárhelyszolgáltatást, az SSL tanúsítványt, a domain/DNS kezelést és az alapvető biztonsági frissítéseket.</p>
<p>A megrendelő kizárólag az admin felületen elérhető funkciók körében jogosult önálló módosításokra.</p> <div className="bg-purple-50 p-6 rounded-2xl border border-purple-100 flex items-start gap-4">
<p>Egyszerű, technikailag nem összetett kérések (például szövegcsere) esetén a megrendelő e-mailben jelezheti igényét, amelynek teljesítésében a MotionWeb eseti alapon segítséget nyújthat.</p> <div className="p-2 bg-white rounded-lg shadow-sm">
<p className="font-bold text-gray-800 border-t border-gray-100 pt-4">Dizájnmódosítás, új funkció, új aloldal vagy admin bővítés külön megrendelésnek minősül.</p> <Settings2 className="w-5 h-5 text-primary" />
<p>A külön megrendelések egyedi árazás alapján, előzetes befizetést követően valósulnak meg.</p> </div>
<p className="italic">A MotionWeb nem nyújt folyamatos technikai támogatási vagy karbantartási szolgáltatást.</p> <div>
<p className="text-sm text-gray-700">
A fenntartási díj aktuális mértékét a weboldalon közzétett díjszabás tartalmazza. A fenntartási díj meg nem fizetése a szolgáltatás (weboldal elérhetősége) felfüggesztését vonhatja maga után.
</p>
<p className="text-sm text-primary font-bold mt-2">
A fenntartási díj nem tartalmazza az új funkciók fejlesztését vagy a dizájnmódosításokat.
</p>
</div>
</div>
</div> </div>
</section> </section>
@@ -300,6 +308,25 @@ export const Terms: React.FC = () => {
</div> </div>
</section> </section>
{/* Section 17 - NEW */}
<section>
<h3 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-3">
<span className="flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary text-sm">17</span>
Kommunikáció és marketing
</h3>
<div className="space-y-4">
<p>A szolgáltató jogosult a megrendelő által megadott e-mail címre a szolgáltatással kapcsolatos technikai és tranzakciós üzeneteket küldeni.</p>
<div className="bg-blue-50 p-6 rounded-2xl border border-blue-100 flex items-start gap-4">
<div className="p-2 bg-white rounded-lg shadow-sm">
<BellRing className="w-5 h-5 text-blue-500" />
</div>
<p className="text-sm text-gray-700">
Amennyiben a felhasználó a weboldalon ehhez kifejezetten hozzájárult, a szolgáltató jogosult marketing célú hírleveleket küldeni. A hírlevélről a felhasználó bármikor ingyenesen leiratkozhat az e-mailek alján található linken vagy a szolgáltató kapcsolattartási e-mail címén.
</p>
</div>
</div>
</section>
</div> </div>
</div> </div>

View File

@@ -140,7 +140,8 @@ export const Login: React.FC = () => {
<div> <div>
<div className="flex justify-between items-center mb-1"> <div className="flex justify-between items-center mb-1">
<label htmlFor="password" className="block text-xs font-black text-gray-400 uppercase tracking-widest">Jelszó</label> <label htmlFor="password" className="block text-xs font-black text-gray-400 uppercase tracking-widest">Jelszó</label>
<Link to="/auth/forgot-password" size="sm" className="text-[10px] font-black text-primary hover:underline uppercase tracking-widest">Elfelejtette?</Link> {/* Fixed: removed invalid 'size' prop from Link component */}
<Link to="/auth/forgot-password" className="text-[10px] font-black text-primary hover:underline uppercase tracking-widest">Elfelejtette?</Link>
</div> </div>
<input id="password" type="password" required value={password} onChange={(e) => setPassword(e.target.value)} className="appearance-none block w-full px-4 py-3 border border-gray-200 rounded-xl shadow-sm focus:outline-none focus:ring-4 focus:ring-primary/10 focus:border-primary sm:text-sm bg-white text-gray-900 font-medium" placeholder="••••••••" /> <input id="password" type="password" required value={password} onChange={(e) => setPassword(e.target.value)} className="appearance-none block w-full px-4 py-3 border border-gray-200 rounded-xl shadow-sm focus:outline-none focus:ring-4 focus:ring-primary/10 focus:border-primary sm:text-sm bg-white text-gray-900 font-medium" placeholder="••••••••" />
</div> </div>

View File

@@ -1,18 +1,20 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { ArrowLeft, Sun, Battery, Zap, ChevronRight, Menu, X, Phone, Mail, CheckCircle, Home, Info, Briefcase, Calculator, ArrowRight } from 'lucide-react'; import {
ArrowLeft, ArrowRight, Sun, Battery, Zap, ChevronRight, Menu, X, Phone,
Mail, CheckCircle, Home, Info, Briefcase, Calculator,
MapPin, Clock, Star, Share2, ArrowUpRight, Play, BookOpen
} from 'lucide-react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
export const BlueWave: React.FC = () => { export const BlueWave: React.FC = () => {
const [activePage, setActivePage] = useState<'home' | 'services' | 'about' | 'contact'>('home'); const [activePage, setActivePage] = useState<'home' | 'services' | 'blog' | 'about' | 'contact'>('home');
const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [scrolled, setScrolled] = useState(false); const [scrolled, setScrolled] = useState(false);
// Smooth scroll to top when "changing pages" in this SPA simulation
useEffect(() => { useEffect(() => {
window.scrollTo({ top: 0, behavior: 'smooth' }); window.scrollTo({ top: 0, behavior: 'smooth' });
}, [activePage]); }, [activePage]);
// Navbar scroll effect
useEffect(() => { useEffect(() => {
const handleScroll = () => setScrolled(window.scrollY > 20); const handleScroll = () => setScrolled(window.scrollY > 20);
window.addEventListener('scroll', handleScroll); window.addEventListener('scroll', handleScroll);
@@ -22,267 +24,224 @@ export const BlueWave: React.FC = () => {
const navItems = [ const navItems = [
{ id: 'home', label: 'Főoldal', icon: Home }, { id: 'home', label: 'Főoldal', icon: Home },
{ id: 'services', label: 'Megoldások', icon: Zap }, { id: 'services', label: 'Megoldások', icon: Zap },
{ id: 'about', label: 'Cégünkről', icon: Info }, { id: 'blog', label: 'Blog', icon: BookOpen },
{ id: 'about', label: 'Rólunk', icon: Info },
{ id: 'contact', label: 'Kapcsolat', icon: Phone }, { id: 'contact', label: 'Kapcsolat', icon: Phone },
]; ];
return ( return (
<div className="font-sans text-gray-800 bg-white min-h-screen flex flex-col selection:bg-[#0284c7] selection:text-white"> <div className="font-sans text-gray-800 bg-white min-h-screen flex flex-col selection:bg-[#0284c7] selection:text-white">
{/* Return to Main Site */} {/* Back to main site button */}
<div className="fixed bottom-6 right-6 z-[60]"> <div className="fixed bottom-4 right-4 md:bottom-6 md:right-6 z-[60]">
<Link to="/#references"> <Link to="/#references">
<button className="bg-gray-900 text-white shadow-xl px-5 py-3 rounded-xl text-sm font-sans font-medium flex items-center hover:bg-gray-800 hover:-translate-y-1 transition-all duration-300"> <button className="bg-gray-900 text-white shadow-2xl px-4 md:px-5 py-2.5 md:py-3 rounded-lg md:rounded-xl text-xs md:text-sm font-sans font-bold flex items-center hover:bg-[#0284c7] transition-all transform hover:-translate-y-1">
<ArrowLeft className="w-4 h-4 mr-2" /> Vissza a referenciákhoz <ArrowLeft className="w-4 h-4 mr-2" /> Vissza a portfólióhoz
</button> </button>
</Link> </Link>
</div> </div>
{/* Top Bar */} {/* Top Bar */}
<div className="bg-[#0f172a] text-gray-300 py-2.5 px-4 text-xs font-medium hidden md:block border-b border-gray-800"> <div className="bg-[#0f172a] text-gray-300 py-2.5 px-4 text-[10px] md:text-xs font-semibold hidden sm:block border-b border-gray-800">
<div className="max-w-7xl mx-auto flex justify-between items-center"> <div className="max-w-7xl mx-auto flex justify-between items-center">
<div className="flex space-x-8"> <div className="flex space-x-6">
<span className="flex items-center hover:text-white transition-colors cursor-pointer"><Phone className="w-3.5 h-3.5 mr-2 text-[#38bdf8]" /> +36 30 999 8888</span> <span className="flex items-center hover:text-white transition-colors cursor-pointer"><Phone className="w-3.5 h-3.5 mr-2 text-[#38bdf8]" /> +36 30 999 8888</span>
<span className="flex items-center hover:text-white transition-colors cursor-pointer"><Mail className="w-3.5 h-3.5 mr-2 text-[#38bdf8]" /> info@bluewave-solar.demo</span> <span className="flex items-center hover:text-white transition-colors cursor-pointer"><Mail className="w-3.5 h-3.5 mr-2 text-[#38bdf8]" /> info@bluewave-solar.hu</span>
</div> </div>
<div className="flex space-x-6"> <div className="flex space-x-6">
<a href="#" className="hover:text-white transition-colors">Lakossági</a> <span className="text-[#38bdf8] uppercase tracking-widest text-[9px]">Ingyenes felmérés az ország egész területén</span>
<a href="#" className="hover:text-white transition-colors">Ipari</a>
<a href="#" className="hover:text-white transition-colors text-[#38bdf8]">Partnerprogram</a>
</div> </div>
</div> </div>
</div> </div>
{/* Navbar */} {/* Navbar */}
<nav className={`sticky top-0 z-50 transition-all duration-300 border-b ${scrolled ? 'bg-white/95 backdrop-blur-md shadow-md py-0 border-gray-200' : 'bg-white py-4 border-transparent'}`}> <nav className={`sticky top-0 z-50 transition-all duration-500 border-b ${scrolled ? 'bg-white/95 backdrop-blur-md shadow-xl py-0 border-gray-100' : 'bg-white py-2 md:py-4 border-transparent'}`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-20 items-center"> <div className="flex justify-between h-16 md:h-20 items-center">
<div className="flex items-center cursor-pointer group" onClick={() => setActivePage('home')}> <div className="flex items-center cursor-pointer group" onClick={() => setActivePage('home')}>
<div className="bg-gradient-to-tr from-[#0284c7] to-[#0ea5e9] p-2.5 rounded-xl mr-3 shadow-lg shadow-sky-200 group-hover:scale-105 transition-transform duration-300"> <div className="bg-gradient-to-tr from-[#0284c7] to-[#0ea5e9] p-2.5 rounded-xl mr-3 shadow-lg shadow-sky-100 group-hover:rotate-12 transition-transform">
<Sun className="w-7 h-7 text-white" /> <Sun className="w-6 h-6 md:w-8 md:h-8 text-white" />
</div> </div>
<div className="leading-none"> <div className="leading-none">
<span className="block text-2xl font-bold text-gray-900 tracking-tight">BlueWave</span> <span className="block text-xl md:text-2xl font-black text-gray-900 tracking-tighter uppercase">BlueWave</span>
<span className="block text-xs font-bold text-[#0284c7] uppercase tracking-widest ml-0.5">Solar Systems</span> <span className="block text-[8px] md:text-[10px] font-black text-[#0284c7] uppercase tracking-[0.3em] ml-0.5">Napenergia Stúdió</span>
</div> </div>
</div> </div>
<div className="hidden md:flex items-center space-x-1"> <div className="hidden lg:flex items-center space-x-2">
{navItems.map((item) => ( {navItems.map((item) => (
<button <button
key={item.id} key={item.id}
onClick={() => setActivePage(item.id as any)} onClick={() => setActivePage(item.id as any)}
className={`relative px-5 py-2.5 rounded-lg text-sm font-semibold transition-all duration-300 ${ className={`px-4 py-2 rounded-xl text-sm font-bold transition-all ${
activePage === item.id activePage === item.id
? 'text-[#0284c7] bg-sky-50' ? 'text-[#0284c7] bg-sky-50'
: 'text-gray-600 hover:text-[#0284c7] hover:bg-gray-50' : 'text-gray-500 hover:text-[#0284c7] hover:bg-gray-50'
}`} }`}
> >
{item.label} {item.label}
{activePage === item.id && (
<span className="absolute bottom-0 left-1/2 transform -translate-x-1/2 w-1/2 h-0.5 bg-[#0284c7] rounded-full"></span>
)}
</button> </button>
))} ))}
<div className="pl-4 ml-4 border-l border-gray-200"> <div className="pl-6 ml-4 border-l border-gray-100">
<button <button
onClick={() => setActivePage('contact')} onClick={() => setActivePage('contact')}
className="bg-[#0284c7] hover:bg-[#0369a1] text-white px-6 py-3 rounded-lg font-bold text-sm transition-all shadow-lg shadow-sky-200 hover:-translate-y-0.5" className="bg-[#0284c7] hover:bg-gray-900 text-white px-6 py-3 rounded-xl font-black text-xs uppercase tracking-widest transition-all shadow-lg shadow-sky-100 active:scale-95"
> >
Ingyenes felmérés Ajánlatkérés
</button> </button>
</div> </div>
</div> </div>
<div className="flex items-center gap-6 md:hidden"> <button onClick={() => setMobileMenuOpen(!mobileMenuOpen)} className="lg:hidden p-2 text-gray-600 bg-gray-50 rounded-lg">
<button onClick={() => setMobileMenuOpen(!mobileMenuOpen)} className="p-2 text-gray-600 hover:bg-gray-100 rounded-lg">
{mobileMenuOpen ? <X /> : <Menu />} {mobileMenuOpen ? <X /> : <Menu />}
</button> </button>
</div>
</div> </div>
</div> </div>
{/* Mobile Menu */}
{mobileMenuOpen && ( {mobileMenuOpen && (
<div className="md:hidden bg-white border-t border-gray-100 p-4 space-y-2 shadow-xl absolute w-full animate-fade-in"> <div className="lg:hidden bg-white border-t border-gray-100 p-6 space-y-3 shadow-2xl absolute w-full animate-fade-in">
{navItems.map((item) => ( {navItems.map((item) => (
<button <button
key={item.id} key={item.id}
onClick={() => { setActivePage(item.id as any); setMobileMenuOpen(false); }} onClick={() => { setActivePage(item.id as any); setMobileMenuOpen(false); }}
className={`w-full flex items-center px-4 py-4 rounded-xl text-base font-medium ${activePage === item.id ? 'bg-sky-50 text-[#0284c7]' : 'text-gray-700 hover:bg-gray-50'}`} className={`w-full flex items-center px-5 py-4 rounded-2xl text-base font-bold ${activePage === item.id ? 'bg-sky-50 text-[#0284c7]' : 'text-gray-600'}`}
> >
<item.icon className="w-5 h-5 mr-3 opacity-70" /> <item.icon className="w-5 h-5 mr-4 opacity-50" />
{item.label} {item.label}
</button> </button>
))} ))}
<button <button
onClick={() => { setActivePage('contact'); setMobileMenuOpen(false); }} onClick={() => { setActivePage('contact'); setMobileMenuOpen(false); }}
className="w-full mt-4 bg-[#0284c7] text-white px-4 py-4 rounded-xl font-bold shadow-md" className="w-full mt-6 bg-gray-900 text-white py-5 rounded-2xl font-black uppercase tracking-widest text-xs"
> >
Ingyenes felmérés Ingyenes Konzultáció
</button> </button>
</div> </div>
)} )}
</nav> </nav>
{/* Main Content Area - Simulating Routing with smooth fade */} {/* Main Content Area */}
<main className="flex-grow relative"> <main className="flex-grow">
<div key={activePage} className="animate-fade-in"> <div key={activePage} className="animate-fade-in">
{/* HOME PAGE */} {/* --- HOME PAGE --- */}
{activePage === 'home' && ( {activePage === 'home' && (
<> <>
<section className="relative bg-[#0f172a] py-32 lg:py-48 overflow-hidden"> {/* Hero */}
<div className="absolute inset-0 z-0"> <section className="relative min-h-[85vh] flex items-center pt-20 overflow-hidden px-4">
<img src="https://images.unsplash.com/photo-1509391366360-2e959784a276?ixlib=rb-4.0.3&auto=format&fit=crop&w=2000&q=80" alt="Solar Panels" className="w-full h-full object-cover opacity-30 scale-105 animate-pulse-slow" /> <div className="absolute inset-0 z-0 scale-105">
<div className="absolute inset-0 bg-gradient-to-r from-[#0f172a] via-[#0f172a]/90 to-transparent"></div> <img src="https://images.unsplash.com/photo-1508514177221-188b1cf16e9d?ixlib=rb-4.0.3&auto=format&fit=crop&w=2000&q=80" alt="Home Solar" className="w-full h-full object-cover" />
<div className="absolute inset-0 bg-gradient-to-r from-white via-white/80 to-transparent"></div>
</div> </div>
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="relative z-10 max-w-7xl mx-auto w-full">
<div className="max-w-3xl"> <div className="max-w-2xl">
<div className="inline-flex items-center px-4 py-2 rounded-full bg-[#0ea5e9]/10 text-[#38bdf8] text-sm font-bold mb-8 border border-[#0ea5e9]/20 backdrop-blur-sm animate-fade-in-up"> <div className="inline-flex items-center px-4 py-2 rounded-full bg-sky-50 text-[#0284c7] text-[10px] md:text-xs font-black uppercase tracking-widest mb-8 border border-sky-100 shadow-sm animate-fade-in-up">
<CheckCircle className="w-4 h-4 mr-2" /> Hivatalos állami kivitelező partner <Star className="w-3 h-3 mr-2 fill-current" /> 2024 Év Kivitelezője Díj
</div> </div>
<h1 className="text-5xl md:text-7xl font-extrabold text-white mb-8 leading-tight animate-fade-in-up" style={{ animationDelay: '0.1s' }}> <h1 className="text-4xl md:text-7xl font-black text-gray-900 mb-8 leading-[0.9] tracking-tighter animate-fade-in-up" style={{ animationDelay: '0.1s' }}>
Váltson tiszta energiára <br/> A NAPENERGIA <br/>
<span className="text-transparent bg-clip-text bg-gradient-to-r from-[#38bdf8] to-[#0ea5e9]">a jövőjéért</span> <span className="text-[#0284c7]">MINDENKIÉ.</span>
</h1> </h1>
<p className="text-xl text-gray-300 mb-10 leading-relaxed max-w-2xl animate-fade-in-up" style={{ animationDelay: '0.2s' }}> <p className="text-lg md:text-xl text-gray-600 mb-10 leading-relaxed font-medium animate-fade-in-up" style={{ animationDelay: '0.2s' }}>
Csökkentse rezsijét akár 100%-kal prémium napelem rendszereinkkel. Teljeskörű ügyintézés a tervezéstől a kulcsrakész átadásig, 25 év garanciával. Felejtse el a villanyszámlát. Komplett napelemes rendszerek telepítése 0% önerővel, teljes körű állami támogatás ügyintézéssel.
</p> </p>
<div className="flex flex-col sm:flex-row gap-5 animate-fade-in-up" style={{ animationDelay: '0.3s' }}> <div className="flex flex-col sm:flex-row gap-4 animate-fade-in-up" style={{ animationDelay: '0.3s' }}>
<button onClick={() => setActivePage('contact')} className="bg-[#0284c7] hover:bg-[#0369a1] text-white px-10 py-4 rounded-xl font-bold text-lg transition-all flex items-center justify-center shadow-lg shadow-sky-900/50 hover:scale-105"> <button onClick={() => setActivePage('contact')} className="bg-[#0284c7] hover:bg-gray-900 text-white px-10 py-5 rounded-2xl font-black text-sm uppercase tracking-widest transition-all shadow-xl shadow-sky-200 flex items-center justify-center">
Kalkuláció kérése <ChevronRight className="w-5 h-5 ml-2" /> Kérjen ajánlatot <ArrowUpRight className="ml-2 w-5 h-5" />
</button> </button>
<button onClick={() => setActivePage('services')} className="bg-white/5 hover:bg-white/10 text-white backdrop-blur-sm px-10 py-4 rounded-xl font-bold text-lg transition-all border border-white/10 hover:border-white/30"> <button onClick={() => setActivePage('services')} className="bg-white hover:bg-gray-50 text-gray-900 border-2 border-gray-100 px-10 py-5 rounded-2xl font-black text-sm uppercase tracking-widest transition-all">
Rendszereink Ismerje meg a technológiát
</button> </button>
</div> </div>
<div className="mt-16 flex items-center gap-8 text-gray-400 text-sm font-medium animate-fade-in-up" style={{ animationDelay: '0.5s' }}>
<div className="flex items-center gap-2">
<div className="w-2 h-2 rounded-full bg-green-500"></div> 1000+ elégedett ügyfél
</div>
<div className="flex items-center gap-2">
<div className="w-2 h-2 rounded-full bg-green-500"></div> Országos lefedettség
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
<section className="py-24 bg-gray-50 relative"> {/* Status Grid */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 -mt-32 relative z-20"> <section className="py-20 bg-white border-b border-gray-100">
<div className="grid md:grid-cols-3 gap-8"> <div className="max-w-7xl mx-auto px-4">
{[ <div className="grid grid-cols-2 md:grid-cols-4 gap-8 md:gap-12">
{ icon: Sun, color: 'text-[#0284c7]', bg: 'bg-sky-50', title: 'Prémium Panelek', desc: 'Tier-1 kategóriás napelemek 25 év teljesítménygaranciával és kiemelkedő hatásfokkal.' }, {[
{ icon: Battery, color: 'text-emerald-600', bg: 'bg-emerald-50', title: 'Energiatárolás', desc: 'Hibrid rendszerek és akkumulátoros megoldások a teljes függetlenségért.' }, { val: '1200+', label: 'Telepített rendszer' },
{ icon: Briefcase, color: 'text-orange-600', bg: 'bg-orange-50', title: 'Kulcsrakész', desc: 'Minden papírmunkát, pályázatot és engedélyeztetést elintézünk Ön helyett.' } { val: '25 Év', label: 'Garancia' },
].map((item, i) => ( { val: '99%', label: 'Ügyfél-elégedettség' },
<div key={i} className="bg-white p-10 rounded-2xl shadow-xl border border-gray-100 hover:-translate-y-2 transition-transform duration-300"> { val: '24 Óra', label: 'Válaszidő' }
<div className={`w-16 h-16 ${item.bg} rounded-2xl flex items-center justify-center mb-8 ${item.color}`}> ].map((s, i) => (
<item.icon className="w-8 h-8" /> <div key={i} className="text-center">
</div> <p className="text-3xl md:text-5xl font-black text-gray-900 mb-2">{s.val}</p>
<h3 className="text-2xl font-bold mb-4 text-gray-900">{item.title}</h3> <p className="text-[10px] md:text-xs font-black text-[#0284c7] uppercase tracking-[0.2em]">{s.label}</p>
<p className="text-gray-600 leading-relaxed">{item.desc}</p> </div>
</div> ))}
))} </div>
</div> </div>
</div> </section>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-24"> {/* Featured Section */}
<div className="text-center mb-16"> <section className="py-24 bg-gray-50">
<h2 className="text-3xl font-bold text-gray-900 mb-4">Miért válassza a BlueWave-et?</h2> <div className="max-w-7xl mx-auto px-4">
<p className="text-xl text-gray-600">Szakértelem, minőség és megbízhatóság egy helyen.</p> <div className="flex flex-col md:flex-row justify-between items-end mb-16 gap-6">
</div> <div className="max-w-2xl">
<h2 className="text-sm font-black text-[#0284c7] uppercase tracking-[0.3em] mb-4">Prémium Szolgáltatás</h2>
<div className="grid md:grid-cols-2 gap-12 items-center"> <p className="text-3xl md:text-5xl font-black text-gray-900 leading-tight tracking-tighter">Miért a BlueWave a legjobb választás?</p>
<img src="https://images.unsplash.com/photo-1581092160562-40aa08e78837?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80" alt="Engineer" className="rounded-3xl shadow-2xl" /> </div>
<div className="space-y-8"> <button onClick={() => setActivePage('about')} className="text-sm font-bold text-gray-400 hover:text-[#0284c7] transition-colors flex items-center group">
{[ Tudjon meg többet rólunk <ChevronRight className="w-4 h-4 ml-1 group-hover:translate-x-1 transition-transform" />
{ title: 'Szakértő Mérnökcsapat', text: 'Saját, magasan képzett mérnökeink tervezik meg rendszerét a maximális hatékonyság érdekében.' }, </button>
{ title: 'Gyors Kivitelezés', text: 'A szerződéskötéstől számított 30 napon belül telepítjük rendszerét.' }, </div>
{ title: 'Folyamatos Támogatás', text: 'Telepítés után sem engedjük el a kezét, távfelügyeletet és karbantartást biztosítunk.' } <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
].map((feat, i) => ( {[
<div key={i} className="flex gap-4"> { icon: Sun, title: 'Csúcskategóriás Panelek', desc: 'Csak Tier-1 besorolású, bizonyítottan tartós napelemeket használunk a legnagyobb hatásfokért.' },
<div className="w-8 h-8 rounded-full bg-[#0284c7] flex-shrink-0 flex items-center justify-center text-white font-bold mt-1"> { icon: Battery, title: 'Intelligens Tárolás', desc: 'Hibrid invertereink és akkumulátoros rendszereink révén akár éjszaka is tiszta energiát használhat.' },
{i + 1} { icon: Shield, title: '25 Év Teljes Biztonság', desc: 'Nemcsak a termékekre, hanem a munkavégzésre is kiemelkedő garanciális feltételeket biztosítunk.' }
</div> ].map((f, i) => (
<div> <div key={i} className="bg-white p-10 rounded-[32px] shadow-sm hover:shadow-xl transition-all group">
<h3 className="text-xl font-bold text-gray-900 mb-2">{feat.title}</h3> <div className="w-16 h-16 bg-sky-50 rounded-2xl flex items-center justify-center text-[#0284c7] mb-8 group-hover:bg-[#0284c7] group-hover:text-white transition-colors">
<p className="text-gray-600 leading-relaxed">{feat.text}</p> <f.icon className="w-8 h-8" />
</div> </div>
</div> <h3 className="text-xl font-black text-gray-900 mb-4 uppercase tracking-tighter">{f.title}</h3>
))} <p className="text-gray-500 text-sm leading-relaxed font-medium">{f.desc}</p>
<button onClick={() => setActivePage('about')} className="mt-4 text-[#0284c7] font-bold flex items-center hover:underline"> </div>
Tudjon meg többet rólunk <ArrowRight className="w-5 h-5 ml-2" /> ))}
</button> </div>
</div> </div>
</div>
</div>
</section> </section>
</> </>
)} )}
{/* SERVICES PAGE */} {/* --- SERVICES PAGE --- */}
{activePage === 'services' && ( {activePage === 'services' && (
<div className="py-20 bg-gray-50 min-h-screen"> <div className="py-24 bg-white min-h-screen px-4">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto">
<div className="text-center mb-20"> <div className="text-center mb-20">
<span className="text-[#0284c7] font-bold uppercase tracking-wider text-sm mb-2 block">Megoldásaink</span> <span className="text-[#0284c7] font-black uppercase tracking-[0.4em] text-xs mb-4 block">Szolgáltatások</span>
<h2 className="text-4xl md:text-5xl font-extrabold text-gray-900 mb-6">Minden igényre van válaszunk</h2> <h2 className="text-4xl md:text-6xl font-black text-gray-900 mb-8 tracking-tighter">Komplex Energetikai Megoldások</h2>
<p className="text-xl text-gray-600 max-w-3xl mx-auto">Legyen szó kis családi házról vagy hatalmas ipari létesítményről, mi megtaláljuk az optimális rendszert.</p> <p className="text-lg text-gray-500 max-w-3xl mx-auto font-medium leading-relaxed">Saját mérnöki csapattal, alvállalkozók nélkül végezzük a teljes kivitelezést.</p>
</div> </div>
<div className="grid lg:grid-cols-2 gap-16"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
{/* Residential */} <div className="bg-gray-900 rounded-[40px] overflow-hidden group shadow-2xl">
<div className="group bg-white rounded-3xl overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 border border-gray-100">
<div className="h-80 overflow-hidden relative"> <div className="h-80 overflow-hidden relative">
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/10 transition-colors z-10"></div> <img src="https://images.unsplash.com/photo-1613665813446-82a78c468a1d?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80" alt="Res" className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700 opacity-80" />
<img src="https://images.unsplash.com/photo-1613665813446-82a78c468a1d?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80" alt="Residential" className="w-full h-full object-cover transform group-hover:scale-110 transition-transform duration-700" /> <div className="absolute top-8 left-8 bg-white/10 backdrop-blur-md px-4 py-2 rounded-full border border-white/20 text-white text-[10px] font-black uppercase tracking-widest">Családi Házak</div>
<div className="absolute bottom-6 left-6 z-20">
<span className="bg-white px-4 py-1 rounded-full text-sm font-bold text-[#0284c7] mb-2 inline-block">Lakossági</span>
<h3 className="text-3xl font-bold text-white">Családi Házak</h3>
</div>
</div> </div>
<div className="p-10"> <div className="p-10 md:p-12">
<p className="text-gray-600 mb-8 text-lg leading-relaxed"> <h3 className="text-3xl font-black text-white mb-6 uppercase tracking-tighter">Lakossági Napelem</h3>
Csökkentse otthona energiafüggőségét és növelje ingatlana értékét. Rendszereink diszkrétek, esztétikusak és okosotthon-kompatibilisek. <p className="text-gray-400 mb-10 leading-relaxed font-medium">Optimalizálja otthona fenntartási költségeit. Teljes körű engedélyeztetés, H-tarifa ügyintézés és statikai tervezés.</p>
</p> <button onClick={() => setActivePage('contact')} className="w-full py-5 border-2 border-white/10 text-white font-black rounded-2xl hover:bg-white hover:text-gray-900 transition-all uppercase tracking-widest text-xs">
<div className="grid sm:grid-cols-2 gap-4 mb-8"> Kérjen lakossági ajánlatot
{['Rezsi nullázása', 'Hibrid Inverterek', 'Okos monitorozás', 'Elektromos autó töltés'].map((item, i) => (
<div key={i} className="flex items-center text-gray-700 font-medium">
<CheckCircle className="w-5 h-5 text-green-500 mr-3" /> {item}
</div>
))}
</div>
<button onClick={() => setActivePage('contact')} className="w-full py-4 border-2 border-[#0284c7] text-[#0284c7] font-bold rounded-xl hover:bg-[#0284c7] hover:text-white transition-all">
Ajánlatkérés Családi Házra
</button> </button>
</div> </div>
</div> </div>
{/* Industrial */} <div className="bg-[#0284c7] rounded-[40px] overflow-hidden group shadow-2xl">
<div className="group bg-white rounded-3xl overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 border border-gray-100">
<div className="h-80 overflow-hidden relative"> <div className="h-80 overflow-hidden relative">
<div className="absolute inset-0 bg-black/20 group-hover:bg-black/10 transition-colors z-10"></div> <img src="https://images.unsplash.com/photo-1624397640148-949b1732bb0a?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80" alt="Comm" className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700 opacity-80" />
<img src="https://images.unsplash.com/photo-1624397640148-949b1732bb0a?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80" alt="Commercial" className="w-full h-full object-cover transform group-hover:scale-110 transition-transform duration-700" /> <div className="absolute top-8 left-8 bg-white/20 backdrop-blur-md px-4 py-2 rounded-full border border-white/30 text-white text-[10px] font-black uppercase tracking-widest">Ipar & Mezőgazdaság</div>
<div className="absolute bottom-6 left-6 z-20">
<span className="bg-white px-4 py-1 rounded-full text-sm font-bold text-[#0284c7] mb-2 inline-block">Ipari</span>
<h3 className="text-3xl font-bold text-white">Vállalatok & Üzemek</h3>
</div>
</div> </div>
<div className="p-10"> <div className="p-10 md:p-12 text-white">
<p className="text-gray-600 mb-8 text-lg leading-relaxed"> <h3 className="text-3xl font-black mb-6 uppercase tracking-tighter">Vállalati Rendszerek</h3>
Optimalizálja vállalkozása működési költségeit. Nagy teljesítményű rendszerek, amelyek fedezik a gépek és üzemcsarnokok energiaigényét. <p className="text-sky-100 mb-10 leading-relaxed font-medium">Csökkentse cége rezsiköltségét ipari méretű naperőművekkel. Megtérülési számítások és pályázati tanácsadás professzionálisan.</p>
</p> <button onClick={() => setActivePage('contact')} className="w-full py-5 bg-white text-[#0284c7] font-black rounded-2xl hover:bg-gray-900 hover:text-white transition-all uppercase tracking-widest text-xs">
<div className="grid sm:grid-cols-2 gap-4 mb-8"> Ipari konzultáció kérése
{['Gyors megtérülés', '50kW - 5MW teljesítmény', 'ESG megfelelőség', 'Saját transzformátor'].map((item, i) => (
<div key={i} className="flex items-center text-gray-700 font-medium">
<CheckCircle className="w-5 h-5 text-green-500 mr-3" /> {item}
</div>
))}
</div>
<button onClick={() => setActivePage('contact')} className="w-full py-4 border-2 border-[#0284c7] text-[#0284c7] font-bold rounded-xl hover:bg-[#0284c7] hover:text-white transition-all">
Ipari Konzultáció Kérése
</button> </button>
</div> </div>
</div> </div>
@@ -291,138 +250,155 @@ export const BlueWave: React.FC = () => {
</div> </div>
)} )}
{/* ABOUT PAGE */} {/* --- BLOG PAGE --- */}
{activePage === 'about' && ( {activePage === 'blog' && (
<div className="py-20 bg-white"> <div className="py-24 bg-gray-50 min-h-screen px-4">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center"> <div className="max-w-7xl mx-auto">
<div className="inline-block p-3 rounded-full bg-sky-100 mb-6 text-[#0284c7]"> <div className="text-center mb-20">
<Sun className="w-8 h-8" /> <span className="text-[#0284c7] font-black uppercase tracking-[0.4em] text-xs mb-4 block">Tudástár</span>
<h2 className="text-4xl md:text-6xl font-black text-gray-900 tracking-tighter">Friss hírek & Cikkek</h2>
</div> </div>
<h2 className="text-4xl font-extrabold text-gray-900 mb-8">A BlueWave Küldetése</h2> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<p className="text-xl text-gray-700 leading-relaxed mb-12"> {[
A BlueWave Solar Kft. 2015-ben azzal a céllal alakult, hogy elérhetővé tegye a napenergiát mindenki számára. Hiszünk abban, hogy a fenntarthatóság nem luxus, hanem a jövő záloga. Csapatunk okleveles mérnökökből, pályázati szakértőkből és tapasztalt kivitelezőkből áll. { date: '2024.03.15', title: 'Új napelemes pályázatok: Mire számíthatunk?', img: 'https://images.unsplash.com/photo-1559302504-64aae6ca6b6d?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80' },
</p> { date: '2024.03.02', title: 'Hibrid vagy szigetüzemű rendszer? Segítünk dönteni.', img: 'https://images.unsplash.com/photo-1509391366360-2e959784a276?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80' },
{ date: '2024.02.20', title: 'Hogyan tartsuk karban napelemes rendszerünket?', img: 'https://images.unsplash.com/photo-1548550023-2bdb3c5beed7?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80' }
<div className="bg-gradient-to-br from-[#0f172a] to-[#1e293b] rounded-3xl p-12 text-white shadow-2xl mb-16 relative overflow-hidden"> ].map((post, i) => (
<div className="relative z-10 grid grid-cols-1 md:grid-cols-3 gap-12"> <article key={i} className="bg-white rounded-[32px] overflow-hidden shadow-sm hover:shadow-2xl transition-all group">
<div> <div className="h-60 overflow-hidden">
<div className="text-5xl font-bold text-[#38bdf8] mb-2">500+</div> <img src={post.img} alt={post.title} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" />
<div className="text-gray-400 font-medium uppercase tracking-wide text-sm">Telepített rendszer</div> </div>
</div> <div className="p-8">
<div> <time className="text-[10px] font-black text-[#0284c7] uppercase tracking-widest">{post.date}</time>
<div className="text-5xl font-bold text-[#38bdf8] mb-2">15MW</div> <h3 className="text-xl font-black text-gray-900 mt-3 mb-6 leading-tight uppercase tracking-tighter">{post.title}</h3>
<div className="text-gray-400 font-medium uppercase tracking-wide text-sm">Össz teljesítmény</div> <button className="flex items-center text-xs font-black text-gray-400 hover:text-[#0284c7] uppercase tracking-widest transition-colors">
</div> Tovább olvasom <ArrowRight className="w-4 h-4 ml-2" />
<div> </button>
<div className="text-5xl font-bold text-[#38bdf8] mb-2">100%</div> </div>
<div className="text-gray-400 font-medium uppercase tracking-wide text-sm">Ügyfél elégedettség</div> </article>
</div> ))}
</div>
{/* Background decorations */}
<div className="absolute top-0 right-0 w-64 h-64 bg-[#38bdf8] rounded-full filter blur-[100px] opacity-20"></div>
</div> </div>
</div>
</div>
)}
<div className="grid md:grid-cols-3 gap-8 text-left"> {/* --- ABOUT PAGE --- */}
<div className="bg-gray-50 p-8 rounded-2xl"> {activePage === 'about' && (
<h3 className="font-bold text-xl mb-3">Minőség</h3> <div className="py-24 bg-white min-h-screen px-4">
<p className="text-gray-600">Kizárólag minősített, prémium gyártók termékeit használjuk, hogy rendszere évtizedekig működjön.</p> <div className="max-w-5xl mx-auto">
<h2 className="text-4xl md:text-7xl font-black text-gray-900 mb-12 tracking-tighter uppercase leading-[0.9]">Több mint egy <br/><span className="text-[#0284c7]">kivitelező cég.</span></h2>
<div className="grid md:grid-cols-2 gap-16 items-center">
<div className="space-y-6">
<p className="text-lg text-gray-600 leading-relaxed font-medium">A BlueWave Solar azért jött létre, hogy a megújuló energiát elérhetővé, egyszerűvé és átláthatóvá tegye mindenki számára. Csapatunk több mint 10 éves tapasztalattal rendelkezik a villamosenergia-szektorban.</p>
<p className="text-lg text-gray-600 leading-relaxed font-medium">Saját mérnökeinkkel és telepítő csapatunkkal garantáljuk, hogy minden rendszerünk évtizedekig hibátlanul működjön. Számunkra nemcsak a panelek felrakása a cél, hanem egy fenntarthatóbb jövő építése.</p>
<div className="pt-10 flex gap-6">
<div className="p-4 bg-sky-50 rounded-2xl border border-sky-100">
<p className="text-2xl font-black text-[#0284c7]">10+</p>
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest">Év tapasztalat</p>
</div>
<div className="p-4 bg-sky-50 rounded-2xl border border-sky-100">
<p className="text-2xl font-black text-[#0284c7]">HU</p>
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest">Országos lefedettség</p>
</div>
</div>
</div> </div>
<div className="bg-gray-50 p-8 rounded-2xl"> <div className="rounded-[40px] overflow-hidden shadow-2xl">
<h3 className="font-bold text-xl mb-3">Innováció</h3> <img src="https://images.unsplash.com/photo-1521737604893-d14cc237f11d?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80" alt="Team" className="w-full h-full object-cover" />
<p className="text-gray-600">Folyamatos követjük a technológia fejlődését, hogy a legmodernebb megoldásokat kínálhassuk.</p>
</div>
<div className="bg-gray-50 p-8 rounded-2xl">
<h3 className="font-bold text-xl mb-3">Garancia</h3>
<p className="text-gray-600">A kivitelezésre és a termékekre is kiemelkedő garanciális feltételeket biztosítunk.</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
)} )}
{/* CONTACT PAGE */} {/* --- CONTACT PAGE --- */}
{activePage === 'contact' && ( {activePage === 'contact' && (
<div className="py-20 bg-[#f8fafc] min-h-screen"> <div className="py-20 bg-gray-50 min-h-screen px-4">
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-6xl mx-auto">
<div className="grid lg:grid-cols-5 gap-10 bg-white rounded-3xl shadow-xl overflow-hidden border border-gray-100"> <div className="grid grid-cols-1 lg:grid-cols-5 bg-white rounded-[48px] shadow-2xl overflow-hidden border border-gray-100">
{/* Left Panel */} {/* Contact Info Card */}
<div className="lg:col-span-2 bg-[#0284c7] p-10 text-white flex flex-col justify-between relative overflow-hidden"> <div className="lg:col-span-2 bg-[#0284c7] p-10 md:p-14 text-white flex flex-col justify-between relative overflow-hidden">
<div className="relative z-10"> <div className="relative z-10">
<h3 className="text-2xl font-bold mb-6">Lépjen velünk kapcsolatba</h3> <h3 className="text-3xl font-black mb-8 tracking-tighter uppercase">Keressen bizalommal</h3>
<p className="text-sky-100 mb-8"> <div className="space-y-8">
Töltse ki az űrlapot egy ingyenes, kötelezettségmentes előzetes kalkulációért. Mérnök kollégánk 24 órán belül keresni fogja. <div className="flex items-start gap-5">
</p> <div className="p-3 bg-white/10 rounded-xl"><Phone className="w-6 h-6" /></div>
<div className="space-y-6"> <div><p className="text-[10px] font-bold text-sky-200 uppercase tracking-widest mb-1">Hívjon minket</p><p className="text-lg font-bold">+36 30 999 8888</p></div>
<div className="flex items-center gap-4">
<Phone className="w-6 h-6 text-sky-200" />
<span className="font-medium">+36 30 999 8888</span>
</div> </div>
<div className="flex items-center gap-4"> <div className="flex items-start gap-5">
<Mail className="w-6 h-6 text-sky-200" /> <div className="p-3 bg-white/10 rounded-xl"><Mail className="w-6 h-6" /></div>
<span className="font-medium">info@bluewave-solar.demo</span> <div><p className="text-[10px] font-bold text-sky-200 uppercase tracking-widest mb-1">Írjon nekünk</p><p className="text-lg font-bold">info@bluewave-solar.hu</p></div>
</div> </div>
<div className="flex items-center gap-4"> <div className="flex items-start gap-5">
<Home className="w-6 h-6 text-sky-200" /> <div className="p-3 bg-white/10 rounded-xl"><MapPin className="w-6 h-6" /></div>
<span className="font-medium">1117 Budapest, Napelem u. 1.</span> <div><p className="text-[10px] font-bold text-sky-200 uppercase tracking-widest mb-1">Irodánk</p><p className="text-lg font-bold">1117 Budapest, Napelem u. 1.</p></div>
</div> </div>
</div> </div>
</div> </div>
<div className="relative z-10 mt-12">
<p className="text-sm text-sky-200 opacity-80"> <div className="mt-16 pt-10 border-t border-white/10 relative z-10">
Nyitvatartás: H-P 8:00 - 17:00 <div className="flex gap-4">
</p> <button className="w-12 h-12 bg-white/10 rounded-full flex items-center justify-center hover:bg-white/20 transition-all"><Share2 className="w-5 h-5" /></button>
<button className="w-12 h-12 bg-white/10 rounded-full flex items-center justify-center hover:bg-white/20 transition-all"><Play className="w-5 h-5" /></button>
</div>
</div> </div>
{/* Circle decorations */}
<div className="absolute -bottom-10 -right-10 w-48 h-48 bg-sky-500 rounded-full opacity-50"></div> {/* Decorative elements */}
<div className="absolute top-10 right-10 w-20 h-20 bg-sky-400 rounded-full opacity-30"></div> <div className="absolute -bottom-20 -right-20 w-64 h-64 bg-sky-500 rounded-full opacity-30 blur-3xl"></div>
</div> </div>
{/* Right Panel - Form */} {/* FORM SECTION */}
<div className="lg:col-span-3 p-10"> <div className="lg:col-span-3 p-10 md:p-14 bg-[#0f172a]">
<h2 className="text-2xl font-bold text-gray-900 mb-6">Ingyenes Ajánlatkérés</h2> <h2 className="text-2xl md:text-3xl font-black text-white mb-10 tracking-tighter uppercase">Ajánlatkérés</h2>
<form className="space-y-6"> <form className="space-y-6">
<div className="grid md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div> <div>
<label className="block text-sm font-semibold text-gray-700 mb-2">Teljes Név</label> <label className="block text-[10px] font-black text-gray-400 uppercase tracking-widest mb-2 ml-1">Teljes Név</label>
<input type="text" className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:ring-2 focus:ring-[#0284c7] focus:border-transparent outline-none transition-all bg-gray-50 focus:bg-white text-gray-900" placeholder="Kovács János" /> <input type="text" className="w-full px-5 py-4 rounded-2xl border-none bg-white text-black font-bold focus:ring-4 focus:ring-[#0ea5e9]/30 outline-none transition-all placeholder:text-gray-300" placeholder="Kovács János" />
</div> </div>
<div> <div>
<label className="block text-sm font-semibold text-gray-700 mb-2">Telefonszám</label> <label className="block text-[10px] font-black text-gray-400 uppercase tracking-widest mb-2 ml-1">Telefonszám</label>
<input type="tel" className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:ring-2 focus:ring-[#0284c7] focus:border-transparent outline-none transition-all bg-gray-50 focus:bg-white text-gray-900" placeholder="+36 30 123 4567" /> <input type="tel" className="w-full px-5 py-4 rounded-2xl border-none bg-white text-black font-bold focus:ring-4 focus:ring-[#0ea5e9]/30 outline-none transition-all placeholder:text-gray-300" placeholder="+36 30 ..." />
</div> </div>
</div> </div>
<div>
<label className="block text-sm font-semibold text-gray-700 mb-2">Email Cím</label>
<input type="email" className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:ring-2 focus:ring-[#0284c7] focus:border-transparent outline-none transition-all bg-gray-50 focus:bg-white text-gray-900" placeholder="janos@pelda.hu" />
</div>
<div className="p-6 bg-sky-50 rounded-xl border border-sky-100"> <div className="p-6 md:p-8 bg-[#1e293b] rounded-[32px] border border-gray-800 space-y-6">
<div className="flex items-center gap-2 mb-4 text-[#0284c7] font-bold"> <div className="flex items-center gap-3 text-[#38bdf8] font-black text-xs uppercase tracking-widest">
<Calculator className="w-5 h-5" /> Gyors Kalkulátor Adatok <Calculator className="w-5 h-5" /> Villám Kalkulátor
</div> </div>
<div className="grid md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div> <div>
<label className="block text-sm font-semibold text-gray-700 mb-2">Havi villanyszámla (kb.)</label> <label className="block text-[10px] font-black text-gray-400 uppercase tracking-widest mb-2 ml-1">Havi villanyszámla (Ft)</label>
<input type="number" className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:ring-2 focus:ring-[#0284c7] outline-none bg-white text-gray-900" placeholder="Pl: 25000" /> <input type="number" className="w-full px-5 py-4 rounded-2xl border-none bg-white text-black font-bold placeholder:text-gray-300" placeholder="Pl: 15.000" />
</div> </div>
<div> <div>
<label className="block text-sm font-semibold text-gray-700 mb-2">Telepítés Helyszíne</label> <label className="block text-[10px] font-black text-gray-400 uppercase tracking-widest mb-2 ml-1">Helyszín</label>
<input type="text" className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:ring-2 focus:ring-[#0284c7] outline-none bg-white text-gray-900" placeholder="Város / Irányítószám" /> <input type="text" className="w-full px-5 py-4 rounded-2xl border-none bg-white text-black font-bold placeholder:text-gray-300" placeholder="Irányítószám / Város" />
</div> </div>
</div> </div>
</div> </div>
<div className="pt-2"> <div className="pt-4">
<button type="button" className="w-full bg-[#0284c7] hover:bg-[#0369a1] text-white font-bold py-4 rounded-xl transition-all shadow-lg hover:shadow-xl transform hover:-translate-y-1"> <button type="button" className="w-full bg-[#0284c7] hover:bg-white hover:text-gray-900 text-white font-black py-6 rounded-2xl shadow-2xl transition-all active:scale-95 uppercase tracking-[0.2em] text-xs">
Díjmentes Kalkuláció Kérése Ingyenes Kalkuláció Kérése
</button> </button>
<p className="text-center text-xs text-gray-500 mt-4"> <p className="text-center text-gray-500 text-[10px] mt-6 font-bold uppercase tracking-widest">Kollégánk 24 órán belül keresni fogja Önt.</p>
Az ajánlatkérés nem jár kötelezettséggel. Adatvédelmi irányelveinket elfogadom.
</p>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
{/* Google Map Placeholder */}
<div className="mt-12 bg-white rounded-[40px] overflow-hidden h-[400px] shadow-sm border border-gray-100 relative group">
<div className="absolute inset-0 bg-gray-200 flex items-center justify-center overflow-hidden">
<img src="https://images.unsplash.com/photo-1526778548025-fa2f459cd5c1?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80" alt="Map" className="w-full h-full object-cover opacity-50 grayscale group-hover:grayscale-0 transition-all duration-700" />
<div className="absolute inset-0 bg-sky-900/10 group-hover:bg-transparent transition-all"></div>
<div className="relative z-10 bg-white p-6 rounded-3xl shadow-2xl text-center border border-gray-100">
<MapPin className="w-10 h-10 text-[#0284c7] mx-auto mb-3" />
<p className="font-black text-gray-900 uppercase tracking-widest text-xs">Interaktív Térkép</p>
<p className="text-[10px] text-gray-400 font-bold mt-1">1117 BUDAPEST, NAPELEM U. 1.</p>
</div>
</div>
</div>
</div> </div>
</div> </div>
)} )}
@@ -431,44 +407,62 @@ export const BlueWave: React.FC = () => {
</main> </main>
{/* Footer */} {/* Footer */}
<footer className="bg-[#0f172a] text-white py-16 border-t border-gray-800"> <footer className="bg-gray-900 text-white py-20 border-t border-gray-800 px-4">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto">
<div className="grid md:grid-cols-4 gap-12 mb-12"> <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-16">
<div className="col-span-1 md:col-span-2"> <div className="sm:col-span-2">
<div className="flex items-center mb-6"> <div className="flex items-center mb-8">
<div className="bg-gradient-to-tr from-[#0284c7] to-[#0ea5e9] p-2 rounded-lg mr-3"> <div className="bg-gradient-to-tr from-[#0284c7] to-[#0ea5e9] p-3 rounded-2xl mr-4">
<Sun className="w-6 h-6 text-white" /> <Sun className="w-6 h-6 text-white" />
</div> </div>
<span className="text-2xl font-bold">BlueWave<span className="text-[#38bdf8]">Solar</span></span> <span className="text-2xl font-black uppercase tracking-tighter">BlueWave<span className="text-[#38bdf8]">Solar</span></span>
</div> </div>
<p className="text-gray-400 max-w-sm leading-relaxed"> <p className="text-gray-400 max-w-sm text-sm leading-relaxed font-medium mb-10">
Magyarország vezető napenergia szolgáltatója. Célunk, hogy ügyfeleink számára energiafüggetlenséget és fenntartható jövőt biztosítsunk. A jövő energiája ma kezdődik. Segítünk elszakadni a hálózati függőségtől és csökkenteni ökológiai lábnyomát professzionális technológiával.
</p> </p>
<div className="flex gap-4">
<div className="w-10 h-10 rounded-full bg-gray-800 flex items-center justify-center hover:bg-[#0284c7] transition-all cursor-pointer"><FacebookIcon className="w-4 h-4" /></div>
<div className="w-10 h-10 rounded-full bg-gray-800 flex items-center justify-center hover:bg-[#0284c7] transition-all cursor-pointer"><InstagramIcon className="w-4 h-4" /></div>
</div>
</div> </div>
<div> <div>
<h4 className="font-bold text-lg mb-6 text-white">Navigáció</h4> <h4 className="font-black text-xs mb-8 text-white uppercase tracking-[0.3em]">Navigáció</h4>
<ul className="space-y-3 text-gray-400"> <ul className="space-y-4 text-xs font-bold text-gray-500 uppercase tracking-widest">
<li onClick={() => setActivePage('home')} className="cursor-pointer hover:text-[#38bdf8] transition-colors">Főoldal</li> <li onClick={() => setActivePage('home')} className="cursor-pointer hover:text-white transition-colors">Főoldal</li>
<li onClick={() => setActivePage('services')} className="cursor-pointer hover:text-[#38bdf8] transition-colors">Megoldások</li> <li onClick={() => setActivePage('services')} className="cursor-pointer hover:text-white transition-colors">Megoldások</li>
<li onClick={() => setActivePage('about')} className="cursor-pointer hover:text-[#38bdf8] transition-colors">Rólunk</li> <li onClick={() => setActivePage('blog')} className="cursor-pointer hover:text-white transition-colors">Blog</li>
<li onClick={() => setActivePage('contact')} className="cursor-pointer hover:text-[#38bdf8] transition-colors">Kapcsolat</li> <li onClick={() => setActivePage('contact')} className="cursor-pointer hover:text-white transition-colors">Kapcsolat</li>
</ul> </ul>
</div> </div>
<div> <div>
<h4 className="font-bold text-lg mb-6 text-white">Kapcsolat</h4> <h4 className="font-black text-xs mb-8 text-white uppercase tracking-[0.3em]">Kapcsolat</h4>
<div className="space-y-3 text-gray-400"> <ul className="space-y-4 text-xs font-bold text-gray-500">
<p>1117 Budapest, Napelem u. 1.</p> <li className="flex items-center gap-3"><MapPin className="w-4 h-4 text-[#38bdf8]" /> 1117 Budapest, Napelem u. 1.</li>
<p>+36 30 999 8888</p> <li className="flex items-center gap-3"><Phone className="w-4 h-4 text-[#38bdf8]" /> +36 30 999 8888</li>
<p>info@bluewave-solar.demo</p> <li className="flex items-center gap-3"><Mail className="w-4 h-4 text-[#38bdf8]" /> info@bluewave-solar.hu</li>
</div> </ul>
</div> </div>
</div> </div>
<div className="border-t border-gray-800 pt-8 flex flex-col md:flex-row justify-between items-center text-gray-500 text-sm"> <div className="border-t border-gray-800 mt-20 pt-10 flex flex-col md:flex-row justify-between items-center gap-6">
<p>&copy; 2024 BlueWave Solar Kft. Minden jog fenntartva.</p> <p className="text-gray-600 text-[10px] font-bold uppercase tracking-widest">&copy; 2024 BlueWave Solar Kft. Minden jog fenntartva.</p>
<p>Demonstrációs weboldal - MotionWeb Pro csomag</p> <div className="flex gap-8 text-[10px] font-bold text-gray-600 uppercase tracking-widest">
<span className="hover:text-white cursor-pointer transition-colors">Adatvédelem</span>
<span className="hover:text-white cursor-pointer transition-colors">ÁSZF</span>
</div>
</div> </div>
</div> </div>
</footer> </footer>
</div> </div>
); );
}; };
// Internal social icons to avoid extra lucide-react dependency issues in demo
const Shield = ({ className }: { className?: string }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
);
const FacebookIcon = ({ className }: { className?: string }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"/></svg>
);
const InstagramIcon = ({ className }: { className?: string }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><rect width="20" height="20" x="2" y="2" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" x2="17.51" y1="6.5" y2="6.5"/></svg>
);

View File

@@ -1,428 +1,420 @@
import React, { useEffect, useState } from 'react';
import { ArrowLeft, Shield, Lock, Eye, Server, Cpu, Globe, ChevronDown, PlayCircle, Fingerprint, Scan, Activity, Radio, Terminal, Box, Building2, Users, MapPin } from 'lucide-react'; import React, { useEffect, useState, useRef } from 'react';
import {
ArrowLeft, Shield, Lock, Eye, Server, Cpu, Globe,
ChevronRight, PlayCircle, Fingerprint, Scan, Activity,
Radio, Terminal, Box, Building2, Users, MapPin,
Menu, X, Zap, ShieldCheck, AlertCircle, Cpu as Chip,
Network, Database, HardDrive, ShieldAlert, Key,
ArrowRight, ShieldCheck as Verified, Loader2
} from 'lucide-react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
export const Steelguard: React.FC = () => { export const Steelguard: React.FC = () => {
const [scrolled, setScrolled] = useState(false); const [scrolled, setScrolled] = useState(false);
const [activeTab, setActiveTab] = useState<'home' | 'solutions' | 'hardware' | 'sectors' | 'company'>('home'); const [activePage, setActivePage] = useState<'home' | 'solutions' | 'hardware' | 'security'>('home');
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
// Hero Scanner State
const [isHovered, setIsHovered] = useState(false);
const [isIdentified, setIsIdentified] = useState(false);
const [randomData, setRandomData] = useState({ temp: '32.4', loss: '0.00', nodes: '1248' });
// Fix: Use ReturnType<typeof setTimeout> instead of NodeJS.Timeout to avoid namespace errors in browser environment
const scanTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
// Fix: Use ReturnType<typeof setInterval> instead of NodeJS.Timeout to avoid namespace errors in browser environment
const dataIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
useEffect(() => { useEffect(() => {
const handleScroll = () => setScrolled(window.scrollY > 20); const handleScroll = () => setScrolled(window.scrollY > 20);
window.addEventListener('scroll', handleScroll); window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll);
}, []); }, []);
// Reset scroll when changing tabs // Handle Scanning Logic
useEffect(() => { useEffect(() => {
window.scrollTo({ top: 0, behavior: 'smooth' }); if (isHovered) {
}, [activeTab]); // Start randomizing data
dataIntervalRef.current = setInterval(() => {
setRandomData({
temp: (Math.random() * 5 + 30).toFixed(1),
loss: (Math.random() * 0.5).toFixed(2),
nodes: Math.floor(Math.random() * 50 + 1200).toString()
});
}, 80);
// Set identification timeout
scanTimerRef.current = setTimeout(() => {
setIsIdentified(true);
if (dataIntervalRef.current) clearInterval(dataIntervalRef.current);
}, 1000);
} else {
// Reset
if (scanTimerRef.current) clearTimeout(scanTimerRef.current);
if (dataIntervalRef.current) clearInterval(dataIntervalRef.current);
setIsIdentified(false);
setRandomData({ temp: '32.4', loss: '0.00', nodes: '1248' });
}
return () => {
if (scanTimerRef.current) clearTimeout(scanTimerRef.current);
if (dataIntervalRef.current) clearInterval(dataIntervalRef.current);
};
}, [isHovered]);
const navItems = [
{ id: 'home', label: 'Rendszer' },
{ id: 'solutions', label: 'Megoldások' },
{ id: 'hardware', label: 'Hardver' },
{ id: 'security', label: 'Biztonság' }
];
return ( return (
<div className="font-sans bg-[#020205] text-gray-100 min-h-screen selection:bg-cyan-500 selection:text-black overflow-x-hidden relative"> <div className="font-sans bg-[#020205] text-gray-100 min-h-screen selection:bg-cyan-500 selection:text-black overflow-x-hidden relative">
{/* INJECTED STYLES FOR ADVANCED ANIMATIONS */}
<style>{` <style>{`
@keyframes grid-move { @keyframes grid-move {
0% { transform: perspective(500px) rotateX(60deg) translateY(0); } 0% { transform: perspective(800px) rotateX(60deg) translateY(0); }
100% { transform: perspective(500px) rotateX(60deg) translateY(40px); } 100% { transform: perspective(800px) rotateX(60deg) translateY(50px); }
} }
@keyframes scanline { @keyframes scanline {
0% { transform: translateY(-100%); } 0% { transform: translateY(-100%); opacity: 0; }
100% { transform: translateY(100%); } 50% { opacity: 1; }
100% { transform: translateY(100%); opacity: 0; }
} }
@keyframes blob { @keyframes pulse-slow {
0% { transform: translate(0px, 0px) scale(1); } 0%, 100% { opacity: 0.3; transform: scale(1); }
33% { transform: translate(30px, -50px) scale(1.1); } 50% { opacity: 0.6; transform: scale(1.05); }
66% { transform: translate(-20px, 20px) scale(0.9); }
100% { transform: translate(0px, 0px) scale(1); }
} }
@keyframes pulse-glow { .cyber-grid {
0%, 100% { box-shadow: 0 0 10px rgba(6, 182, 212, 0.2); } background-image:
50% { box-shadow: 0 0 25px rgba(6, 182, 212, 0.6); } linear-gradient(to right, rgba(6, 182, 212, 0.1) 1px, transparent 1px),
linear-gradient(to bottom, rgba(6, 182, 212, 0.1) 1px, transparent 1px);
background-size: 50px 50px;
mask-image: radial-gradient(circle, black, transparent 80%);
} }
.text-glow:hover { .glass-card {
text-shadow: 0 0 10px rgba(34, 211, 238, 0.8), 0 0 20px rgba(34, 211, 238, 0.4); background: rgba(10, 15, 30, 0.4);
backdrop-filter: blur(15px);
border: 1px solid rgba(6, 182, 212, 0.15);
box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.5);
} }
.animate-grid-move { .text-glow {
animation: grid-move 2s linear infinite; text-shadow: 0 0 15px rgba(34, 211, 238, 0.8), 0 0 30px rgba(34, 211, 238, 0.4);
} }
.animate-blob { .neon-glow-btn:hover {
animation: blob 10s infinite; box-shadow: 0 0 25px rgba(34, 211, 238, 0.6), 0 0 50px rgba(34, 211, 238, 0.2);
transform: translateY(-2px);
} }
.animation-delay-2000 { .button-clip {
animation-delay: 2s;
}
.animation-delay-4000 {
animation-delay: 4s;
}
.glass-panel {
background: rgba(10, 15, 30, 0.6);
backdrop-filter: blur(12px);
border: 1px solid rgba(6, 182, 212, 0.1);
box-shadow: 0 0 15px rgba(0,0,0,0.5);
}
.cyber-button {
position: relative;
overflow: hidden;
transition: all 0.3s;
}
.cyber-button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: 0.5s;
}
.cyber-button:hover::before {
left: 100%;
}
.clip-path-polygon {
clip-path: polygon(10% 0, 100% 0, 100% 70%, 90% 100%, 0 100%, 0 30%); clip-path: polygon(10% 0, 100% 0, 100% 70%, 90% 100%, 0 100%, 0 30%);
} }
`}</style> `}</style>
{/* Return to Main Site */} {/* Back to Reality Button */}
<div className="fixed bottom-6 right-6 z-[60] mix-blend-difference"> <div className="fixed bottom-4 right-4 md:bottom-8 md:right-8 z-[60]">
<Link to="/#references"> <Link to="/#references">
<button className="bg-white text-black px-6 py-2 rounded-sm uppercase text-[10px] font-bold tracking-[0.3em] hover:bg-cyan-500 hover:text-white transition-all duration-300 flex items-center group"> <button className="bg-white/10 backdrop-blur-xl border border-white/20 text-white px-5 py-2.5 rounded-full text-[10px] font-black tracking-[0.2em] hover:bg-white hover:text-black transition-all flex items-center shadow-2xl group">
<ArrowLeft className="w-3 h-3 mr-3 group-hover:-translate-x-1 transition-transform" /> BACK TO REALITY <ArrowLeft className="w-4 h-4 mr-2 group-hover:-translate-x-1 transition-transform" /> VISSZA A PORTFÓLIÓHOZ
</button> </button>
</Link> </Link>
</div> </div>
{/* Enterprise Navbar */} {/* Animated Background */}
<nav className={`fixed w-full z-40 transition-all duration-500 border-b ${scrolled ? 'bg-[#050505]/80 backdrop-blur-xl border-cyan-900/30 py-2' : 'bg-transparent border-transparent py-6'}`}> <div className="fixed inset-0 z-0 pointer-events-none">
<div className="max-w-[1600px] mx-auto px-8 flex items-center justify-between"> <div className="absolute top-0 left-1/2 -translate-x-1/2 w-full h-[1000px] cyber-grid animate-[grid-move_10s_linear_infinite]"></div>
<div className="flex items-center gap-4 group cursor-pointer" onClick={() => setActiveTab('home')}> <div className="absolute top-[10%] left-[20%] w-[500px] h-[500px] bg-cyan-900/20 blur-[120px] rounded-full animate-pulse-slow"></div>
<div className="absolute bottom-[10%] right-[10%] w-[600px] h-[600px] bg-blue-900/10 blur-[150px] rounded-full animate-pulse-slow" style={{ animationDelay: '2s' }}></div>
</div>
{/* Navbar */}
<nav className={`fixed w-full z-50 transition-all duration-700 border-b ${scrolled ? 'bg-[#020205]/90 backdrop-blur-2xl border-cyan-500/20 py-2 shadow-[0_10px_30px_rgba(0,0,0,0.5)]' : 'bg-transparent border-transparent py-6'}`}>
<div className="max-w-[1400px] mx-auto px-6 md:px-12 flex items-center justify-between">
<div className="flex items-center gap-4 cursor-pointer group" onClick={() => setActivePage('home')}>
<div className="relative"> <div className="relative">
<div className="absolute inset-0 bg-cyan-500 blur-md opacity-20 group-hover:opacity-60 transition-opacity duration-500 animate-pulse"></div> <div className="absolute inset-0 bg-cyan-500 blur-lg opacity-30 group-hover:opacity-80 transition-opacity"></div>
<div className="w-10 h-10 bg-[#0a0a0a] border border-cyan-500/50 flex items-center justify-center relative z-10 clip-path-polygon group-hover:border-cyan-400 transition-colors"> <div className="w-10 h-10 md:w-12 md:h-12 bg-gray-900 border border-cyan-500/50 flex items-center justify-center relative z-10 rounded-xl overflow-hidden group-hover:shadow-[0_0_20px_rgba(34,211,238,0.5)] transition-shadow">
<Shield className="text-cyan-400 w-5 h-5" /> <Shield className="text-cyan-400 w-5 h-5 md:w-6 md:h-6" />
<div className="absolute inset-0 bg-gradient-to-t from-cyan-500/20 to-transparent"></div>
</div> </div>
</div> </div>
<div className="flex flex-col text-left"> <div className="flex flex-col">
<span className="text-2xl font-bold tracking-tighter text-white font-mono group-hover:text-cyan-400 transition-colors">STEELGUARD</span> <span className="text-xl md:text-2xl font-black tracking-tighter text-white font-mono uppercase">Steelguard</span>
<div className="flex items-center gap-2"> <span className="text-[8px] text-cyan-600 tracking-[0.4em] uppercase font-bold">Enterprise Defense</span>
<div className="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></div>
<span className="text-[9px] text-cyan-600 tracking-[0.4em] uppercase">Systems Online</span>
</div>
</div> </div>
</div> </div>
<div className="hidden lg:flex items-center space-x-12 text-[10px] font-bold tracking-[0.2em] text-gray-500 font-mono"> <div className="hidden lg:flex items-center space-x-2 font-mono">
{[ {navItems.map((item) => (
{ id: 'solutions', label: 'Solutions' },
{ id: 'hardware', label: 'Hardware' },
{ id: 'sectors', label: 'Sectors' },
{ id: 'company', label: 'Company' }
].map((item) => (
<button <button
key={item.id} key={item.id}
onClick={() => setActiveTab(item.id as any)} onClick={() => setActivePage(item.id as any)}
className={`transition-all relative group py-2 uppercase ${activeTab === item.id ? 'text-cyan-400' : 'hover:text-cyan-400'}`} className={`px-5 py-2 rounded-lg text-[11px] font-black tracking-widest uppercase transition-all ${activePage === item.id ? 'text-cyan-400 bg-cyan-400/5 shadow-[0_0_20px_rgba(34,211,238,0.2)]' : 'text-gray-500 hover:text-gray-200'}`}
> >
<span className={`text-cyan-800 transition-opacity ${activeTab === item.id ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'} mr-1`}>&lt;</span>
{item.label} {item.label}
<span className={`text-cyan-800 transition-opacity ${activeTab === item.id ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'} ml-1`}>/&gt;</span>
<span className={`absolute bottom-0 left-0 h-[1px] bg-cyan-500 transition-all duration-300 shadow-[0_0_10px_#06b6d4] ${activeTab === item.id ? 'w-full' : 'w-0 group-hover:w-full'}`}></span>
</button> </button>
))} ))}
<div className="h-4 w-px bg-gray-800 mx-4"></div>
<button className="bg-cyan-600 hover:bg-cyan-500 text-black px-6 py-2.5 rounded-lg text-[10px] font-black uppercase tracking-widest transition-all shadow-lg shadow-cyan-900/20 active:scale-95 hover:shadow-[0_0_30px_rgba(34,211,238,0.7)]">
Rendszer Belépés
</button>
</div> </div>
<div className="flex items-center gap-6"> <button onClick={() => setMobileMenuOpen(!mobileMenuOpen)} className="lg:hidden p-2 text-cyan-400">
<button onClick={() => setActiveTab('home')} className="text-[10px] font-bold text-gray-500 hover:text-white uppercase tracking-[0.2em] hidden sm:block transition-colors border border-transparent hover:border-gray-800 px-4 py-2"> {mobileMenuOpen ? <X /> : <Menu />}
Login_Portal </button>
</button>
<button className="cyber-button bg-cyan-600 hover:bg-cyan-500 text-black px-8 py-3 text-[10px] font-bold uppercase tracking-[0.2em] transition-all shadow-[0_0_20px_rgba(8,145,178,0.4)] hover:shadow-[0_0_30px_rgba(6,182,212,0.6)]">
Initialize
</button>
</div>
</div> </div>
</nav> </nav>
{/* Main Content Router Simulation */} {/* Main Content */}
<main className="animate-fade-in"> <main className="relative z-10 pt-20">
{/* HOME VIEW */} {activePage === 'home' && (
{activeTab === 'home' && (
<> <>
<header className="relative h-screen flex items-center justify-center overflow-hidden bg-[#020205]"> {/* Hero Section */}
<div className="absolute inset-0 z-0 overflow-hidden pointer-events-none"> <header className="min-h-screen flex items-center px-6 md:px-12 max-w-[1400px] mx-auto pt-10">
<div className="absolute top-[-10%] left-[-10%] w-[600px] h-[600px] bg-blue-900/20 rounded-full mix-blend-screen filter blur-[80px] opacity-30 animate-blob"></div> <div className="grid lg:grid-cols-2 gap-16 items-center">
<div className="absolute top-[20%] right-[-20%] w-[500px] h-[500px] bg-cyan-900/20 rounded-full mix-blend-screen filter blur-[80px] opacity-30 animate-blob animation-delay-2000"></div> <div className="text-center lg:text-left space-y-8">
<div className="absolute bottom-[-20%] left-[20%] w-[600px] h-[600px] bg-purple-900/10 rounded-full mix-blend-screen filter blur-[80px] opacity-30 animate-blob animation-delay-4000"></div> <div className="inline-flex items-center gap-3 px-4 py-1.5 border border-cyan-500/30 bg-cyan-950/20 text-cyan-400 text-[10px] font-bold tracking-[0.3em] uppercase rounded-full backdrop-blur-md">
<div className="absolute inset-0 bg-[linear-gradient(rgba(255,255,255,0.02)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.02)_1px,transparent_1px)] bg-[size:50px_50px]"></div>
<div className="absolute inset-0 bg-gradient-to-t from-[#020205] via-transparent to-transparent"></div>
<div className="absolute inset-0 bg-gradient-to-b from-[#020205] via-transparent to-transparent"></div>
</div>
<div className="relative z-10 max-w-[1400px] mx-auto px-6 grid lg:grid-cols-2 gap-20 items-center mt-20">
<div>
<div className="inline-flex items-center gap-3 px-4 py-2 border border-cyan-500/30 bg-cyan-900/10 text-cyan-400 text-[10px] font-bold tracking-[0.3em] mb-10 animate-fade-in-up backdrop-blur-md">
<Terminal className="w-3 h-3" /> <Terminal className="w-3 h-3" />
<span className="animate-pulse">ESTABLISHING SECURE CONNECTION...</span> <span className="animate-pulse">Rendszer állapota: Aktív</span>
</div> </div>
<h1 className="text-6xl lg:text-8xl font-bold text-white leading-[0.9] mb-8 font-mono animate-fade-in-up" style={{animationDelay: '0.1s'}}>
TOTAL <br/> <h1 className="text-5xl md:text-8xl font-black text-white leading-[0.85] tracking-tighter uppercase font-mono italic">
<span className="text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-blue-500 to-purple-600 drop-shadow-[0_0_15px_rgba(6,182,212,0.5)]">DEFENSE</span> Abszolút <br/>
<span className="text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-blue-500 to-purple-600 drop-shadow-2xl">Digitális</span> <br/>
Pajzs
</h1> </h1>
<p className="text-lg text-gray-400 max-w-lg mb-12 leading-relaxed animate-fade-in-up border-l-2 border-cyan-900/50 pl-6" style={{animationDelay: '0.2s'}}>
Advanced AI-driven security architecture for enterprise infrastructure. <span className="text-cyan-400 font-bold">Zero-trust protocols</span> and predictive threat neutralization active. <p className="text-sm md:text-xl text-gray-400 max-w-xl mx-auto lg:mx-0 font-medium leading-relaxed">
Kvantumszintű titkosítás és mesterséges intelligencia alapú fenyegetés-elemzés nagyvállalati környezetre tervezve. <span className="text-cyan-400 font-bold text-glow">Zero-Trust</span> architektúra a teljes biztonságért.
</p> </p>
<div className="flex flex-wrap gap-6 animate-fade-in-up" style={{animationDelay: '0.3s'}}>
<button onClick={() => setActiveTab('solutions')} className="cyber-button bg-white text-black hover:bg-cyan-50 px-10 py-4 text-xs font-bold uppercase tracking-[0.2em] flex items-center gap-4 transition-all hover:pr-12 group shadow-[0_0_20px_rgba(255,255,255,0.3)]"> <div className="flex flex-col sm:flex-row justify-center lg:justify-start gap-5">
Execute Protocol <ChevronDown className="w-4 h-4 group-hover:translate-y-1 transition-transform" /> <button className="bg-white text-black px-10 py-5 font-black uppercase tracking-[0.2em] text-xs button-clip hover:bg-cyan-400 transition-all shadow-xl shadow-white/10 neon-glow-btn">
Rendszer Indítása
</button> </button>
<button className="border border-gray-800 hover:border-cyan-500 text-gray-300 hover:text-cyan-400 px-10 py-4 text-xs font-bold uppercase tracking-[0.2em] flex items-center gap-4 transition-all bg-[#0a0a0a]/50 backdrop-blur-sm group hover:shadow-[0_0_15px_rgba(6,182,212,0.3)]"> <button className="border border-cyan-500/30 bg-cyan-500/5 text-cyan-400 px-10 py-5 font-black uppercase tracking-[0.2em] text-xs button-clip hover:bg-cyan-500/20 transition-all hover:shadow-[0_0_20px_rgba(34,211,238,0.3)]">
<PlayCircle className="w-4 h-4 group-hover:scale-110 transition-transform" /> Simulation Technikai Specifikáció
</button> </button>
</div> </div>
<div className="pt-10 flex flex-wrap justify-center lg:justify-start gap-8 opacity-40">
<div className="flex items-center gap-2 font-mono text-[10px] font-bold uppercase tracking-widest"><ShieldCheck className="w-4 h-4" /> ISO 27001 Certified</div>
<div className="flex items-center gap-2 font-mono text-[10px] font-bold uppercase tracking-widest"><Lock className="w-4 h-4" /> 256-bit AES</div>
<div className="flex items-center gap-2 font-mono text-[10px] font-bold uppercase tracking-widest"><Chip className="w-4 h-4" /> hardware-Encrypted</div>
</div>
</div> </div>
<div className="relative hidden lg:block animate-fade-in perspective-1000" style={{animationDelay: '0.5s'}}> {/* HERO INTERACTIVE SCANNER */}
<div className="relative w-full aspect-square flex items-center justify-center transform-style-3d rotate-y-12"> <div className="relative hidden lg:block group/hero"
<div className="absolute w-[80%] h-[80%] border border-cyan-900/40 rounded-full animate-[spin_20s_linear_infinite] shadow-[0_0_30px_rgba(6,182,212,0.1)]"></div> onMouseEnter={() => setIsHovered(true)}
<div className="absolute w-[60%] h-[60%] border-2 border-dashed border-cyan-500/20 rounded-full animate-[spin_15s_linear_infinite_reverse]"></div> onMouseLeave={() => setIsHovered(false)}>
<div className="relative z-10 w-[70%] h-[70%] rounded-2xl overflow-hidden border border-cyan-500/30 group shadow-[0_0_50px_rgba(6,182,212,0.15)]"> <div className={`glass-card rounded-[40px] aspect-square flex items-center justify-center p-12 relative overflow-hidden transition-all duration-700 border-2 ${isIdentified ? 'border-green-500 shadow-[0_0_60px_rgba(34,197,94,0.3)]' : 'border-cyan-500/20 shadow-[0_0_30px_rgba(34,211,238,0.05)]'}`}>
<img src="https://images.unsplash.com/photo-1550751827-4bd374c3f58b?auto=format&fit=crop&w=1000&q=80" alt="Tech Visual" className="w-full h-full object-cover opacity-60 mix-blend-luminosity group-hover:scale-105 transition-transform duration-1000 grayscale" />
<div className="absolute inset-0 bg-cyan-900/20 mix-blend-overlay"></div> <div className={`absolute inset-0 bg-gradient-to-br transition-colors duration-700 ${isIdentified ? 'from-green-500/10' : 'from-cyan-500/10'} to-transparent`}></div>
<div className="absolute top-0 left-0 w-full h-[2px] bg-cyan-400 shadow-[0_0_20px_#22d3ee] animate-[scanline_3s_linear_infinite]"></div>
</div> {/* Interactive Scanning Line */}
<div className="absolute top-20 -right-10 glass-panel p-4 flex items-center gap-4 animate-[bounce_4s_infinite] border-l-2 border-l-green-500"> <div className={`absolute top-0 left-0 w-full h-[3px] shadow-2xl transition-all duration-300 z-20 ${isIdentified ? 'bg-green-400 shadow-green-500 opacity-0' : isHovered ? 'bg-cyan-400 shadow-cyan-400 animate-[scanline_1s_linear_infinite]' : 'bg-cyan-500/50 shadow-cyan-500/20 animate-[scanline_4s_linear_infinite]'}`}></div>
<Activity className="w-6 h-6 text-green-500 animate-pulse" />
<div> {/* Center Module */}
<p className="text-[9px] text-gray-400 uppercase tracking-widest font-mono">Status</p> <div className="relative z-10 w-full h-full flex items-center justify-center">
<p className="text-xs font-bold text-green-400 font-mono tracking-wider">OPTIMAL_FLOW</p> {/* Orbiting Rings */}
<div className={`absolute w-[120%] h-[120%] border rounded-full transition-all duration-700 ${isIdentified ? 'border-green-500/30 animate-[spin_5s_linear_infinite]' : 'border-cyan-500/5 animate-[spin_30s_linear_infinite]'}`}></div>
<div className={`absolute w-[80%] h-[80%] border rounded-full transition-all duration-700 ${isIdentified ? 'border-green-500/50 animate-[spin_3s_linear_infinite_reverse]' : 'border-cyan-500/10 animate-[spin_20s_linear_infinite_reverse]'}`}></div>
{/* Core Fingerprint Circle */}
<div className={`w-64 h-64 rounded-full border flex items-center justify-center transition-all duration-700 relative bg-gray-900 ${isIdentified ? 'border-green-400 shadow-[0_0_150px_rgba(34,197,94,0.4)] scale-110' : 'border-cyan-500/30 shadow-[0_0_100px_rgba(6,182,212,0.2)]'}`}>
{/* Scanning Pulse Overlay */}
{isHovered && !isIdentified && (
<div className="absolute inset-0 rounded-full bg-cyan-400/20 animate-pulse"></div>
)}
<Fingerprint className={`w-32 h-32 transition-all duration-700 ${isIdentified ? 'text-green-400' : isHovered ? 'text-cyan-300 scale-105' : 'text-cyan-400'}`} />
{/* Verification Badge */}
<div className={`absolute -bottom-4 bg-gray-900 border px-4 py-1.5 rounded-full transition-all duration-700 transform ${isIdentified ? 'scale-100 opacity-100 border-green-500 translate-y-0' : 'scale-50 opacity-0 border-cyan-500 translate-y-4'}`}>
<div className="flex items-center gap-2">
<Verified className="w-4 h-4 text-green-400" />
<span className="text-[10px] font-black text-white uppercase tracking-widest">Access Granted</span>
</div>
</div>
</div> </div>
</div> </div>
{/* Dynamic Data Readouts */}
<div className={`absolute top-10 left-10 font-mono text-[9px] leading-tight transition-colors duration-700 ${isIdentified ? 'text-green-400' : isHovered ? 'text-cyan-400' : 'text-cyan-500/60'}`}>
CORE_TEMP: {randomData.temp}C<br/>
ENCRYPT_MODE: RSA_4096<br/>
SEC_LAYER: {isIdentified ? 'V5_ULTRA' : 'V4_ACTIVE'}<br/>
{isHovered && <span className={`font-bold ${isIdentified ? 'text-green-300' : 'text-cyan-300'}`}>BIO_AUTH: {isIdentified ? 'VERIFIED' : 'SCANNING...'}</span>}
</div>
<div className={`absolute bottom-10 right-10 font-mono text-[9px] text-right transition-colors duration-700 ${isIdentified ? 'text-green-400' : isHovered ? 'text-cyan-400' : 'text-cyan-500/60'}`}>
PACKET_LOSS: {randomData.loss}%<br/>
LATENCY: 0.04ms<br/>
NODES: {randomData.nodes}/1248<br/>
{isHovered && <span className={`font-bold ${isIdentified ? 'text-green-300 animate-pulse' : 'text-cyan-300'}`}>{isIdentified ? 'ENCRYPTION: MAX' : 'HANDSHAKE...'}</span>}
</div>
</div> </div>
</div> </div>
</div> </div>
</header> </header>
<section className="py-32 bg-[#020205]"> {/* Feature Grid */}
<div className="max-w-[1400px] mx-auto px-6"> <section className="py-24 bg-transparent px-6">
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="max-w-[1400px] mx-auto">
{[ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{ icon: Eye, title: 'Neural Surveillance', desc: 'Real-time object recognition and behavioral prediction algorithms.' }, {[
{ icon: Scan, title: 'Retinal Access', desc: '99.999% accuracy biometric entry points with liveness detection.' }, { icon: ShieldAlert, title: 'AI Védelem', desc: 'Öntanuló algoritmusok, melyek felismerik a nulladik napi támadásokat is.' },
{ icon: Server, title: 'Core Defense', desc: 'Hardened physical and logical shielding for data centers.' }, { icon: Network, title: 'Mesh Hálózat', desc: 'Decentralizált adatforgalom, amely garantálja a 100%-os rendelkezésre állást.' },
{ icon: Globe, title: 'Global Ops', desc: '24/7 localized threat monitoring from orbit-synced satellites.' }, { icon: HardDrive, title: 'Adatszéf', desc: 'Fizikailag elkülönített, titkosított adattárolási központok világszerte.' },
{ icon: Cpu, title: 'IoT Mesh', desc: 'Thousands of interconnected sensors forming an unbreakable web.' }, { icon: Key, title: 'Biometrikus Auth', desc: 'Többtényezős azonosítás retina, ujjlenyomat és hangalapú validációval.' }
{ icon: Shield, title: 'Hybrid Firewall', desc: 'Simultaneous protection against kinetic and digital intrusion.' }, ].map((f, i) => (
].map((item, i) => ( <div key={i} className="glass-card p-8 rounded-[32px] hover:border-cyan-400/50 transition-all group cursor-pointer hover:-translate-y-2 hover:shadow-[0_0_35px_rgba(34,211,238,0.2)]">
<div key={i} className="group relative bg-[#05070a] border border-gray-800 p-10 overflow-hidden hover:border-cyan-500/50 transition-all duration-500"> <div className="w-14 h-14 bg-cyan-950/30 rounded-2xl flex items-center justify-center text-cyan-400 mb-6 group-hover:bg-cyan-500 group-hover:text-black transition-all group-hover:shadow-[0_0_20px_rgba(34,211,238,0.6)]">
<div className="relative z-10"> <f.icon className="w-7 h-7" />
<div className="w-14 h-14 bg-[#0a0f18] border border-gray-800 group-hover:border-cyan-500 flex items-center justify-center mb-8 transition-all"> </div>
<item.icon className="w-6 h-6 text-gray-500 group-hover:text-cyan-400 transition-colors" /> <h3 className="text-lg font-bold text-white mb-3 uppercase font-mono tracking-tighter group-hover:text-cyan-300 transition-colors">{f.title}</h3>
</div> <p className="text-gray-400 text-xs leading-relaxed">{f.desc}</p>
<h3 className="text-xl font-bold text-white mb-4 font-mono group-hover:text-cyan-300 transition-colors">{item.title}</h3> </div>
<p className="text-gray-500 text-xs leading-relaxed group-hover:text-gray-300 transition-colors font-mono">{item.desc}</p> ))}
</div> </div>
</div>
))}
</div>
</div> </div>
</section> </section>
</> </>
)} )}
{/* SOLUTIONS VIEW */} {/* --- SOLUTIONS PAGE --- */}
{activeTab === 'solutions' && ( {activePage === 'solutions' && (
<section className="pt-40 pb-20 px-8"> <div className="py-24 px-6 max-w-[1400px] mx-auto min-h-screen">
<div className="max-w-6xl mx-auto"> <div className="flex flex-col md:flex-row justify-between items-end mb-16 gap-8 text-glow">
<div className="flex items-center gap-4 mb-10"> <div className="max-w-2xl">
<div className="w-12 h-1 bg-cyan-500"></div> <h2 className="text-sm font-black text-cyan-500 uppercase tracking-[0.5em] mb-4">Megoldásaink</h2>
<h2 className="text-4xl font-mono font-black uppercase tracking-tighter">Strategic Solutions</h2> <p className="text-4xl md:text-6xl font-black text-white leading-none tracking-tighter uppercase font-mono">Ipari szintű <br/>biztonsági stack</p>
</div>
<div className="grid lg:grid-cols-2 gap-16 items-center">
<div className="space-y-10">
<p className="text-xl text-gray-400 font-mono leading-relaxed">
We offer a multi-layered security stack designed to neutralize threats before they reach your perimeter.
</p>
<div className="space-y-6">
{[
{ title: "Zero Trust Architecture", desc: "Never trust, always verify. Every node is isolated and encrypted." },
{ title: "Predictive AI Shield", desc: "Our neural networks predict intrusion patterns with 99.8% accuracy." },
{ title: "Cloud Integration", desc: "Seamless security across AWS, Azure, and private data centers." }
].map((sol, i) => (
<div key={i} className="bg-[#05070a] border-l-4 border-l-cyan-500 p-6">
<h4 className="font-bold text-cyan-400 mb-2 font-mono uppercase text-sm">{sol.title}</h4>
<p className="text-gray-500 text-xs font-mono">{sol.desc}</p>
</div>
))}
</div>
</div> </div>
<div className="relative group"> <div className="text-gray-500 font-mono text-xs uppercase tracking-widest border-l border-gray-800 pl-6 hidden md:block">
<div className="absolute -inset-2 bg-cyan-500 blur-2xl opacity-10 group-hover:opacity-30 transition-opacity"></div> Full Spectrum <br/>Protection Suite v.8.2
<img src="https://images.unsplash.com/photo-1550751827-4bd374c3f58b?auto=format&fit=crop&w=1200&q=80" alt="Solution" className="rounded-2xl border border-cyan-500/20 relative z-10" />
</div> </div>
</div> </div>
</div>
</section>
)}
{/* HARDWARE VIEW */} <div className="grid grid-cols-1 lg:grid-cols-2 gap-10">
{activeTab === 'hardware' && ( <div className="glass-card rounded-[48px] overflow-hidden group border-cyan-500/10 hover:shadow-[0_0_40px_rgba(34,211,238,0.1)] transition-all">
<section className="pt-40 pb-20 px-8"> <div className="h-[400px] relative overflow-hidden">
<div className="max-w-6xl mx-auto"> <img src="https://images.unsplash.com/photo-1558494949-ef010cbdcc51?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80" alt="Server" className="w-full h-full object-cover grayscale opacity-50 group-hover:scale-110 group-hover:opacity-80 transition-all duration-1000" />
<div className="flex items-center gap-4 mb-10"> <div className="absolute inset-0 bg-gradient-to-t from-[#020205] via-transparent to-transparent"></div>
<div className="w-12 h-1 bg-cyan-500"></div> <div className="absolute top-10 right-10 bg-cyan-500 text-black px-4 py-1.5 rounded-full text-[10px] font-black uppercase tracking-widest group-hover:shadow-[0_0_20px_rgba(34,211,238,0.6)] transition-all">Kritikus Infrastruktúra</div>
<h2 className="text-4xl font-mono font-black uppercase tracking-tighter">Hardened Hardware</h2>
</div>
<div className="grid md:grid-cols-3 gap-8">
{[
{ icon: Box, name: "Node V4 Unit", img: "https://images.unsplash.com/photo-1518770660439-4636190af475?auto=format&fit=crop&w=800&q=80" },
{ icon: Cpu, name: "Neural Processor", img: "https://images.unsplash.com/photo-1591799264318-7e6ef8ddb7ea?auto=format&fit=crop&w=800&q=80" },
{ icon: Shield, name: "Quantum Enclosure", img: "https://images.unsplash.com/photo-1544197150-b99a580bb7a8?auto=format&fit=crop&w=800&q=80" }
].map((hw, i) => (
<div key={i} className="bg-[#05070a] rounded-2xl overflow-hidden border border-gray-800 hover:border-cyan-500/40 transition-all">
<img src={hw.img} alt={hw.name} className="h-48 w-full object-cover grayscale opacity-60 hover:grayscale-0 hover:opacity-100 transition-all" />
<div className="p-6">
<div className="flex items-center gap-3 mb-4">
<hw.icon className="w-5 h-5 text-cyan-500" />
<span className="font-mono font-bold uppercase text-xs">{hw.name}</span>
</div>
<button className="w-full py-2 bg-gray-900 border border-gray-800 text-[10px] font-bold uppercase tracking-widest hover:bg-cyan-600 hover:text-black transition-all">View Specs</button>
</div>
</div>
))}
</div>
</div>
</section>
)}
{/* SECTORS VIEW */}
{activeTab === 'sectors' && (
<section className="pt-40 pb-20 px-8 text-center">
<div className="max-w-5xl mx-auto">
<h2 className="text-5xl font-mono font-black uppercase tracking-tighter mb-6">Strategic Sectors</h2>
<p className="text-gray-400 font-mono mb-20">Steelguard protects the infrastructure that power nations.</p>
<div className="grid md:grid-cols-3 gap-12">
{[
{ icon: Building2, label: "Enterprise", count: "400+ Nodes" },
{ icon: Globe, label: "Government", count: "12 Nations" },
{ icon: Shield, label: "Defense", count: "Active Mesh" }
].map((sector, i) => (
<div key={i} className="flex flex-col items-center group cursor-default">
<div className="w-24 h-24 rounded-full border-2 border-gray-800 flex items-center justify-center mb-6 group-hover:border-cyan-500 group-hover:shadow-[0_0_30px_rgba(6,182,212,0.2)] transition-all">
<sector.icon className="w-10 h-10 text-gray-500 group-hover:text-cyan-400 transition-colors" />
</div>
<h3 className="font-mono font-black uppercase text-xl mb-2">{sector.label}</h3>
<span className="text-[10px] font-mono text-cyan-600 tracking-widest">{sector.count}</span>
</div>
))}
</div>
</div>
</section>
)}
{/* COMPANY VIEW */}
{activeTab === 'company' && (
<section className="pt-40 pb-20 px-8">
<div className="max-w-4xl mx-auto">
<div className="grid md:grid-cols-2 gap-16 items-center">
<div className="relative">
<div className="absolute -inset-4 bg-cyan-500/5 blur-3xl rounded-full"></div>
<img src="https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&w=1000&q=80" alt="Office" className="rounded-3xl relative z-10 opacity-70 grayscale hover:grayscale-0 transition-all" />
</div>
<div>
<span className="text-cyan-500 font-mono text-[10px] tracking-widest block mb-4 uppercase">Origins</span>
<h2 className="text-4xl font-mono font-black uppercase mb-8">Engineering <br/>Secured Future</h2>
<p className="text-gray-400 font-mono text-sm leading-loose mb-8">
Founded in 2042, Steelguard Defense Systems has evolved from a small hardware research lab into a global leader in AI-driven security architecture. Our mission is absolute protection through innovation.
</p>
<div className="flex items-center gap-8">
<div>
<p className="text-3xl font-black text-white font-mono">15</p>
<p className="text-[9px] text-gray-600 uppercase font-mono tracking-widest">Global Hubs</p>
</div>
<div>
<p className="text-3xl font-black text-white font-mono">850+</p>
<p className="text-[9px] text-gray-600 uppercase font-mono tracking-widest">Architects</p>
</div>
</div> </div>
</div> <div className="p-10 md:p-12">
</div> <h3 className="text-3xl font-black text-white mb-6 uppercase tracking-tighter font-mono italic group-hover:text-glow transition-all">Kormányzati Szintű Titkosítás</h3>
</div> <p className="text-gray-400 mb-10 leading-relaxed">Megoldásaink a legmagasabb szintű állami és katonai sztenderdeknek felelnek meg. Biztonságos adatcsere, védett kommunikációs csatornák és zéró hozzáférésű adattárolás.</p>
</section> <button className="flex items-center gap-2 text-cyan-400 font-black text-xs uppercase tracking-[0.3em] hover:text-white transition-colors group/btn hover:text-glow">
Részletes specifikáció <ChevronRight className="w-4 h-4 group-hover/btn:translate-x-1 transition-transform" />
</button>
</div>
</div>
<div className="glass-card rounded-[48px] overflow-hidden group border-cyan-500/10 hover:shadow-[0_0_40px_rgba(34,211,238,0.1)] transition-all">
<div className="h-[400px] relative overflow-hidden">
<img src="https://images.unsplash.com/photo-1550751827-4bd374c3f58b?ixlib=rb-4.0.3&auto=format&fit=crop&w=1200&q=80" alt="Control Room" className="w-full h-full object-cover grayscale opacity-50 group-hover:scale-110 group-hover:opacity-80 transition-all duration-1000" />
<div className="absolute inset-0 bg-gradient-to-t from-[#020205] via-transparent to-transparent"></div>
<div className="absolute top-10 right-10 bg-cyan-500 text-black px-4 py-1.5 rounded-full text-[10px] font-black uppercase tracking-widest group-hover:shadow-[0_0_20px_rgba(34,211,238,0.6)] transition-all">Global Monitoring</div>
</div>
<div className="p-10 md:p-12">
<h3 className="text-3xl font-black text-white mb-6 uppercase tracking-tighter font-mono italic group-hover:text-glow transition-all">24/7 AI Felügyeleti Központ</h3>
<p className="text-gray-400 mb-10 leading-relaxed">Globális SOC (Security Operations Center) hálózatunk folyamatosan figyeli a gyanús aktivitásokat. Az incidensek kezelése automatizált, az emberi beavatkozás csak validálásra szolgál.</p>
<button className="flex items-center gap-2 text-cyan-400 font-black text-xs uppercase tracking-[0.3em] hover:text-white transition-colors group/btn hover:text-glow">
Részletes specifikáció <ChevronRight className="w-4 h-4 group-hover/btn:translate-x-1 transition-transform" />
</button>
</div>
</div>
</div>
</div>
)} )}
{/* MAP INTEGRATION */} {/* --- HARDWARE PAGE --- */}
{activeTab === 'home' && ( {activePage === 'hardware' && (
<section className="py-20 bg-[#050505] relative overflow-hidden"> <div className="py-24 px-6 max-w-[1400px] mx-auto min-h-screen">
<div className="max-w-[1400px] mx-auto px-6"> <div className="text-center mb-20">
<div className="flex items-center gap-4 mb-10"> <h2 className="text-4xl md:text-7xl font-black text-white uppercase tracking-tighter italic font-mono mb-6 text-glow">Fizikai Biztonság</h2>
<MapPin className="text-cyan-500 w-6 h-6" /> <p className="text-gray-400 max-w-2xl mx-auto font-medium">Saját fejlesztésű hardvereszközök, melyek a digitális védelmet fizikai réteggel egészítik ki.</p>
<h2 className="text-2xl font-mono font-black uppercase tracking-widest">Command Center HQ</h2>
</div>
<div className="relative w-full h-[500px] rounded-3xl overflow-hidden border border-cyan-900/30 group shadow-[0_0_30px_rgba(0,0,0,0.5)]">
<div className="absolute inset-0 z-10 pointer-events-none border-[10px] border-[#020205] opacity-80"></div>
<div className="absolute inset-0 z-10 pointer-events-none ring-1 ring-cyan-500/20"></div>
<iframe
title="Steelguard HQ Map"
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2695.565377508381!2d19.0354183769188!3d47.49831737118037!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4741dc41c2c8f877%3A0x7292275f0a2072e!2sBudapest%2C%20Szent%20Gy%C3%B6rgy%20t%C3%A9r%2C%201014!5e0!3m2!1shu!2shu!4v1716300000000!5m2!1shu!2shu"
width="100%"
height="100%"
style={{ border: 0, filter: 'grayscale(1) invert(0.9) contrast(1.2)' }}
allowFullScreen
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
></iframe>
<div className="absolute top-0 left-0 w-full h-full bg-cyan-500/5 mix-blend-color pointer-events-none"></div>
</div>
</div> </div>
</section>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{[
{ name: 'S-Core Node', type: 'Hardveres tűzfal', desc: 'Optikai izolációs technológia, 100Gbps átviteli sebesség mellett is észrevehetetlen késleltetés.' },
{ name: 'Retina-X', type: 'Biometrikus szkenner', desc: 'Infravörös érhálózat-vizsgálat, melyet lehetetlen másolni vagy kijátszani.' },
{ name: 'Vault One', type: 'Kvantum tároló', desc: 'Hardware Security Module (HSM), mely önmegsemmisítő mechanizmussal rendelkezik behatolás esetén.' }
].map((h, i) => (
<div key={i} className="glass-card p-10 rounded-[40px] flex flex-col items-center text-center group border-cyan-500/5 hover:border-cyan-400/40 transition-all hover:shadow-[0_0_40px_rgba(34,211,238,0.15)]">
<div className="w-32 h-32 bg-gray-900 border border-gray-800 rounded-full flex items-center justify-center mb-8 relative group-hover:scale-110 transition-transform">
<div className="absolute inset-0 bg-cyan-500/10 rounded-full blur-xl group-hover:bg-cyan-500/30 transition-all"></div>
<Chip className="w-16 h-16 text-cyan-400 group-hover:drop-shadow-[0_0_12px_rgba(34,211,238,0.8)] transition-all" />
</div>
<span className="text-[10px] font-black text-cyan-500 uppercase tracking-widest mb-2 group-hover:text-glow transition-all">{h.type}</span>
<h3 className="text-2xl font-black text-white mb-6 uppercase tracking-tighter font-mono group-hover:text-cyan-300 transition-colors">{h.name}</h3>
<p className="text-gray-500 text-sm leading-relaxed">{h.desc}</p>
</div>
))}
</div>
</div>
)} )}
</main> </main>
{/* Footer / CTA */} {/* Stats & CTA */}
<footer className="py-32 bg-[#020205] relative overflow-hidden"> <footer className="py-24 relative overflow-hidden bg-transparent">
<div className="max-w-[1400px] mx-auto px-6 grid md:grid-cols-4 gap-0 divide-x divide-gray-900 text-center relative z-10 border-y border-gray-900 mb-20"> <div className="max-w-[1400px] mx-auto px-6">
{[ <div className="grid grid-cols-2 md:grid-cols-4 gap-10 md:gap-0 divide-x divide-gray-900 text-center border-y border-gray-900 py-16 mb-24">
{ val: '500+', label: 'NODES ACTIVE' }, {[
{ val: '0.01ms', label: 'LATENCY' }, { val: '14 PB', label: 'Védett adat' },
{ val: '100%', label: 'UPTIME' }, { val: '0.00ms', label: 'Esemény válaszidő' },
{ val: 'SECURE', label: 'STATUS' } { val: '256k+', label: 'Napi hárítás' },
].map((stat, i) => ( { val: 'ZERO', label: 'Biztonsági rés' }
<div key={i} className="relative py-10 group hover:bg-cyan-900/5 transition-colors cursor-default"> ].map((s, i) => (
<div className="text-5xl font-bold text-gray-700 mb-2 font-mono group-hover:text-cyan-400 group-hover:scale-110 transition-all duration-300 text-glow">{stat.val}</div> <div key={i} className="px-4">
<div className="text-cyan-900 text-[10px] font-bold uppercase tracking-[0.3em] group-hover:text-cyan-600">{stat.label}</div> <div className="text-3xl md:text-6xl font-black text-white mb-2 font-mono tracking-tighter text-glow italic">{s.val}</div>
</div> <div className="text-cyan-900 text-[9px] font-black uppercase tracking-[0.3em]">{s.label}</div>
))} </div>
</div> ))}
</div>
<div className="max-w-4xl mx-auto px-6 text-center relative z-10"> <div className="max-w-4xl mx-auto text-center space-y-12">
<div className="inline-block mb-10 p-4 border border-cyan-500/30 rounded-full animate-pulse-glow"> <div className="relative inline-block group">
<Shield className="w-12 h-12 text-cyan-500" /> <div className="absolute inset-0 bg-cyan-500 blur-3xl opacity-30 animate-pulse group-hover:opacity-60 transition-opacity"></div>
</div> <div className="w-20 h-20 md:w-24 md:h-24 bg-gray-900 border border-cyan-500/30 rounded-[32px] flex items-center justify-center relative z-10 mx-auto transform -rotate-12 group-hover:rotate-0 transition-transform duration-500 shadow-[0_0_40px_rgba(34,211,238,0.2)] group-hover:shadow-[0_0_60px_rgba(34,211,238,0.5)] group-hover:border-cyan-400">
<h2 className="text-4xl md:text-6xl font-bold text-white mb-8 font-mono uppercase"> <ShieldCheck className="w-10 h-10 md:w-12 md:h-12 text-cyan-400 group-hover:drop-shadow-[0_0_8px_rgba(34,211,238,1)]" />
SECURE YOUR <span className="text-cyan-500">FUTURE</span> </div>
</h2> </div>
<p className="text-gray-400 mb-12 text-lg max-w-xl mx-auto font-mono text-xs leading-loose">
Initiate contact with our security architects. Design a defense strategy leveraging next-gen technologies. <h2 className="text-4xl md:text-7xl font-black text-white uppercase tracking-tighter font-mono leading-none italic text-glow">
</p> Ahol a <span className="text-cyan-500 underline decoration-cyan-500/30 underline-offset-8">bizalom</span> <br/>nem kérdés.
<div className="flex flex-col sm:flex-row justify-center gap-6"> </h2>
<button className="cyber-button bg-cyan-600 hover:bg-cyan-500 text-black px-12 py-5 font-bold uppercase tracking-[0.2em] text-xs transition-all shadow-[0_0_20px_rgba(8,145,178,0.5)]">
Initialize Sequence <p className="text-gray-400 text-lg max-w-xl mx-auto font-medium">
</button> Kérje szakértőink konzultációját az Enterprise Security Protocol implementálásához.
<button className="border border-gray-800 hover:border-white text-gray-400 hover:text-white px-12 py-5 font-bold uppercase tracking-[0.2em] text-xs transition-all hover:bg-white/5 hover:shadow-[0_0_15px_rgba(255,255,255,0.2)]"> </p>
Download Manifest
</button> <div className="flex flex-col sm:flex-row justify-center gap-6 pt-10">
</div> <button className="bg-cyan-600 text-black px-12 py-6 font-black uppercase tracking-widest text-sm button-clip hover:bg-white transition-all shadow-[0_0_30px_rgba(34,211,238,0.4)] hover:shadow-[0_0_50px_rgba(34,211,238,0.8)] neon-glow-btn">
<div className="mt-32 pt-10 border-t border-gray-900 text-gray-600 text-[9px] uppercase tracking-[0.2em] flex flex-col md:flex-row justify-between items-center gap-4 font-mono"> Szakértői Konzultáció
<div>&copy; 2024 STEELGUARD DEFENSE SYSTEMS.</div> </button>
<div className="text-cyan-900">SYSTEM_ID: MW-ENT-8842</div> <button className="border border-gray-800 text-gray-500 px-12 py-6 font-black uppercase tracking-widest text-sm button-clip hover:border-cyan-500 hover:text-cyan-400 transition-all hover:shadow-[0_0_20px_rgba(34,211,238,0.2)]">
Rendszerbemutató (PDF)
</button>
</div>
<div className="pt-32 border-t border-gray-900 flex flex-col md:flex-row justify-between items-center gap-8 text-gray-600 font-mono text-[9px] uppercase tracking-[0.3em]">
<div>&copy; 2024 STEELGUARD DEFENSE SYSTEMS. ALL RIGHTS RESERVED.</div>
<div className="flex gap-10">
<span className="hover:text-cyan-400 cursor-pointer transition-colors hover:text-glow">ADATVÉDELEM</span>
<span className="hover:text-cyan-400 cursor-pointer transition-colors hover:text-glow">ÁSZF</span>
<span className="text-cyan-900">SYSTEM_ID: CORE-X88-HU</span>
</div>
</div>
</div> </div>
</div> </div>
</footer> </footer>
</div> </div>
); );
}; };

View File

@@ -1,9 +1,10 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { ArrowLeft, Instagram, Facebook, MapPin, Phone, Mail, Clock, Heart, Star, ChevronDown } from 'lucide-react'; import { ArrowLeft, Instagram, Facebook, MapPin, Phone, Mail, Clock, Heart, Star, ChevronDown, Menu, X } from 'lucide-react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
export const SweetCraving: React.FC = () => { export const SweetCraving: React.FC = () => {
const [scrolled, setScrolled] = useState(false); const [scrolled, setScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
useEffect(() => { useEffect(() => {
const handleScroll = () => { const handleScroll = () => {
@@ -16,9 +17,9 @@ export const SweetCraving: React.FC = () => {
return ( return (
<div className="font-serif bg-[#FFF5F5] text-[#5D4037] min-h-screen scroll-smooth"> <div className="font-serif bg-[#FFF5F5] text-[#5D4037] min-h-screen scroll-smooth">
{/* Return to Main Site Button */} {/* Return to Main Site Button */}
<div className="fixed bottom-6 right-6 z-[60]"> <div className="fixed bottom-4 right-4 md:bottom-6 md:right-6 z-[60]">
<Link to="/#references"> <Link to="/#references">
<button className="bg-white/90 backdrop-blur-md shadow-lg px-5 py-2.5 rounded-full text-sm font-sans font-medium flex items-center hover:bg-white hover:scale-105 transition-all duration-300 group text-[#E91E63]"> <button className="bg-white/90 backdrop-blur-md shadow-lg px-4 md:px-5 py-2 md:py-2.5 rounded-full text-xs md:text-sm font-sans font-medium flex items-center hover:bg-white hover:scale-105 transition-all duration-300 group text-[#E91E63]">
<ArrowLeft className="w-4 h-4 mr-2 group-hover:-translate-x-1 transition-transform" /> <ArrowLeft className="w-4 h-4 mr-2 group-hover:-translate-x-1 transition-transform" />
Vissza a referenciákhoz Vissza a referenciákhoz
</button> </button>
@@ -29,15 +30,16 @@ export const SweetCraving: React.FC = () => {
<nav <nav
className={`fixed top-0 w-full z-40 transition-all duration-500 ${ className={`fixed top-0 w-full z-40 transition-all duration-500 ${
scrolled scrolled
? 'bg-white/90 backdrop-blur-md shadow-lg py-3' ? 'bg-white/95 backdrop-blur-md shadow-lg py-2 md:py-3'
: 'bg-transparent py-6' : 'bg-transparent py-4 md:py-6'
}`} }`}
> >
<div className="max-w-6xl mx-auto px-6 flex justify-between items-center"> <div className="max-w-6xl mx-auto px-4 md:px-6 flex justify-between items-center">
<div className={`text-3xl font-bold text-[#E91E63] italic transition-all duration-300 ${scrolled ? 'scale-90' : 'scale-100'}`}> <div className={`text-2xl md:text-3xl font-bold text-[#E91E63] italic transition-all duration-300 ${scrolled ? 'scale-90' : 'scale-100'}`}>
SweetCraving SweetCraving
</div> </div>
<div className="hidden md:flex space-x-10 font-medium font-sans text-sm tracking-wide">
<div className="hidden md:flex space-x-8 lg:space-x-10 font-medium font-sans text-sm tracking-wide">
{['Kezdőlap', 'Rólunk', 'Kínálat', 'Vélemények'].map((item, i) => ( {['Kezdőlap', 'Rólunk', 'Kínálat', 'Vélemények'].map((item, i) => (
<a <a
key={i} key={i}
@@ -49,10 +51,33 @@ export const SweetCraving: React.FC = () => {
</a> </a>
))} ))}
</div> </div>
<button className="bg-[#E91E63] text-white px-8 py-2.5 rounded-full font-sans font-bold text-sm hover:bg-[#D81B60] transition-all shadow-lg hover:shadow-[#E91E63]/30 hover:-translate-y-0.5 transform">
Rendelés <div className="flex items-center gap-4">
</button> <button className="hidden sm:block bg-[#E91E63] text-white px-6 md:px-8 py-2 md:2.5 rounded-full font-sans font-bold text-xs md:text-sm hover:bg-[#D81B60] transition-all shadow-lg hover:shadow-[#E91E63]/30">
Rendelés
</button>
<button onClick={() => setMobileMenuOpen(!mobileMenuOpen)} className="md:hidden p-2 text-[#E91E63]">
{mobileMenuOpen ? <X /> : <Menu />}
</button>
</div>
</div> </div>
{/* Mobile Nav Overlay */}
{mobileMenuOpen && (
<div className="md:hidden absolute top-full left-0 w-full bg-white shadow-2xl animate-fade-in p-6 space-y-6 flex flex-col font-sans font-bold text-center border-t border-gray-100">
{['Kezdőlap', 'Rólunk', 'Kínálat', 'Vélemények'].map((item, i) => (
<a
key={i}
onClick={() => setMobileMenuOpen(false)}
href={`#${item.toLowerCase() === 'kezdőlap' ? 'home' : item === 'Kínálat' ? 'menu' : item === 'Rólunk' ? 'about' : 'contact'}`}
className="text-lg hover:text-[#E91E63]"
>
{item}
</a>
))}
<button className="bg-[#E91E63] text-white py-4 rounded-xl">Rendelés Most</button>
</div>
)}
</nav> </nav>
{/* Hero Section */} {/* Hero Section */}
@@ -61,86 +86,84 @@ export const SweetCraving: React.FC = () => {
<img <img
src="https://images.unsplash.com/photo-1558961363-fa8fdf82db35?auto=format&fit=crop&w=1920&q=80" src="https://images.unsplash.com/photo-1558961363-fa8fdf82db35?auto=format&fit=crop&w=1920&q=80"
alt="Desszertműhely Hero" alt="Desszertműhely Hero"
className="w-full h-full object-cover" className="w-full h-full object-cover object-center"
/> />
<div className="absolute inset-0 bg-gradient-to-t from-[#FFF5F5] via-white/20 to-transparent"></div> <div className="absolute inset-0 bg-gradient-to-t from-[#FFF5F5] via-white/40 to-transparent md:via-white/20"></div>
</div> </div>
<div className="relative z-10 text-center px-4 max-w-4xl mx-auto mt-16"> <div className="relative z-10 text-center px-4 max-w-4xl mx-auto pt-20">
<div className="animate-fade-in-up" style={{ animationDelay: '0.1s' }}> <div className="animate-fade-in-up" style={{ animationDelay: '0.1s' }}>
<span className="bg-white/80 backdrop-blur-md px-6 py-2 rounded-full text-[#E91E63] text-xs font-bold font-sans tracking-[0.2em] uppercase mb-8 inline-block shadow-sm"> <span className="bg-white/80 backdrop-blur-md px-4 md:px-6 py-1.5 md:py-2 rounded-full text-[#E91E63] text-[10px] md:text-xs font-bold font-sans tracking-[0.2em] uppercase mb-6 md:mb-8 inline-block shadow-sm">
Kézműves Desszertműhely Kézműves Desszertműhely
</span> </span>
</div> </div>
<h1 className="text-6xl md:text-8xl font-bold mb-8 drop-shadow-sm text-gray-900 leading-tight animate-fade-in-up" style={{ animationDelay: '0.3s' }}> <h1 className="text-4xl sm:text-6xl md:text-8xl font-bold mb-6 md:mb-8 drop-shadow-sm text-gray-900 leading-tight animate-fade-in-up px-2" style={{ animationDelay: '0.3s' }}>
Édes Álmok <br/> Édes Álmok <br className="hidden sm:block" />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-[#E91E63] to-[#FF80AB]"> <span className="text-transparent bg-clip-text bg-gradient-to-r from-[#E91E63] to-[#FF80AB]">
Süteménybe Zárva Süteménybe Zárva
</span> </span>
</h1> </h1>
<p className="text-xl md:text-2xl text-gray-800/80 max-w-2xl mx-auto mb-12 font-medium leading-relaxed animate-fade-in-up" style={{ animationDelay: '0.5s' }}> <p className="text-base md:text-xl lg:text-2xl text-gray-800/80 max-w-2xl mx-auto mb-8 md:mb-12 font-medium leading-relaxed animate-fade-in-up px-4" style={{ animationDelay: '0.5s' }}>
Természetes alapanyagokból, szívvel-lélekkel készült desszertek minden alkalomra. Természetes alapanyagokból, szívvel-lélekkel készült desszertek minden alkalomra.
<br className="hidden md:block"/> Mert minden nap megérdemel egy kis kényeztetést.
</p> </p>
<div className="flex flex-col sm:flex-row gap-5 justify-center animate-fade-in-up" style={{ animationDelay: '0.7s' }}> <div className="flex flex-col sm:flex-row gap-4 md:gap-5 justify-center animate-fade-in-up px-6 sm:px-0" style={{ animationDelay: '0.7s' }}>
<a href="#menu" className="bg-[#E91E63] text-white px-10 py-4 rounded-full font-sans font-bold hover:bg-[#D81B60] transition-all shadow-xl shadow-[#E91E63]/30 hover:-translate-y-1 hover:scale-105"> <a href="#menu" className="bg-[#E91E63] text-white px-8 md:px-10 py-3 md:py-4 rounded-full font-sans font-bold hover:bg-[#D81B60] transition-all shadow-xl shadow-[#E91E63]/30 hover:-translate-y-1">
Kínálatunk Megtekintése Kínálatunk
</a> </a>
<a href="#about" className="bg-white text-[#5D4037] px-10 py-4 rounded-full font-sans font-bold hover:bg-gray-50 transition-all shadow-lg hover:-translate-y-1 hover:scale-105"> <a href="#about" className="bg-white text-[#5D4037] px-8 md:px-10 py-3 md:py-4 rounded-full font-sans font-bold hover:bg-gray-50 transition-all shadow-lg hover:-translate-y-1">
Ismerj meg minket Ismerj meg minket
</a> </a>
</div> </div>
</div> </div>
{/* Scroll Indicator */} <div className="absolute bottom-6 md:bottom-10 left-1/2 transform -translate-x-1/2 animate-bounce">
<div className="absolute bottom-10 left-1/2 transform -translate-x-1/2 animate-bounce"> <ChevronDown className="w-6 h-6 md:w-8 h-8 text-[#E91E63] opacity-60" />
<ChevronDown className="w-8 h-8 text-[#E91E63] opacity-60" />
</div> </div>
</section> </section>
{/* About Section */} {/* About Section */}
<section id="about" className="py-32 px-6 bg-white overflow-hidden"> <section id="about" className="py-20 md:py-32 px-4 md:px-6 bg-white overflow-hidden">
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<div className="grid md:grid-cols-2 gap-20 items-center"> <div className="grid md:grid-cols-2 gap-12 md:gap-20 items-center">
<div className="relative group"> <div className="relative group px-4 md:px-0">
<div className="absolute -top-6 -left-6 w-full h-full border-4 border-[#FF80AB]/30 rounded-[2rem] transition-transform duration-500 group-hover:translate-x-2 group-hover:translate-y-2"></div> <div className="absolute -top-4 md:-top-6 -left-4 md:-left-6 w-full h-full border-4 border-[#FF80AB]/30 rounded-[1.5rem] md:rounded-[2rem]"></div>
<img <img
src="https://images.unsplash.com/photo-1556910103-1c02745aae4d?auto=format&fit=crop&w=1000&q=80" src="https://images.unsplash.com/photo-1556910103-1c02745aae4d?auto=format&fit=crop&w=1000&q=80"
alt="Pék és Cukrászmunka" alt="Pék és Cukrászmunka"
className="rounded-[2rem] shadow-2xl relative z-10 transform transition-transform duration-700 hover:scale-[1.02]" className="rounded-[1.5rem] md:rounded-[2rem] shadow-2xl relative z-10 w-full"
/> />
{/* Floating Badge */} {/* Floating Badge (hidden on small mobile) */}
<div className="absolute -bottom-10 -right-10 z-20 bg-white p-6 rounded-2xl shadow-xl animate-bounce-slow hidden lg:block"> <div className="absolute -bottom-6 -right-6 md:-bottom-10 md:-right-10 z-20 bg-white p-4 md:p-6 rounded-xl md:rounded-2xl shadow-xl animate-bounce-slow hidden sm:block">
<div className="text-center"> <div className="text-center">
<p className="text-4xl font-bold text-[#E91E63]">5+</p> <p className="text-2xl md:text-4xl font-bold text-[#E91E63]">5+</p>
<p className="text-sm font-sans text-gray-500 uppercase tracking-wider">Év Tapasztalat</p> <p className="text-[10px] md:text-sm font-sans text-gray-500 uppercase tracking-wider">Év Tapasztalat</p>
</div> </div>
</div> </div>
</div> </div>
<div className="space-y-8"> <div className="space-y-6 md:space-y-8 text-center md:text-left px-2">
<h2 className="text-5xl font-bold text-[#5D4037] leading-tight"> <h2 className="text-4xl md:text-5xl font-bold text-[#5D4037] leading-tight">
A szenvedélyünk <br/> A szenvedélyünk <br/>
<span className="text-[#E91E63] italic">a minőség</span> <span className="text-[#E91E63] italic text-3xl md:text-4xl lg:text-5xl">a minőség</span>
</h2> </h2>
<p className="text-lg leading-relaxed text-[#795548] font-sans"> <p className="text-base md:text-lg leading-relaxed text-[#795548] font-sans">
2018 óta készítjük desszertjeinket Budapest szívében. Hiszünk abban, hogy egy sütemény nemcsak étel, hanem élmény. Ezért kizárólag prémium belga csokoládét, termelői tejet és friss gyümölcsöket használunk. 2018 óta készítjük desszertjeinket Budapest szívében. Hiszünk abban, hogy egy sütemény nemcsak étel, hanem élmény.
</p> </p>
<div className="grid gap-6"> <div className="grid gap-4 md:gap-6">
{[ {[
{ text: '100% Természetes alapanyagok', icon: Heart }, { text: '100% Természetes alapanyagok', icon: Heart },
{ text: 'Glutén- és laktózmentes opciók', icon: Star }, { text: 'Glutén- és laktózmentes opciók', icon: Star },
{ text: 'Egyedi tortarendelés 48 órán belül', icon: Clock } { text: 'Egyedi tortarendelés 48 órán belül', icon: Clock }
].map((item, i) => ( ].map((item, i) => (
<div key={i} className="flex items-center gap-4 p-4 rounded-xl bg-[#FFF5F5] border border-[#FF80AB]/20 transition-all hover:shadow-md hover:bg-[#fff0f0]"> <div key={i} className="flex items-center gap-4 p-3 md:p-4 rounded-xl bg-[#FFF5F5] border border-[#FF80AB]/20 transition-all">
<div className="w-10 h-10 rounded-full bg-white flex items-center justify-center text-[#E91E63] shadow-sm"> <div className="w-8 h-8 md:w-10 md:h-10 rounded-full bg-white flex items-center justify-center text-[#E91E63] shadow-sm flex-shrink-0">
<item.icon className="w-5 h-5" /> <item.icon className="w-4 h-4 md:w-5 h-5" />
</div> </div>
<span className="font-bold text-[#5D4037]">{item.text}</span> <span className="font-bold text-[#5D4037] text-sm md:text-base">{item.text}</span>
</div> </div>
))} ))}
</div> </div>
@@ -150,16 +173,16 @@ export const SweetCraving: React.FC = () => {
</section> </section>
{/* Menu Grid */} {/* Menu Grid */}
<section id="menu" className="py-32 bg-[#FFF5F5]"> <section id="menu" className="py-20 md:py-32 bg-[#FFF5F5]">
<div className="max-w-6xl mx-auto px-6"> <div className="max-w-6xl mx-auto px-4 md:px-6">
<div className="text-center mb-20"> <div className="text-center mb-12 md:mb-20">
<h2 className="text-5xl font-bold mb-6 text-[#5D4037]">Legnépszerűbb Finomságok</h2> <h2 className="text-4xl md:text-5xl font-bold mb-4 md:mb-6 text-[#5D4037]">Kínálatunk</h2>
<p className="text-[#795548] text-xl max-w-2xl mx-auto font-sans"> <p className="text-[#795548] text-base md:text-xl max-w-2xl mx-auto font-sans px-4">
Válogasson kedvenc süteményeink közül, melyeket minden reggel frissen készítünk. Válogasson kedvenc süteményeink közül, melyeket minden reggel frissen készítünk.
</p> </p>
</div> </div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-10"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-10">
{[ {[
{ title: 'Macaron Válogatás', price: '3 490 Ft', img: 'https://images.unsplash.com/photo-1569864358642-9d1684040f43?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80', tag: 'Best Seller' }, { title: 'Macaron Válogatás', price: '3 490 Ft', img: 'https://images.unsplash.com/photo-1569864358642-9d1684040f43?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80', tag: 'Best Seller' },
{ title: 'Epres Sajttorta', price: '1 290 Ft', img: 'https://images.unsplash.com/photo-1533134242443-d4fd215305ad?auto=format&fit=crop&w=800&q=80', tag: null }, { title: 'Epres Sajttorta', price: '1 290 Ft', img: 'https://images.unsplash.com/photo-1533134242443-d4fd215305ad?auto=format&fit=crop&w=800&q=80', tag: null },
@@ -168,96 +191,87 @@ export const SweetCraving: React.FC = () => {
{ title: 'Cupcake Mix', price: '2 990 Ft', img: 'https://images.unsplash.com/photo-1519869325930-281384150729?auto=format&fit=crop&w=800&q=80', tag: null }, { title: 'Cupcake Mix', price: '2 990 Ft', img: 'https://images.unsplash.com/photo-1519869325930-281384150729?auto=format&fit=crop&w=800&q=80', tag: null },
{ title: 'Vajas Croissant', price: '890 Ft', img: 'https://images.unsplash.com/photo-1509440159596-0249088772ff?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80', tag: 'Friss' } { title: 'Vajas Croissant', price: '890 Ft', img: 'https://images.unsplash.com/photo-1509440159596-0249088772ff?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80', tag: 'Friss' }
].map((item, i) => ( ].map((item, i) => (
<div key={i} className="group bg-white rounded-3xl p-4 shadow-md hover:shadow-2xl transition-all duration-500 hover:-translate-y-2"> <div key={i} className="group bg-white rounded-3xl p-4 shadow-md hover:shadow-2xl transition-all duration-500">
<div className="overflow-hidden rounded-2xl mb-6 h-64 relative"> <div className="overflow-hidden rounded-2xl mb-4 md:mb-6 h-48 md:h-64 relative">
<img <img
src={item.img} src={item.img}
alt={item.title} alt={item.title}
className="w-full h-full object-cover transform group-hover:scale-110 transition-transform duration-700" className="w-full h-full object-cover transform group-hover:scale-110 transition-transform duration-700"
/> />
{item.tag && ( {item.tag && (
<div className="absolute top-4 left-4 bg-white/90 backdrop-blur px-3 py-1 rounded-full text-xs font-bold text-[#E91E63] uppercase tracking-wider shadow-sm"> <div className="absolute top-4 left-4 bg-white/90 backdrop-blur px-3 py-1 rounded-full text-[10px] font-bold text-[#E91E63] uppercase tracking-wider">
{item.tag} {item.tag}
</div> </div>
)} )}
{/* Quick Add Overlay */}
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
<button className="bg-white text-[#E91E63] px-6 py-2 rounded-full font-bold transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
Kosárba
</button>
</div>
</div> </div>
<div className="px-2 pb-2"> <div className="px-2 pb-2 text-center sm:text-left">
<div className="flex justify-between items-start mb-2"> <div className="flex flex-col sm:flex-row justify-between items-center sm:items-start mb-2 gap-2">
<h3 className="text-2xl font-bold text-[#5D4037] group-hover:text-[#E91E63] transition-colors">{item.title}</h3> <h3 className="text-xl md:text-2xl font-bold text-[#5D4037]">{item.title}</h3>
<span className="text-lg font-bold text-[#E91E63] bg-[#FFF5F5] px-3 py-1 rounded-lg">{item.price}</span> <span className="text-base md:text-lg font-bold text-[#E91E63] bg-[#FFF5F5] px-3 py-0.5 rounded-lg">{item.price}</span>
</div> </div>
<p className="text-gray-500 text-sm line-clamp-2">Krémes, ízletes finomság, amely elolvad a szádban.</p> <p className="text-gray-500 text-xs md:text-sm line-clamp-2">Krémes, ízletes finomság, amely elolvad a szádban.</p>
</div> </div>
</div> </div>
))} ))}
</div> </div>
<div className="mt-16 text-center"> <div className="mt-12 md:mt-16 text-center">
<button className="border-2 border-[#E91E63] text-[#E91E63] px-10 py-3 rounded-full font-bold hover:bg-[#E91E63] hover:text-white transition-all duration-300 uppercase tracking-wider text-sm"> <button className="border-2 border-[#E91E63] text-[#E91E63] px-8 md:px-10 py-3 rounded-full font-bold hover:bg-[#E91E63] hover:text-white transition-all uppercase tracking-wider text-xs md:text-sm">
Teljes étlap letöltése Teljes étlap letöltése
</button> </button>
</div> </div>
</div> </div>
</section> </section>
{/* Testimonials (Simple) */} {/* Testimonials */}
<section className="py-24 bg-white"> <section className="py-20 md:py-24 bg-white px-4">
<div className="max-w-4xl mx-auto px-6 text-center"> <div className="max-w-4xl mx-auto text-center">
<Star className="w-10 h-10 text-yellow-400 fill-current mx-auto mb-6" /> <Star className="w-8 h-8 md:w-10 md:h-10 text-yellow-400 fill-current mx-auto mb-6" />
<h2 className="text-4xl font-bold mb-8 text-[#5D4037]">Vendégeink mondták</h2> <h2 className="text-3xl md:text-4xl font-bold mb-6 md:mb-8 text-[#5D4037]">Vendégeink mondták</h2>
<blockquote className="text-2xl italic text-gray-600 font-serif leading-relaxed mb-8"> <blockquote className="text-lg md:text-2xl italic text-gray-600 font-serif leading-relaxed mb-6 md:mb-8 px-4">
"A legfinomabb macaron, amit valaha ettem! A pisztáciás egyszerűen mennyei. Mindenkinek csak ajánlani tudom a helyet, igazi ékszerdoboz." "A legfinomabb macaron, amit valaha ettem! A pisztáciás egyszerűen mennyei. Mindenkinek csak ajánlani tudom."
</blockquote> </blockquote>
<cite className="font-bold text-[#E91E63] not-italic"> Kovács Anna, Budapest</cite> <cite className="font-bold text-[#E91E63] not-italic text-sm md:text-base"> Kovács Anna, Budapest</cite>
</div> </div>
</section> </section>
{/* Contact & Footer */} {/* Contact & Footer */}
<section id="contact" className="bg-[#5D4037] text-white py-24 px-6 relative overflow-hidden"> <section id="contact" className="bg-[#5D4037] text-white py-20 md:py-24 px-4 md:px-6 relative overflow-hidden">
{/* Background Pattern */}
<div className="absolute inset-0 opacity-5" style={{backgroundImage: 'radial-gradient(circle, #ffffff 2px, transparent 2px)', backgroundSize: '30px 30px'}}></div>
<div className="max-w-4xl mx-auto text-center relative z-10"> <div className="max-w-4xl mx-auto text-center relative z-10">
<h2 className="text-4xl font-bold mb-16">Látogass el hozzánk</h2> <h2 className="text-3xl md:text-4xl font-bold mb-12 md:mb-16">Látogass el hozzánk</h2>
<div className="grid md:grid-cols-3 gap-12 mb-16"> <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-10 md:gap-12 mb-12 md:mb-16">
<div className="flex flex-col items-center group"> <div className="flex flex-col items-center">
<div className="w-16 h-16 bg-white/10 rounded-full flex items-center justify-center mb-6 group-hover:bg-[#E91E63] transition-colors duration-300"> <div className="w-12 h-12 md:w-16 md:h-16 bg-white/10 rounded-full flex items-center justify-center mb-4 md:mb-6">
<MapPin className="w-8 h-8" /> <MapPin className="w-6 h-6 md:w-8 h-8" />
</div> </div>
<h4 className="font-bold text-xl mb-3">Címünk</h4> <h4 className="font-bold text-lg md:text-xl mb-2 md:mb-3">Címünk</h4>
<p className="text-white/70 leading-relaxed">1052 Budapest,<br/>Petőfi Sándor utca 12.</p> <p className="text-white/70 text-sm md:text-base leading-relaxed">1052 Budapest,<br/>Petőfi Sándor utca 12.</p>
</div> </div>
<div className="flex flex-col items-center group"> <div className="flex flex-col items-center">
<div className="w-16 h-16 bg-white/10 rounded-full flex items-center justify-center mb-6 group-hover:bg-[#E91E63] transition-colors duration-300"> <div className="w-12 h-12 md:w-16 md:h-16 bg-white/10 rounded-full flex items-center justify-center mb-4 md:mb-6">
<Clock className="w-8 h-8" /> <Clock className="w-6 h-6 md:w-8 h-8" />
</div> </div>
<h4 className="font-bold text-xl mb-3">Nyitvatartás</h4> <h4 className="font-bold text-lg md:text-xl mb-2 md:mb-3">Nyitvatartás</h4>
<p className="text-white/70 leading-relaxed">H-P: 08:00 - 19:00<br/>Szo-V: 09:00 - 16:00</p> <p className="text-white/70 text-sm md:text-base leading-relaxed">H-P: 08:00 - 19:00<br/>Szo-V: 09:00 - 16:00</p>
</div> </div>
<div className="flex flex-col items-center group"> <div className="flex flex-col items-center sm:col-span-2 md:col-span-1">
<div className="w-16 h-16 bg-white/10 rounded-full flex items-center justify-center mb-6 group-hover:bg-[#E91E63] transition-colors duration-300"> <div className="w-12 h-12 md:w-16 md:h-16 bg-white/10 rounded-full flex items-center justify-center mb-4 md:mb-6">
<Phone className="w-8 h-8" /> <Phone className="w-6 h-6 md:w-8 h-8" />
</div> </div>
<h4 className="font-bold text-xl mb-3">Kapcsolat</h4> <h4 className="font-bold text-lg md:text-xl mb-2 md:mb-3">Kapcsolat</h4>
<p className="text-white/70 leading-relaxed">+36 1 234 5678<br/>hello@sweetcraving.hu</p> <p className="text-white/70 text-sm md:text-base leading-relaxed">+36 1 234 5678<br/>hello@sweetcraving.hu</p>
</div> </div>
</div> </div>
<div className="flex justify-center space-x-8"> <div className="flex justify-center space-x-6 md:space-x-8">
<a href="#" className="opacity-60 hover:opacity-100 hover:text-[#E91E63] transition-all transform hover:scale-110"><Facebook className="w-8 h-8" /></a> <a href="#" className="opacity-60 hover:opacity-100 hover:text-[#E91E63] transition-all"><Facebook className="w-6 h-6 md:w-8 h-8" /></a>
<a href="#" className="opacity-60 hover:opacity-100 hover:text-[#E91E63] transition-all transform hover:scale-110"><Instagram className="w-8 h-8" /></a> <a href="#" className="opacity-60 hover:opacity-100 hover:text-[#E91E63] transition-all"><Instagram className="w-6 h-6 md:w-8 h-8" /></a>
<a href="#" className="opacity-60 hover:opacity-100 hover:text-[#E91E63] transition-all transform hover:scale-110"><Mail className="w-8 h-8" /></a> <a href="#" className="opacity-60 hover:opacity-100 hover:text-[#E91E63] transition-all"><Mail className="w-6 h-6 md:w-8 h-8" /></a>
</div> </div>
<div className="mt-16 pt-8 border-t border-white/10 text-white/40 text-sm font-sans"> <div className="mt-12 md:mt-16 pt-8 border-t border-white/10 text-white/40 text-[10px] md:text-xs font-sans">
&copy; 2024 SweetCraving. Ez egy demonstrációs weboldal a MotionWeb referenciáihoz. &copy; 2024 SweetCraving. Demonstrációs oldal.
</div> </div>
</div> </div>
</section> </section>

View File

@@ -0,0 +1,104 @@
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3'
declare const Deno: any;
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}
Deno.serve(async (req: any) => {
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}
try {
const supabase = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
)
// Fetch active subscriptions
const { data: subscriptions, error } = await supabase
.from('maintenance_subscriptions')
.select('*, order:orders(*)')
.eq('status', 'active');
if (error) throw error;
const notificationsToSend: any[] = [];
const today = new Date();
// Mock email sending function for now
const sendEmailMock = async (payload: any) => {
console.log("Mock email sent:", payload);
// In production, you would invoke the 'resend' function here
};
if (subscriptions) {
for (const sub of subscriptions) {
const billingDate = new Date(sub.next_billing_date);
const daysUntil = Math.ceil((billingDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));
// Logic: Notify if <= 30 days and not notified recently (e.g. in last 14 days)
let shouldNotify = false;
// If it's already overdue or coming up in 30 days
if (daysUntil <= 30) {
if (!sub.last_notified_at) {
shouldNotify = true;
} else {
const lastNotified = new Date(sub.last_notified_at);
const daysSinceLastNotification = Math.ceil((today.getTime() - lastNotified.getTime()) / (1000 * 60 * 60 * 24));
// Only notify if 2 weeks passed since last notification
if (daysSinceLastNotification > 14) {
shouldNotify = true;
}
}
}
if (shouldNotify) {
const payload = {
to: sub.client_email,
subject: `Emlékeztető: Éves díj esedékes (${daysUntil} nap)`,
daysLeft: daysUntil,
domain: sub.order?.details?.domainName || 'Weboldal',
subscriptionId: sub.id
};
notificationsToSend.push(payload);
// Itt hívnánk meg a sendEmail függvényt
await sendEmailMock(payload);
// Update last_notified_at to keep data consistent
const { error: updateError } = await supabase
.from('maintenance_subscriptions')
.update({ last_notified_at: new Date().toISOString() })
.eq('id', sub.id);
if (updateError) {
console.error(`Failed to update subscription ${sub.id}:`, updateError);
}
}
}
}
return new Response(
JSON.stringify({ success: true, notifications: notificationsToSend }),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 200,
}
)
} catch (err: any) {
return new Response(
JSON.stringify({ error: err.message }),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
}
)
}
})

View File

@@ -0,0 +1,90 @@
// @ts-nocheck
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { Stripe } from "https://esm.sh/stripe@12.0.0?target=deno"
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}
serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}
try {
const STRIPE_SECRET_KEY = Deno.env.get('STRIPE_SECRET_KEY')
if (!STRIPE_SECRET_KEY) {
throw new Error('STRIPE_SECRET_KEY not set in environment variables')
}
const stripe = new Stripe(STRIPE_SECRET_KEY, {
apiVersion: '2022-11-15',
httpClient: Stripe.createFetchHttpClient(),
})
const { order_id, package_name, payment_type, customer_email } = await req.json()
// Árazási logika (HUF-ban)
let priceAmount = 0
// Landing Page: 190.000 Ft (Előleg: 40.000, Vég: 150.000)
if (package_name === 'Landing Page') {
if (payment_type === 'deposit') priceAmount = 40000;
else if (payment_type === 'final') priceAmount = 150000;
}
// Pro Web: 350.000 Ft (Előleg: 80.000, Vég: 270.000)
else if (package_name === 'Pro Web') {
if (payment_type === 'deposit') priceAmount = 80000;
else if (payment_type === 'final') priceAmount = 270000;
}
if (priceAmount === 0) {
throw new Error('Invalid package or payment type')
}
// Origin meghatározása a visszairányításhoz
const origin = req.headers.get('origin') || 'https://motionweb.hu'
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: 'huf',
product_data: {
name: `${package_name} - ${payment_type === 'deposit' ? 'Előleg' : 'Fennmaradó összeg'}`,
},
unit_amount: priceAmount * 100, // Fillérben kell megadni
},
quantity: 1,
},
],
mode: 'payment',
success_url: `${origin}/#/dashboard?payment_success=true&order_id=${order_id}`,
cancel_url: `${origin}/#/dashboard?payment_cancelled=true&order_id=${order_id}`,
customer_email: customer_email,
metadata: {
order_id: order_id,
payment_type: payment_type
},
})
return new Response(
JSON.stringify({ url: session.url }),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 200,
}
)
} catch (error: any) {
console.error(error)
return new Response(
JSON.stringify({ error: error.message }),
{
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
}
)
}
})

View File

@@ -9,11 +9,14 @@ export interface Service {
export interface ProductPackage { export interface ProductPackage {
id: string; id: string;
name: string; name: string;
price: string; price: string; // Megjelenített ár szöveg (pl. "150.000 Ft" vagy "Egyedi árazás")
desc: string; // Description total_price?: number; // Numerikus teljes ár
advance_price?: number; // Numerikus előleg
is_custom_price?: boolean; // Egyedi árazás jelző
desc: string;
features: string[]; features: string[];
isPopular?: boolean; isPopular?: boolean;
cta: string; // Call to Action button text cta: string;
} }
export interface Reference { export interface Reference {
@@ -42,3 +45,13 @@ export interface Invoice {
status: 'paid' | 'pending' | 'overdue'; status: 'paid' | 'pending' | 'overdue';
pdf_url?: string; pdf_url?: string;
} }
export interface MaintenanceSubscription {
id: string;
order_id: string;
client_email: string;
start_date: string;
next_billing_date: string;
status: 'active' | 'overdue' | 'cancelled';
last_notified_at?: string;
}