diff --git a/index.html b/index.html index 9d38f93..9e43ed4 100644 --- a/index.html +++ b/index.html @@ -64,7 +64,8 @@ "lucide-react": "https://esm.sh/lucide-react@0.344.0?deps=react@18.2.0", "@supabase/supabase-js": "https://esm.sh/@supabase/supabase-js@2.39.7", "react-dom/": "https://esm.sh/react-dom@^19.2.3/", - "react/": "https://esm.sh/react@^19.2.3/" + "react/": "https://esm.sh/react@^19.2.3/", + "@google/genai": "https://esm.sh/@google/genai@^1.34.0" } } diff --git a/motion-web-studio-0.1-login-order-status.zip b/motion-web-stúdió2.0.zip similarity index 94% rename from motion-web-studio-0.1-login-order-status.zip rename to motion-web-stúdió2.0.zip index 4dea16d..dc00cae 100644 Binary files a/motion-web-studio-0.1-login-order-status.zip and b/motion-web-stúdió2.0.zip differ diff --git a/package.json b/package.json index d30e329..09bc09e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "react-dom": "^19.2.3", "react-router-dom": "6.22.3", "lucide-react": "0.344.0", - "@supabase/supabase-js": "2.39.7" + "@supabase/supabase-js": "2.39.7", + "@google/genai": "^1.34.0" }, "devDependencies": { "@types/node": "^22.14.0", diff --git a/pages/Admin.tsx b/pages/Admin.tsx index 390c57c..1e43abe 100644 --- a/pages/Admin.tsx +++ b/pages/Admin.tsx @@ -32,6 +32,7 @@ interface EmailLogEntry { id: string; email_type: string; sent_at: string; + body?: string; } interface AdminOrder { @@ -49,6 +50,122 @@ interface AdminOrder { emailLogs?: EmailLogEntry[]; } +const getEmailTemplate = (type: string, data: { customer: string, package: string, demoUrl?: string }) => { + const baseStyle = "font-family: 'Inter', Helvetica, Arial, sans-serif; line-height: 1.6; color: #1a1a1a; max-width: 600px; margin: 0 auto; padding: 40px 20px; border: 1px solid #f0f0f0; border-radius: 24px; background-color: #ffffff;"; + const headerStyle = "color: #7c3aed; font-size: 28px; font-weight: 800; margin-bottom: 24px; letter-spacing: -0.02em; border-bottom: 1px solid #f0f0f0; padding-bottom: 20px;"; + const footerStyle = "margin-top: 40px; padding-top: 24px; border-top: 1px solid #f0f0f0; font-size: 13px; color: #94a3b8;"; + const buttonStyle = "display: inline-block; background-color: #7c3aed; color: #ffffff !important; padding: 14px 28px; text-decoration: none; border-radius: 12px; font-weight: 700; margin: 20px 0; font-size: 15px;"; + + const templates: Record = { + 'Fejlesztés megkezdése': { + subject: `Projekt Indítása: Megkezdtük a fejlesztést - ${data.package}`, + body: `
+
MotionWeb
+

Kedves ${data.customer}!

+

Örömmel értesítjük, hogy a ${data.package} csomagjához tartozó fejlesztési folyamat a mai napon hivatalosan is elindult.

+

Szakembereink elkezdték a weboldal vázlatának és design elemeinek kidolgozását. Amint elkészülünk az első megtekinthető demó verzióval, azonnal jelentkezünk a hozzáférési linkkel.

+

Köszönjük a bizalmát!

+
+ Üdvözlettel,
+ Balogh Bence
+ MotionWeb Stúdió | motionweb.hu +
+
` + }, + 'Demó oldal elkészült': { + subject: `Elkészült a weboldal demó verziója - ${data.package}`, + body: `
+
MotionWeb
+

Kedves ${data.customer}!

+

Jó hírünk van: elkészültünk weboldala első, interaktív bemutató verziójával!

+

A demó oldalt az alábbi biztonságos linken tudja megtekinteni:

+
+ DEMÓ MEGTEKINTÉSE +
+

Kérjük, nézze át az oldalt, és a MotionWeb ügyfélkapujában a Rendeléseim menüpont alatt küldje el visszajelzését, hogy rögzíthessük az esetleges módosítási kéréseit.

+
+ Üdvözlettel,
+ Balogh Bence
+ MotionWeb Stúdió | motionweb.hu +
+
` + }, + 'Módosítások fejlesztése': { + subject: `Visszajelzés rögzítve: Módosítások folyamatban`, + body: `
+
MotionWeb
+

Kedves ${data.customer}!

+

Köszönjük részletes visszajelzését! A kért módosításokat rögzítettük és szakembereink már dolgoznak azok átvezetésén.

+

Amint a frissített verzió megtekinthető lesz, e-mailben ismét értesíteni fogjuk.

+
+ Üdvözlettel,
+ Balogh Bence
+ MotionWeb Stúdió | motionweb.hu +
+
` + }, + '1 hete nincs visszajelzés': { + subject: `Emlékeztető: Visszajelzés várható a demó oldallal kapcsolatban`, + body: `
+
MotionWeb
+

Kedves ${data.customer}!

+

Szeretnénk emlékeztetni, hogy egy héttel ezelőtt küldtük el Önnek a weboldal demó verzióját.

+

Annak érdekében, hogy tartsuk a fejlesztési ütemtervet, kérjük, amint ideje engedi, nézze át a tervet és küldje el véleményét az ügyfélkapun keresztül.

+
+ Üdvözlettel,
+ Balogh Bence
+ MotionWeb Stúdió | motionweb.hu +
+
` + }, + '2 hete nincs visszajelzés': { + subject: `Fontos: Továbblépéshez szükséges visszajelzés hiánya`, + body: `
+
MotionWeb
+

Kedves ${data.customer}!

+

Szeretnénk felhívni figyelmét, hogy weboldala demó verziója már két hete várakozik az Ön jóváhagyására.

+

Amennyiben elégedett a látottakkal, kérjük, jelezze azt a felületen a véglegesítés megkezdéséhez. Bármilyen kérdés vagy észrevétel esetén állunk rendelkezésére.

+
+ Üdvözlettel,
+ Balogh Bence
+ MotionWeb Stúdió | motionweb.hu +
+
` + }, + 'Projekt lezárva (Nincs válasz)': { + subject: `Értesítés: Projekt adminisztratív lezárása - ${data.package}`, + body: `
+
MotionWeb
+

Kedves ${data.customer}!

+

Sajnálattal értesítjük, hogy mivel az elmúlt időszakban többszöri megkeresésünkre sem érkezett válasz, a ${data.package} projektet a mai napon adminisztratív okokból lezártnak tekintjük.

+

Amennyiben a jövőben folytatni szeretné a fejlesztést, kérjük, vegye fel velünk a kapcsolatot egy új ütemterv egyeztetése érdekében.

+
+ Üdvözlettel,
+ Balogh Bence
+ MotionWeb Stúdió | motionweb.hu +
+
` + }, + 'Végleges oldal elérhető': { + subject: `Gratulálunk! Weboldala elkészült és élesítésre került`, + body: `
+
MotionWeb
+

Kedves ${data.customer}!

+

Örömmel jelentjük, hogy a ${data.package} projektünk sikeresen befejeződött!

+

A weboldalt élesítettük, így az mostantól minden látogató számára elérhető a végleges domain címen.

+

Köszönjük, hogy minket választott digitális partnerének. Kérjük, amennyiben elégedett volt a munkánkkal, ajánljon minket ismerőseinek is!

+
+ Üdvözlettel,
+ Balogh Bence
+ MotionWeb Stúdió | motionweb.hu +
+
` + } + }; + + return templates[type] || { subject: 'Értesítés a MotionWeb-től', body: 'Üzenete érkezett a MotionWeb Stúdiótól.' }; +}; + export const Admin: React.FC = () => { const { user, isAdmin, loading } = useAuth(); const navigate = useNavigate(); @@ -149,11 +266,17 @@ export const Admin: React.FC = () => { const fetchEmailLogs = async (orderId: string) => { if (!isSupabaseConfigured) return []; try { - const { data } = await supabase + // Megpróbáljuk lekérni, de ha hiányzik oszlop vagy tábla, hibatűrően kezeljük + const { data, error } = await supabase .from('email_log') .select('*') .eq('order_id', orderId) .order('sent_at', { ascending: false }); + + if (error) { + console.error("Email log fetch error:", error.message); + return []; + } return data || []; } catch (e) { console.warn("Could not fetch email_log table."); @@ -213,6 +336,10 @@ export const Admin: React.FC = () => { setOrders(prev => prev.map(o => o.id === orderId ? { ...o, status: targetStatus, details: updatedDetails } : o)); setViewOrder({ ...viewOrder, status: targetStatus, details: updatedDetails, history: newHist }); + if (demoUrlInput.startsWith('http')) { + handleSendEmail('Demó oldal elkészült'); + } + alert(`Sikeres mentés és visszajelzés kérése!`); } else { setViewOrder({ ...viewOrder, details: updatedDetails }); @@ -240,25 +367,62 @@ export const Admin: React.FC = () => { setEmailSending(emailType); try { - console.log(`Email notification trigger: ${emailType}`); - + const template = getEmailTemplate(emailType, { + customer: viewOrder.customer, + package: viewOrder.package, + demoUrl: demoUrlInput || viewOrder.details?.demoUrl + }); + if (isSupabaseConfigured) { - const { error } = await supabase.from('email_log').insert({ - order_id: viewOrder.id, - email_type: emailType + // MEGHÍVJUK A FÜGGVÉNYT + const response = await supabase.functions.invoke('resend', { + body: { + to: viewOrder.email, + subject: template.subject, + html: template.body + } }); - - if (error) throw error; + + // Supabase hiba kezelése (az invoke hiba objektumot ad vissza, ha a hívás sikertelen) + if (response.error) { + let errorDetail = response.error.message; + if (errorDetail.includes('API kulcs hiányzik')) { + throw new Error("HIÁNYZIK A BEÁLLÍTÁS: A Supabase Dashboardon az Edge Functions -> Secrets menüpontban fel kell venni a RESEND_API_KEY kulcsot!"); + } + throw new Error(errorDetail); + } + + // A függvény által visszaadott egyedi hiba (ha van) + if (response.data && response.data.error) { + throw new Error(response.data.error); + } + + // SIKERES KÜLDÉS NAPLÓZÁSA (Hibatűrő módon) + try { + const { error: logError } = await supabase.from('email_log').insert({ + order_id: viewOrder.id, + email_type: emailType, + body: template.body + }); + + if (logError) { + console.error("Adatbázis naplózási hiba (lehet, hogy hiányzik a 'body' oszlop):", logError.message); + // Itt nem dobunk hibát, mert az email már kiment! Csak logolunk a konzolra. + } + } catch (dbErr) { + console.error("Váratlan hiba az adatbázisba íráskor:", dbErr); + } const newLogs = await fetchEmailLogs(viewOrder.id); setViewOrder({ ...viewOrder, emailLogs: newLogs }); - alert(`E-mail ("${emailType}") naplózva és kiküldve (szimulált).`); + alert(`Sikeres küldés! Az értesítőt kiküldtük ${viewOrder.email} címre.`); } else { - alert(`E-mail értesítő előkészítve: "${emailType}"\n\nJelenleg ez a funkció csak placeholder.`); + alert(`DEMO MÓD: Tárgy: ${template.subject}`); } } catch (e: any) { - alert("Hiba az e-mail naplózásakor: " + e.message); + console.error("Hiba az e-mail folyamatban:", e); + alert("Hiba az e-mail küldésekor:\n\n" + e.message); } finally { setEmailSending(null); } @@ -468,10 +632,9 @@ export const Admin: React.FC = () => { - {/* EMAIL NOTIFICATIONS & LOGS COMBINED */}
-

E-mail értesítők

+

E-mail értesítők (Közvetlen sablonok)

{[ { label: 'Fejlesztés megkezdése', icon: Rocket }, @@ -493,7 +656,9 @@ export const Admin: React.FC = () => {

{email.label}

-

Értesítő küldése

+

+ {emailSending === email.label ? 'Küldés folyamatban...' : 'E-mail küldése'} +

@@ -501,7 +666,6 @@ export const Admin: React.FC = () => {
- {/* IN-PLACE EMAIL LOG */}

Korábban kiküldött e-mailek

@@ -510,8 +674,13 @@ export const Admin: React.FC = () => {
-

{log.email_type}

-

{new Date(log.sent_at).toLocaleString('hu-HU')}

+
+

{log.email_type}

+

{new Date(log.sent_at).toLocaleString('hu-HU')}

+
+ {log.body && ( +
+ )}
)) @@ -557,7 +726,7 @@ export const Admin: React.FC = () => { disabled={savingDemoUrl} className="bg-blue-600 hover:bg-blue-700 text-white font-black px-6 py-4 rounded-2xl text-xs uppercase tracking-widest transition-all disabled:opacity-50 shadow-lg shadow-blue-200" > - {savingDemoUrl ? 'MENTÉS...' : 'PUBLIKÁLÁS ÉS VISSZAJELZÉS KÉRÉSE'} + {savingDemoUrl ? 'MENTÉS...' : 'PUBLIKÁLÁS ÉS ÉRTESÍTÉS'}
diff --git a/pages/auth/Login.tsx b/pages/auth/Login.tsx index 6a37641..6b3ab27 100644 --- a/pages/auth/Login.tsx +++ b/pages/auth/Login.tsx @@ -3,7 +3,7 @@ import { Link, useNavigate } from 'react-router-dom'; import { supabase, isSupabaseConfigured } from '../../lib/supabaseClient'; import { Button } from '../../components/Button'; import { useAuth } from '../../context/AuthContext'; -import { LogIn, AlertCircle, ArrowLeft, RefreshCw, Mail, ShieldCheck } from 'lucide-react'; +import { LogIn, AlertCircle, ArrowLeft, RefreshCw, Mail } from 'lucide-react'; export const Login: React.FC = () => { const navigate = useNavigate(); @@ -46,20 +46,22 @@ export const Login: React.FC = () => { if (error) { console.error('Login error:', error); + + // Specifikus hibaüzenetek kezelése if (error.message.includes('Invalid login credentials')) { - setError('Helytelen e-mail cím vagy jelszó. Kérjük, győződjön meg róla, hogy megerősítette az e-mail címét!'); + setError('Helytelen e-mail cím vagy jelszó. Ha most regisztráltál, ellenőrizd a postafiókodat és kattints a megerősítő linkre!'); setNeedsConfirmation(true); } else if (error.message.includes('Email not confirmed')) { - setError('Az e-mail cím még nincs megerősítve.'); + setError('Az e-mail címed még nincs megerősítve. Kérjük, kattints a regisztrációkor kapott linkre!'); setNeedsConfirmation(true); } else { - setError('Hiba történt a bejelentkezés során: ' + error.message); + setError('Hiba történt: ' + error.message); } } else { navigate('/dashboard'); } } catch (err: any) { - setError('Váratlan hiba történt.'); + setError('Váratlan hiba történt a bejelentkezés során.'); } finally { setLoading(false); } @@ -86,9 +88,10 @@ export const Login: React.FC = () => { setError('Hiba az újraküldéskor: ' + error.message); } else { setResendSuccess(true); + setNeedsConfirmation(false); } } catch (err: any) { - setError('Hiba történt.'); + setError('Hiba történt az e-mail újraküldésekor.'); } finally { setResendLoading(false); } @@ -99,22 +102,22 @@ export const Login: React.FC = () => {

Bejelentkezés

-

Jelentkezzen be fiókjába a folytatáshoz.

+

Lépjen be fiókjába a kezeléshez.

-
+
{error && ( -
+
-

{error}

+

{error}

{needsConfirmation && ( -
-
)} @@ -122,47 +125,43 @@ export const Login: React.FC = () => { )} {resendSuccess && ( -
+
-

A megerősítő e-mailt újraküldtük!

+

A megerősítő linket újra elküldtük!

)} -
- -
- setEmail(e.target.value)} className="appearance-none block w-full px-4 py-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm bg-white text-gray-900" /> +
+
+ + setEmail(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="pelda@email.hu" /> +
+ +
+
+ + Elfelejtette? +
+ 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="••••••••" />
-
- - Elfelejtette? -
-
- setPassword(e.target.value)} className="appearance-none block w-full px-4 py-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-primary focus:border-primary sm:text-sm bg-white text-gray-900" /> -
-
- -
-
-
-
Nincs még fiókod?
-
- Regisztrálj ingyenesen -
+
+

Nincs még fiókod?

+ Regisztrálj ingyenesen
- - Vissza a főoldalra + + Vissza a főoldalra