From c4fe22135031f1a500d16ef128b2e47f0c2df9ef Mon Sep 17 00:00:00 2001
From: DanielS
Date: Tue, 30 Jun 2026 21:26:37 +0200
Subject: [PATCH 1/5] Update external links to real URLs for Zulip, Wiki,
Support
---
shop/components/HomeClient.tsx | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/shop/components/HomeClient.tsx b/shop/components/HomeClient.tsx
index 42a18f1..268a9e8 100644
--- a/shop/components/HomeClient.tsx
+++ b/shop/components/HomeClient.tsx
@@ -237,7 +237,7 @@ export function HomeClient({ initialUser }: HomeClientProps) {
{/* Card 1 */}
-
@@ -252,10 +252,10 @@ export function HomeClient({ initialUser }: HomeClientProps) {
Sie möchten sich mit anderen CASPOS Partnern austauschen, Fragen stellen oder Feedback geben? Treten Sie unserem Zulip-Chat bei.
-
+
{/* Card 2 */}
-
@@ -270,10 +270,10 @@ export function HomeClient({ initialUser }: HomeClientProps) {
Ihr Wissens-Portal für die CASPOS Produktfamilie.
-
+
{/* Card 3 */}
-
@@ -288,7 +288,7 @@ export function HomeClient({ initialUser }: HomeClientProps) {
Sie haben ein Problem in der CASPOS? Wir helfen Ihnen gerne weiter! Erstellen Sie jetzt ein Ticket über unser Ticketsystem.
-
+
From 541a9651ecdc627beb47081441c5f72831a91c3b Mon Sep 17 00:00:00 2001
From: DanielS
Date: Tue, 30 Jun 2026 22:00:38 +0200
Subject: [PATCH 2/5] Fix recent orders component UI and styling
---
shop/app/globals.css | 2 +-
shop/components/HomeClient.tsx | 6 +--
shop/components/NavbarClient.tsx | 2 +-
shop/components/admin/recent-orders.tsx | 65 +++++++++++-------------
shop/public/assets/CASPOS-logo.webp | Bin 0 -> 8540 bytes
5 files changed, 35 insertions(+), 40 deletions(-)
create mode 100644 shop/public/assets/CASPOS-logo.webp
diff --git a/shop/app/globals.css b/shop/app/globals.css
index f777ed7..83ae263 100644
--- a/shop/app/globals.css
+++ b/shop/app/globals.css
@@ -10,7 +10,7 @@
--card-foreground: 220 40% 2%;
--popover: 0 0% 100%;
--popover-foreground: 220 40% 2%;
- --primary: 220 90% 56%;
+ --primary: 199 100% 43%;
--primary-foreground: 0 0% 100%;
--secondary: 220 14% 90%;
--secondary-foreground: 220 40% 2%;
diff --git a/shop/components/HomeClient.tsx b/shop/components/HomeClient.tsx
index 268a9e8..d242b0f 100644
--- a/shop/components/HomeClient.tsx
+++ b/shop/components/HomeClient.tsx
@@ -121,7 +121,7 @@ export function HomeClient({ initialUser }: HomeClientProps) {
>
- CASPOS Lizenz-Order-Portal
+ CASPOS Lizenz-Portal
{/* Headline */}
@@ -249,7 +249,7 @@ export function HomeClient({ initialUser }: HomeClientProps) {
Zulip
- Sie möchten sich mit anderen CASPOS Partnern austauschen, Fragen stellen oder Feedback geben? Treten Sie unserem Zulip-Chat bei.
+ Treten Sie unserem Partner-Chat bei! tauschen Sie sich mit anderen CASPOS Partnern aus.
@@ -285,7 +285,7 @@ export function HomeClient({ initialUser }: HomeClientProps) {
Support
- Sie haben ein Problem in der CASPOS? Wir helfen Ihnen gerne weiter! Erstellen Sie jetzt ein Ticket über unser Ticketsystem.
+ Sie haben ein technisches Problem in der CASPOS? Erstellen Sie jetzt ein Ticket!
diff --git a/shop/components/NavbarClient.tsx b/shop/components/NavbarClient.tsx
index 3b111c3..78d6daf 100644
--- a/shop/components/NavbarClient.tsx
+++ b/shop/components/NavbarClient.tsx
@@ -98,7 +98,7 @@ export function NavbarClient({ user, role = "partner" }: NavbarClientProps) {
<>
- CASPOS Shop
+
Demo
diff --git a/shop/components/admin/recent-orders.tsx b/shop/components/admin/recent-orders.tsx
index 75e1bd6..3ea7fa2 100644
--- a/shop/components/admin/recent-orders.tsx
+++ b/shop/components/admin/recent-orders.tsx
@@ -74,43 +74,41 @@ export function AdminRecentOrders() {
return () => clearInterval(interval)
}, [])
- return (
-
-
-
- Übersicht (letzte 6 Monate)
-
-
-
-
-
+ return (
+
+
+
+ Übersicht (letzte 6 Monate)
+
+
+
+
+
-
-
- Neue Bestellungen
-
- Aktualisiert: {lastChecked.toLocaleTimeString('de-DE')}
-
-
-
- {orders.length === 0 ? (
- Noch keine Bestellungen
- ) : (
-
- {orders.map(order => {
+
+
+
Neue Bestellungen
+
+ Aktualisiert: {lastChecked.toLocaleTimeString('de-DE')}
+
+
+
+ {orders.length === 0 ? (
+
Noch keine Bestellungen
+ ) : (
+ orders.map(order => {
const isNew = newOrderIds.has(order.id)
const customerName =
order.customer_data?.company_name ||
`${order.customer_data?.first_name ?? ''} ${order.customer_data?.last_name ?? ''}`.trim() ||
'Unbekannt'
-
return (
@@ -124,18 +122,15 @@ export function AdminRecentOrders() {
{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(order.total_price)}
-
- {statusLabel[order.status] ?? order.status}
-
+
{statusLabel[order.status] ?? order.status}
)
- })}
-
- )}
-
-
-
- )
+ })
+ )}
+
+
+
+ )
}
diff --git a/shop/public/assets/CASPOS-logo.webp b/shop/public/assets/CASPOS-logo.webp
new file mode 100644
index 0000000000000000000000000000000000000000..4e8f66d26b6fdec5dc09d0a3f76ea7339724943e
GIT binary patch
literal 8540
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
literal 0
HcmV?d00001
From 492721679458d5b1a4c642f979d7f416252a4053 Mon Sep 17 00:00:00 2001
From: DanielS
Date: Tue, 30 Jun 2026 22:09:12 +0200
Subject: [PATCH 3/5] limit recent orders visibility to last 5
---
shop/components/admin/recent-orders.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/shop/components/admin/recent-orders.tsx b/shop/components/admin/recent-orders.tsx
index 3ea7fa2..205d368 100644
--- a/shop/components/admin/recent-orders.tsx
+++ b/shop/components/admin/recent-orders.tsx
@@ -92,11 +92,11 @@ export function AdminRecentOrders() {
Aktualisiert: {lastChecked.toLocaleTimeString('de-DE')}
-
+
{orders.length === 0 ? (
Noch keine Bestellungen
) : (
- orders.map(order => {
+ orders.slice(0, 5).map(order => {
const isNew = newOrderIds.has(order.id)
const customerName =
order.customer_data?.company_name ||
From 8f447d52e53365407bed785e7ac84a7dd463bc95 Mon Sep 17 00:00:00 2001
From: DanielS
Date: Tue, 30 Jun 2026 22:28:30 +0200
Subject: [PATCH 4/5] Add lockout logic and email notification utils
---
shop/lib/actions/auth.ts | 27 +++++++++++++++++++++++++++
shop/lib/utils/email.ts | 25 +++++++++++++++++++++++++
2 files changed, 52 insertions(+)
create mode 100644 shop/lib/utils/email.ts
diff --git a/shop/lib/actions/auth.ts b/shop/lib/actions/auth.ts
index 23d255a..8b45ce3 100644
--- a/shop/lib/actions/auth.ts
+++ b/shop/lib/actions/auth.ts
@@ -3,6 +3,7 @@
import { createClient } from '@/lib/supabase/server'
import { createAdminClient } from '@/lib/supabase/admin'
import { headers } from 'next/headers'
+import { sendLockoutEmail } from '@/lib/utils/email'
export async function signIn(email: string, password: string) {
try {
@@ -12,6 +13,32 @@ export async function signIn(email: string, password: string) {
password,
})
if (error) {
+ // Track failed attempts
+ const { data: usr, error: usrError } = await supabase
+ .from('users')
+ .select('failed_attempts, email')
+ .eq('email', email)
+ .single()
+
+ const attempts = (usr?.failed_attempts ?? 0) + 1
+
+ // Update attempts count
+ await supabase
+ .from('users')
+ .update({ failed_attempts: attempts })
+ .eq('email', email)
+
+ // Lock account on 5th failure
+ if (attempts >= 5) {
+ await supabase
+ .from('users')
+ .update({ role: 'gesperrt' })
+ .eq('email', email)
+ // Notify admin
+ await sendLockoutEmail('info@hephex.de')
+ return { success: false, error: 'Konto gesperrt nach 5 Fehlversuchen.' }
+ }
+
return { success: false, error: error.message }
}
diff --git a/shop/lib/utils/email.ts b/shop/lib/utils/email.ts
new file mode 100644
index 0000000..ab3dcca
--- /dev/null
+++ b/shop/lib/utils/email.ts
@@ -0,0 +1,25 @@
+'use server'
+
+import nodemailer from 'nodemailer'
+
+export async function sendLockoutEmail(to: string) {
+ const transporter = nodemailer.createTransport({
+ host: process.env.SMTP_HOST,
+ port: Number(process.env.SMTP_PORT),
+ secure: process.env.SMTP_SECURE === 'true',
+ auth: {
+ user: process.env.SMTP_USER,
+ pass: process.env.SMTP_PASS,
+ },
+ })
+
+ const message = {
+ from: `"Admin" <${process.env.SMTP_FROM}>`,
+ to,
+ subject: 'Konto gesperrt',
+ text: 'Ihr Konto wurde wegen zu vieler falscher Passwortversuche gesperrt.',
+ html: `Ihr Konto wurde gesperrt, weil das Passwort zu oft falsch eingegeben wurde.
`,
+ }
+
+ await transporter.sendMail(message)
+}
From f3baada896785d9743b99ccdfa57b87504a54a12 Mon Sep 17 00:00:00 2001
From: DanielS
Date: Tue, 30 Jun 2026 22:36:40 +0200
Subject: [PATCH 5/5] limit recent orders visibility to last 3
---
shop/components/admin/recent-orders.tsx | 107 ++++++++++++------------
1 file changed, 53 insertions(+), 54 deletions(-)
diff --git a/shop/components/admin/recent-orders.tsx b/shop/components/admin/recent-orders.tsx
index 205d368..3d43290 100644
--- a/shop/components/admin/recent-orders.tsx
+++ b/shop/components/admin/recent-orders.tsx
@@ -74,63 +74,62 @@ export function AdminRecentOrders() {
return () => clearInterval(interval)
}, [])
- return (
-
-
-
- Übersicht (letzte 6 Monate)
-
-
-
-
-
+ return (
+
+
+
+ Übersicht (letzte 6 Monate)
+
+
+
+
+
-
-
-
Neue Bestellungen
-
- Aktualisiert: {lastChecked.toLocaleTimeString('de-DE')}
-
-
-
- {orders.length === 0 ? (
-
Noch keine Bestellungen
- ) : (
- orders.slice(0, 5).map(order => {
- const isNew = newOrderIds.has(order.id)
- const customerName =
- order.customer_data?.company_name ||
- `${order.customer_data?.first_name ?? ''} ${order.customer_data?.last_name ?? ''}`.trim() ||
- 'Unbekannt'
- return (
-
-
+
+
Neue Bestellungen
+
+ Aktualisiert: {lastChecked.toLocaleTimeString('de-DE')}
+
+
+
+ {orders.length === 0 ? (
+
Noch keine Bestellungen
+ ) : (
+ orders.slice(0, 3).map(order => {
+ const isNew = newOrderIds.has(order.id)
+ const customerName =
+ order.customer_data?.company_name ||
+ `${order.customer_data?.first_name ?? ''} ${order.customer_data?.last_name ?? ''}`.trim() ||
+ 'Unbekannt'
+ return (
+
+
-
- {customerName.slice(0, 2).toUpperCase()}
-
-
-
{customerName}
-
#{order.order_number}
-
-
-
- {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(order.total_price)}
-
-
{statusLabel[order.status] ?? order.status}
-
+ >
+
+ {customerName.slice(0, 2).toUpperCase()}
-
- )
- })
- )}
-
+
+
{customerName}
+
#{order.order_number}
+
+
+
+ {new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(order.total_price)}
+
+
{statusLabel[order.status] ?? order.status}
+
+
+
+ )
+ })
+ )}
- )
+
+ )
}