added status changing for clients and legal stuff

This commit is contained in:
Rajpreet0 2026-10-01 12:28:07 +02:00
parent b6f741be8f
commit 838801c9dd
15 changed files with 1188 additions and 35 deletions

505
app/(legal)/agb/page.tsx Normal file
View file

@ -0,0 +1,505 @@
import Image from "next/image"
import Link from "next/link"
const AGB = () => {
return (
<div className="flex min-h-svh flex-col bg-background p-4 sm:p-6">
<Link href="/">
<Image
src="/pictures/since3-logo.svg" alt=""
width={1617}
height={332}
loading="eager"
className="h-5 w-auto self-start md:h-6 dark:hidden"/>
</Link>
<Link href="/">
<Image
src="/pictures/since3-logo-weiss.svg" alt=""
width={1617}
height={332}
loading="eager"
className="hidden h-5 w-auto self-start md:h-6 dark:block"/>
</Link>
<div className="flex flex-1 flex-col justify-center py-10">
<div className="flex flex-1 flex-col justify-center py-10">
<div className="mx-auto w-full max-w-3xl space-y-10">
<section>
<h1 className="mb-6 text-4xl font-semibold">
Allgemeine Geschäftsbedingungen
</h1>
<p className="leading-7">
der Since3 GbR, Sandweg 91, 48565 Steinfurt (nachfolgend
„Since3“), für Leistungen und die Nutzung der Kundenplattform
app.since3.de. Stand: 01.10.2026 · Version 1.0
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">§ 1 Geltungsbereich</h2>
<p className="leading-7">
(1) Diese Allgemeinen Geschäftsbedingungen (AGB) gelten für alle
Verträge, Angebote und Leistungen zwischen Since3 und ihren
Kunden, insbesondere für die Konzeption, Gestaltung und Erstellung
digitaler Produkte, die Betreuung, Wartung und Pflege sowie die
Bereitstellung der Kundenplattform.
</p>
<p className="leading-7">
(2) Unsere Leistungen richten sich ausschließlich an Unternehmer
im Sinne von § 14 BGB, juristische Personen des öffentlichen
Rechts und öffentlich-rechtliche Sondervermögen. Verbraucher sind
vom Vertragsschluss ausgeschlossen.
</p>
<p className="leading-7">
(3) Abweichende oder entgegenstehende Bedingungen des Kunden
werden nicht Vertragsbestandteil, auch wenn wir ihnen nicht
ausdrücklich widersprechen. Individuelle Vereinbarungen haben
Vorrang vor diesen AGB.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">§ 2 Vertragsschluss</h2>
<p className="leading-7">
(1) Unsere Angebote sind freibleibend, sofern sie nicht
ausdrücklich als verbindlich bezeichnet sind. Ein Vertrag kommt
durch schriftliche oder in Textform erklärte Annahme des Angebots
durch den Kunden oder durch unsere Auftragsbestätigung zustande.
</p>
<p className="leading-7">
(2) Der Leistungsumfang ergibt sich aus dem jeweiligen Angebot
bzw. der Auftragsbestätigung. Nachträgliche Änderungen oder
Erweiterungen bedürfen der Textform und werden gesondert
vergütet, sofern nichts anderes vereinbart ist.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 3 Kundenplattform und Zugang
</h2>
<p className="leading-7">
(1) Since3 stellt dem Kunden für die Dauer des Vertragsverhältnisses
eine webbasierte Plattform unter app.since3.de zur Verfügung. Dort
kann der Kunde insbesondere Stammdaten einsehen und ergänzen,
Rechnungen einsehen und herunterladen, Informationen zu den von
Since3 erstellten Produkten abrufen, Dokumente hochladen und
projektbezogene Zugangsdaten verwalten.
</p>
<p className="leading-7">
(2) Die Konten werden von Since3 angelegt. Der Zugang zur Plattform
wird erst freigeschaltet, nachdem der Kunde diese AGB in der
Plattform ausdrücklich akzeptiert hat. Wir speichern dazu den
Zeitpunkt der Zustimmung und die akzeptierte Version der AGB.
</p>
<p className="leading-7">
(3) Der Kunde hält seine Zugangsdaten zur Plattform geheim, nutzt
ein sicheres Passwort. Er informiert Since3 unverzüglich,
wenn er den Verdacht hat, dass Dritte Kenntnis von seinen
Zugangsdaten erlangt haben. Der Kunde ist dafür verantwortlich, dass
nur von ihm autorisierte Personen seines Unternehmens die Plattform
nutzen, und haftet für deren Handlungen.
</p>
<p className="leading-7">
(4) Wir bemühen uns um eine hohe Verfügbarkeit der Plattform. Ein Anspruch auf
ununterbrochene Verfügbarkeit besteht nicht. Wartungsarbeiten,
Störungen bei Drittanbietern und Ereignisse außerhalb unseres
Einflussbereichs können zu zeitweisen Einschränkungen führen.
</p>
<p className="leading-7">
(5) Die Plattform ist ein ergänzender Service zu unseren
Leistungen und kein Datenarchiv. Der Kunde ist selbst dafür
verantwortlich, von ihm hochgeladene Dokumente und wichtige
Informationen in eigener Kopie vorzuhalten.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 4 Hochgeladene Inhalte und Datenschutz
</h2>
<p className="leading-7">
(1) Der Kunde darf Dokumente und Dateien hochladen, soweit sie für
die Zusammenarbeit mit Since3 erforderlich sind. Er versichert, dass
er zur Nutzung und Weitergabe dieser Inhalte berechtigt ist und
dass diese keine Rechte Dritter verletzen und nicht gegen Gesetze
verstoßen.
</p>
<p className="leading-7">
(2) Nicht hochgeladen werden dürfen rechtswidrige Inhalte,
Schadsoftware sowie besondere Kategorien personenbezogener Daten
im Sinne von Art. 9 DSGVO (z. B. Gesundheitsdaten), es sei denn,
es wurde vorher ausdrücklich in Textform etwas anderes mit
Since3 vereinbart.
</p>
<p className="leading-7">
(3) Soweit Since3 im Rahmen der Leistungserbringung
personenbezogene Daten im Auftrag des Kunden verarbeitet, schließen
die Parteien einen Vertrag zur Auftragsverarbeitung nach Art. 28
DSGVO. Der Vertrag ist Bestandteil der Kundenvereinbarung.
Informationen zur Verarbeitung personenbezogener Daten auf der
Plattform enthält die Datenschutzerklärung unter
app.since3.de/datenschutz.
</p>
<p className="leading-7">
(4) Der Kunde räumt Since3 die für die Vertragserfüllung
erforderlichen, nicht ausschließlichen Nutzungsrechte an den
hochgeladenen Inhalten ein, insbesondere zum Speichern,
Verarbeiten und Einbinden in die vereinbarten Produkte.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 5 Zugangsdaten des Kunden zu Drittsystemen
</h2>
<p className="leading-7">
(1) Soweit der Kunde Since3 Zugangsdaten zu eigenen Systemen oder
Konten überlässt (z. B. Hosting, Domain, Shop-System, Social Media,
Marketing-Tools), erteilt er Since3 hiermit die ausdrückliche
Erlaubnis, diese ausschließlich zur Erbringung der vereinbarten
Leistungen zu nutzen.
</p>
<p className="leading-7">
(2) Der Kunde sichert zu, dass er zur Weitergabe der Zugangsdaten
berechtigt ist und dass dies nicht gegen Nutzungsbedingungen des
jeweiligen Anbieters verstößt. Wo die Anbieter dies vorsehen,
stellt der Kunde Since3 bevorzugt einen eigenen Benutzer-,
Mitarbeiter- oder Partnerzugang bereit, anstatt die Zugangsdaten
des Inhaber-Kontos zu übermitteln.
</p>
<p className="leading-7">
(3) Der Kunde hält die hinterlegten Zugangsdaten aktuell und
unterstützt bei Bedarf bei Sicherheitsabfragen, etwa der
Bereitstellung von Zwei-Faktor-Codes.
</p>
<p className="leading-7">
(4) Since3 speichert hinterlegte Zugangsdaten verschlüsselt und
beschränkt den Zugriff auf die Mitarbeiter, die das jeweilige
Projekt betreuen. Since3 verwendet die Zugangsdaten nur im
vereinbarten Umfang und gibt sie nicht an Dritte weiter, es sei
denn, dies ist für die Leistung erforderlich und vertraglich
abgesichert.
</p>
<p className="leading-7">
(5) Nach Beendigung des Vertrags oder Abschluss des Projekts
löscht Since3 die hinterlegten Zugangsdaten. Der Kunde ist verpflichtet, die Passwörter der betroffenen
Konten nach Vertragsende selbst zu ändern und überlassene
Benutzerzugänge zu entziehen.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 6 Mitwirkungspflichten des Kunden
</h2>
<p className="leading-7">
(1) Der Kunde stellt Since3 alle für die Leistungserbringung
erforderlichen Informationen, Texte, Bilder, Logos, Zugänge und
sonstigen Materialien rechtzeitig, vollständig und in geeigneter
Form zur Verfügung und benennt einen Ansprechpartner, der
Entscheidungen treffen kann.
</p>
<p className="leading-7">
(2) Der Kunde ist für die Rechtmäßigkeit der von ihm gelieferten
Inhalte verantwortlich (z. B. Urheber-, Marken- und Bildrechte).
Er stellt Since3 von Ansprüchen Dritter frei, die auf der
Verletzung solcher Rechte durch die vom Kunden gelieferten Inhalte
beruhen.
</p>
<p className="leading-7">
(3) Verzögert sich die Leistung, weil der Kunde Mitwirkungspflichten
nicht rechtzeitig erfüllt, verschieben sich vereinbarte Termine
entsprechend. Mehraufwand kann gesondert berechnet werden.
</p>
<p className="leading-7">
(4) Rechtliche Anforderungen an die Inhalte der fertigen Produkte
(z. B. Impressum, Datenschutzerklärung, Widerrufsbelehrung, AGB
des Kunden, Cookie-Einwilligung) liegen in der Verantwortung des
Kunden, sofern Since3 keine rechtliche Prüfung oder Erstellung
ausdrücklich schriftlich zugesagt hat. Since3 erbringt keine
Rechtsberatung.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 7 Vergütung und Zahlung
</h2>
<p className="leading-7">
(1) Es gelten die im Angebot bzw. in der Auftragsbestätigung
genannten Preise. Alle Preise verstehen sich, soweit nicht anders
angegeben, zuzüglich der gesetzlichen Umsatzsteuer.
</p>
<p className="leading-7">
(2) Rechnungen werden über die Plattform bereitgestellt oder per
E-Mail versendet und sind, sofern nichts anderes vereinbart ist,
innerhalb von 14 Tagen ab Rechnungsdatum ohne Abzug zu zahlen.
Die Zahlung erfolgt außerhalb der Plattform per Überweisung.
</p>
<p className="leading-7">
(3) Bei größeren Projekten sind wir berechtigt, Abschlagszahlungen
oder eine Anzahlung zu verlangen und die Arbeit bis zum
Eingang der Zahlung zurückzustellen.
</p>
<p className="leading-7">
(4) Kosten für Drittanbieter (z. B. Domains, Hosting, Lizenzen,
Themes, Plug-ins, Shop- und Tool-Abonnements, Werbebudgets) sind
nicht im Preis enthalten und trägt der Kunde, sofern nicht
ausdrücklich anders vereinbart. Verträge mit diesen Anbietern
schließt der Kunde im eigenen Namen, sofern nichts anderes
vereinbart ist.
</p>
<p className="leading-7">
(5) Bei Zahlungsverzug gelten die gesetzlichen Regelungen,
einschließlich der Verzugszinsen und der Pauschale nach § 288
Abs. 5 BGB. Wir sind berechtigt, nach Mahnung weitere Leistungen
zurückzuhalten und den Zugang zur Plattform zu sperren. Die
Verpflichtung zur Zahlung bleibt davon unberührt.
</p>
<p className="leading-7">
(6) Aufrechnung und Zurückbehaltungsrechte stehen dem Kunden nur
wegen unbestrittener oder rechtskräftig festgestellter Forderungen
zu.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 8 Abnahme und Mängelrechte
</h2>
<p className="leading-7">
(1) Soweit Since3 ein Werk herstellt (z. B. eine Website oder einen
Online-Shop), ist der Kunde zur Abnahme verpflichtet. Die Abnahme
gilt als erfolgt, wenn der Kunde das Werk produktiv nutzt.
</p>
<p className="leading-7">
(2) Mängel meldet der Kunde unverzüglich und nachvollziehbar
beschrieben in Textform. Wir beseitigen berechtigte Mängel
innerhalb angemessener Frist nach unserer Wahl durch
Nachbesserung oder Neuherstellung. Schlägt die Nacherfüllung
fehl, gelten die gesetzlichen Rechte.
</p>
<p className="leading-7">
(3) Mängelansprüche verjähren nach drei Monaten ab Abnahme. Dies
gilt nicht bei Vorsatz, Arglist und in den in § 11 Abs. 2
genannten Fällen.
</p>
<p className="leading-7">
(4) Keine Mängel sind Abweichungen, die auf Änderungen durch den
Kunden oder Dritte, auf Updates von Drittsystemen (z. B.
Shop-System, Browser, Plug-ins) oder auf unterschiedliche
Darstellung in Endgeräten im üblichen Rahmen beruhen.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 9 Nutzungsrechte und Referenzen
</h2>
<p className="leading-7">
(1) Mit vollständiger Zahlung der vereinbarten Vergütung erhält
der Kunde an den von Since3 erstellten Arbeitsergebnissen
(Designs, Texte, Grafiken, Code) ein einfaches, zeitlich und
räumlich unbeschränktes Nutzungsrecht für den vereinbarten Zweck.
Bis dahin dürfen die Arbeitsergebnisse nur zur Ansicht und
Abstimmung genutzt werden.
</p>
<p className="leading-7">
(2) Nicht erfasst sind Rechte an Open-Source-Komponenten,
Lizenzsoftware und Inhalten Dritter. Hier gelten die jeweiligen
Lizenzbedingungen. Since3 weist auf diese auf Anfrage hin.
</p>
<p className="leading-7">
(3) Since3 bleibt berechtigt, Methoden, Werkzeuge und allgemeines
Know-how, das bei der Erstellung entsteht, weiter zu verwenden.
</p>
<p className="leading-7">
(4) Since3 darf das Projekt, sofern der Kunde nicht in Textform
widerspricht, unter Nennung des Kunden als Referenz (Logo,
Screenshots, Link) in der eigenen Werbung nennen.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 10 Laufzeit und Kündigung
</h2>
<p className="leading-7">
(1) Projektverträge enden mit vollständiger Leistungserbringung
und Abnahme.
</p>
<p className="leading-7">
(2) Dauerschuldverhältnisse (z. B. Wartung, Betreuung, Hosting,
laufende Marketingleistungen) haben die im Angebot genannte
Mindestlaufzeit. Sie verlängern sich jeweils um den dort genannten
Zeitraum, wenn sie nicht mit einer Frist von ein Monat zum Ende
der Laufzeit in Textform gekündigt werden.
</p>
<p className="leading-7">
(3) Das Recht zur außerordentlichen Kündigung aus wichtigem Grund
bleibt unberührt. Ein wichtiger Grund für Since3 liegt
insbesondere vor, wenn der Kunde trotz Mahnung in Zahlungsverzug
ist oder gegen § 4 Abs. 2 oder § 5 Abs. 2 verstößt.
</p>
<p className="leading-7">
(4) Mit Vertragsende wird der Zugang zur Plattform gesperrt.
Since3 stellt dem Kunden auf Anfrage innerhalb von 30 Tagen nach
Vertragsende einen Export seiner hochgeladenen Dokumente bereit.
Anschließend werden Daten nach Maßgabe der Datenschutzerklärung
und des Vertrags zur Auftragsverarbeitung gelöscht. Gesetzliche
Aufbewahrungspflichten, insbesondere für Rechnungen, bleiben
unberührt.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">§ 11 Haftung</h2>
<p className="leading-7">
(1) Since3 haftet unbeschränkt bei Vorsatz und grober
Fahrlässigkeit sowie für Schäden aus der Verletzung von Leben,
Körper oder Gesundheit.
</p>
<p className="leading-7">
(2) Bei leicht fahrlässiger Verletzung einer wesentlichen
Vertragspflicht (Kardinalpflicht), also einer Pflicht, deren
Erfüllung die ordnungsgemäße Durchführung des Vertrags überhaupt
erst ermöglicht und auf deren Einhaltung der Kunde regelmäßig
vertrauen darf, ist die Haftung auf den vorhersehbaren,
vertragstypischen Schaden begrenzt. Die Haftung ist je Schadensfall
begrenzt.
</p>
<p className="leading-7">
(3) Im Übrigen ist die Haftung bei leichter Fahrlässigkeit
ausgeschlossen.
</p>
<p className="leading-7">
(4) Die Haftung nach dem Produkthaftungsgesetz, für arglistig
verschwiegene Mängel und aus übernommenen Garantien bleibt
unberührt.
</p>
<p className="leading-7">
(5) Für Schäden an Daten haftet Since3 nur in Höhe des Aufwands,
der bei regelmäßiger und gefahrentsprechender Datensicherung durch
den Kunden für die Wiederherstellung entstanden wäre.
</p>
<p className="leading-7">
(6) Since3 haftet nicht für Ausfälle, Änderungen oder Sperrungen
bei Drittanbietern (z. B. Hosting, Shop-Systeme, soziale
Netzwerke) und nicht für Schäden, die dadurch entstehen, dass der
Kunde seine Mitwirkungs- und Sicherheitspflichten (§§ 3, 5, 6)
verletzt, etwa durch die Weitergabe von Zugangsdaten an Dritte.
</p>
<p className="leading-7">
(7) Die Haftungsbeschränkungen gelten auch zugunsten der
Gesellschafter, Mitarbeiter und Erfüllungsgehilfen von Since3.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">§ 12 Vertraulichkeit</h2>
<p className="leading-7">
Die Parteien behandeln alle im Rahmen der Zusammenarbeit
bekanntgewordenen vertraulichen Informationen der jeweils anderen
Partei (insbesondere Zugangsdaten, Geschäftsgeheimnisse und
Kundendaten) vertraulich und nutzen sie nur zur Vertragserfüllung.
Die Pflicht besteht über das Vertragsende hinaus fort.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">
§ 13 Änderungen dieser AGB
</h2>
<p className="leading-7">
(1) Wir können diese AGB mit Wirkung für die Zukunft ändern, wenn
dafür ein sachlicher Grund besteht (z. B. Gesetzesänderung,
neue Funktionen der Plattform oder eine Anpassung der
Leistungen) und die Änderung für den Kunden zumutbar ist.
</p>
<p className="leading-7">
(2) Über Änderungen informieren wir den Kunden in Textform und
über die Plattform. Die geänderten AGB gelten erst, wenn der
Kunde ihnen in der Plattform ausdrücklich zustimmt. Stimmt er nicht
zu, gelten die bisherigen AGB für bestehende Verträge fort. Wir
behalten uns das Recht vor, den Zugang zur Plattform
einzuschränken, wenn der Betrieb nach den bisherigen AGB nicht
mehr möglich ist.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">§ 14 Schlussbestimmungen</h2>
<p className="leading-7">
(1) Es gilt das Recht der Bundesrepublik Deutschland unter
Ausschluss des UN-Kaufrechts (CISG).
</p>
<p className="leading-7">
(2) Ist der Kunde Kaufmann, juristische Person des öffentlichen
Rechts oder öffentlich-rechtliches Sondervermögen, ist
ausschließlicher Gerichtsstand Steinfurt für alle Streitigkeiten aus dem Vertragsverhältnis.
Since3 ist berechtigt, den Kunden auch an seinem allgemeinen
Gerichtsstand zu verklagen.
</p>
<p className="leading-7">
(3) Änderungen und Ergänzungen des Vertrags bedürfen der Textform.
Das gilt auch für die Aufhebung dieses Textformerfordernisses.
</p>
<p className="leading-7">
(4) Sollten einzelne Bestimmungen dieser AGB ganz oder teilweise
unwirksam sein oder werden, bleibt die Wirksamkeit der übrigen
Bestimmungen unberührt. An die Stelle der unwirksamen Regelung
tritt die gesetzliche Regelung.
</p>
</section>
<hr/>
<section className="space-y-3">
<h2 className="text-xl font-semibold">Kontakt</h2>
<p className="leading-7">
Bei Fragen zu diesen AGB erreichen Sie uns unter{" "}
<a
href="mailto:info@since3.de"
className="underline underline-offset-2"
>
info@since3.de
</a>
.
</p>
</section>
</div>
</div>
</div>
</div>
)
}
export default AGB

View file

@ -0,0 +1,439 @@
import Image from "next/image"
import Link from "next/link"
const Datenschutz = () => {
return (
<div className="flex min-h-svh flex-col bg-background p-4 sm:p-6">
<Link href="/">
<Image
src="/pictures/since3-logo.svg" alt=""
width={1617}
height={332}
loading="eager"
className="h-5 w-auto self-start md:h-6 dark:hidden"/>
</Link>
<Link href="/">
<Image
src="/pictures/since3-logo-weiss.svg" alt=""
width={1617}
height={332}
loading="eager"
className="hidden h-5 w-auto self-start md:h-6 dark:block"/>
</Link>
<div className="flex flex-1 flex-col justify-center py-10">
<div className="flex flex-1 flex-col justify-center py-10">
<div className="mx-auto w-full max-w-3xl space-y-10">
<section>
<h1 className="mb-6 text-4xl font-semibold">Datenschutzerklärung</h1>
<p className="leading-7">
Diese Datenschutzerklärung gilt für die Kundenplattform
app.since3.de. Informationen zur Marketing-Website since3.de
finden Sie in der Datenschutzerklärung unter since3.de/datenschutz.
</p>
</section>
<hr/>
{/* ---------------------------------------------------------------- */}
{/* VERANTWORTLICHE STELLE */}
{/* ---------------------------------------------------------------- */}
<section className="space-y-3">
<h2 className="text-2xl font-semibold">Verantwortliche Stelle</h2>
<p className="leading-7">
Verantwortlich für die Datenverarbeitung ist:
</p>
<div className="space-y-1">
<p className="font-medium">Since3 GbR</p>
<p>Sandweg 91</p>
<p>48565 Steinfurt</p>
<p>Vertreten durch: Ben Dalhoff, Rajpreet Singh</p>
</div>
<div className="space-y-1">
<p>
<span className="font-medium">Telefon:</span>{" "}
+49 176 47601638
</p>
<p>
<span className="font-medium">E-Mail:</span>{" "}
<a
href="mailto:info@since3.de"
className="underline underline-offset-2"
>
info@since3.de
</a>
</p>
</div>
<p className="leading-7">
Verantwortliche Stelle ist die natürliche oder juristische Person,
die allein oder gemeinsam mit anderen über die Zwecke und Mittel
der Verarbeitung von personenbezogenen Daten (z. B. Namen,
E-Mail-Adressen o. Ä.) entscheidet.
</p>
</section>
<hr/>
{/* ================================================================ */}
{/* TEIL B: APP */}
{/* ================================================================ */}
<section className="space-y-8">
<h2 className="text-3xl font-semibold">
Datenverarbeitung auf der Plattform
</h2>
<div className="space-y-3">
<h3 className="text-xl font-semibold">Zweck der Plattform</h3>
<p className="leading-7">
Über die Plattform stellen wir unseren Kunden einen
persönlichen Zugang bereit. Dort können Kunden ihre
Stammdaten einsehen und ergänzen, Rechnungen einsehen und
herunterladen, Informationen zu den von uns erstellten
Produkten abrufen, Dokumente hochladen und Zugangsdaten
verwalten, die für die Umsetzung ihrer Projekte erforderlich
sind.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Kontoanlage durch uns (Information nach Art. 14 DSGVO)
</h3>
<p className="leading-7">
Die Konten werden von uns angelegt. Wenn Sie als Mitarbeiter
oder Ansprechpartner eines Unternehmens einen Zugang erhalten,
haben wir Ihre Kontaktdaten (Name, geschäftliche E-Mail-Adresse,
ggf. Funktion) in der Regel von Ihrem Arbeitgeber bzw. dem
Auftraggeber erhalten. Wir verarbeiten sie, um Ihnen den Zugang
einzurichten und den Vertrag mit Ihrem Unternehmen
durchzuführen (Art. 6 Abs. 1 lit. b bzw. lit. f DSGVO).
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Verarbeitete Daten, Zwecke und Rechtsgrundlagen
</h3>
<ul className="list-disc space-y-2 pl-6 leading-7">
<li>
<span className="font-medium">Stammdaten und Kontaktdaten</span>{" "}
(z. B. Name, Firma, Anschrift, E-Mail, Telefon, USt-IdNr.):
Vertragsabwicklung und Kommunikation, Art. 6 Abs. 1 lit. b
DSGVO.
</li>
<li>
<span className="font-medium">Rechnungen und Abrechnungsdaten:</span>{" "}
Vertragsabwicklung und gesetzliche Aufbewahrungspflichten,
Art. 6 Abs. 1 lit. b und c DSGVO. Zahlungen werden nicht
über die Plattform abgewickelt.
</li>
<li>
<span className="font-medium">Produkt- und Projektinformationen:</span>{" "}
Bereitstellung der von uns erstellten Leistungen, Art. 6
Abs. 1 lit. b DSGVO.
</li>
<li>
<span className="font-medium">Hochgeladene Dokumente:</span>{" "}
Dateien, die Sie zur Projektabwicklung hochladen, Art. 6
Abs. 1 lit. b DSGVO.
</li>
<li>
<span className="font-medium">Zugangsdaten für Projekte</span>{" "}
(z. B. Hosting- oder Shop-Zugänge): ausschließlich zur
Durchführung des vereinbarten Projekts, Art. 6 Abs. 1 lit. b
DSGVO.
</li>
<li>
<span className="font-medium">Login- und Nutzungsdaten</span>{" "}
(Anmeldedaten, Zeitpunkt der Anmeldung, IP-Adresse,
Zugriffsprotokolle): Betrieb und Sicherheit der Plattform,
Art. 6 Abs. 1 lit. f DSGVO.
</li>
</ul>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Unsere Rolle: Verantwortlicher und Auftragsverarbeiter
</h3>
<p className="leading-7">
Bei Ihren Stammdaten, Rechnungen und Login-Daten sind wir
Verantwortlicher im Sinne der DSGVO. Enthalten hochgeladene
Dokumente oder die Systeme, für die Sie uns Zugangsdaten
überlassen (z. B. Shop, Website, Hosting), personenbezogene Daten
Dritter, etwa Ihrer Mitarbeiter oder Endkunden, verarbeiten wir
diese in Ihrem Auftrag. Dafür schließen wir mit Ihnen einen
Vertrag über Auftragsverarbeitung nach Art. 28 DSGVO. Als
Auftraggeber sind Sie für die Rechtmäßigkeit dieser
Verarbeitung verantwortlich.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Login, Session-Cookies und Protokollierung
</h3>
<p className="leading-7">
Für die Anmeldung setzen wir technisch notwendige Cookies bzw.
Speicherelemente ein (z. B. Session- und Authentifizierungs-Token).
Sie sind erforderlich, damit Sie eingeloggt bleiben und die
Plattform sicher nutzen können (§ 25 Abs. 2 Nr. 2 TDDDG). Eine
Einwilligung ist dafür nicht erforderlich.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Schutz gespeicherter Zugangsdaten
</h3>
<p className="leading-7">
Zugangsdaten, die Sie in der Plattform hinterlegen, speichern wir
verschlüsselt. Der Zugriff ist auf Mitarbeiter beschränkt, die
das jeweilige Projekt betreuen. Wir empfehlen, uns wo möglich keine
Inhaber-Passwörter zu überlassen, sondern einen eigenen
Zugang (z. B. Mitarbeiter- oder Partnerzugang) einzurichten,
den Sie jederzeit selbst entziehen können.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">Empfänger und Dienstleister</h3>
<p className="leading-7">
Wir geben Daten nur weiter, soweit dies zur Vertragserfüllung
erforderlich ist, wir gesetzlich dazu verpflichtet sind oder
eine Rechtsgrundlage besteht. Für den Betrieb der Plattform
setzen wir folgende Auftragsverarbeiter ein, mit denen jeweils
ein Vertrag nach Art. 28 DSGVO besteht:
</p>
<ul className="list-disc space-y-2 pl-6 leading-7">
<li>
<span className="font-medium">Supabase</span> (Datenbank,
Authentifizierung, Dateispeicher und Verschlüsselung von
Zugangsdaten). Hosting in der Region EU-Frankfurt. Anbieter: Supabase PTE LTD. 65 Chulia Street #38-02/03, OCBC, Centre, Singapore 049513
</li>
<li>
<span className="font-medium">Vercel Inc.</span> (Hosting der
Anwendung), 440 Barranca Ave #4133, Covina, CA 91723, USA.
</li>
<li>
<span className="font-medium">Plus Five Five Inc.</span>{" "}
2261 Market Street #5039 San Francisco, CA 94114
(Versand von Einladungs- und Benachrichtigungs-E-Mails).
</li>
</ul>
<p className="leading-7">
Soweit Dienstleister ihren Sitz in den USA haben oder dort
Daten verarbeiten, stützt sich die Übermittlung auf EU-US Data
Privacy Framework.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">Speicherdauer</h3>
<ul className="list-disc space-y-2 pl-6 leading-7">
<li>
<span className="font-medium">Rechnungen und Buchungsbelege:</span>{" "}
werden entsprechend den gesetzlichen Aufbewahrungsfristen
aufbewahrt. Nach
Vertragsende werden diese Daten für andere Zwecke gesperrt.
</li>
<li>
<span className="font-medium">Stammdaten:</span> für die
Dauer der Geschäftsbeziehung, danach nur noch soweit
gesetzliche Aufbewahrungspflichten bestehen oder die Daten
zur Geltendmachung oder Abwehr von Rechtsansprüchen
erforderlich sind.
</li>
<li>
<span className="font-medium">Hochgeladene Dokumente, Produktinformationen und Zugangsdaten:</span>{" "}
werden spätestens nach Vertragsende oder Projektabschluss
gelöscht, sofern Sie nichts anderes mit uns vereinbaren.
</li>
<li>
<span className="font-medium">Backups:</span> Gelöschte
Daten können noch bis zu 24h in Sicherungen vorhanden sein und werden danach
endgültig entfernt.
</li>
</ul>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Erforderlichkeit der Daten
</h3>
<p className="leading-7">
Die Bereitstellung der Stammdaten und Kontaktdaten ist für den
Abschluss und die Durchführung des Vertrags erforderlich.
Ohne diese Daten können wir die Plattform nicht bereitstellen
und unsere Leistungen nicht erbringen. Hochgeladene Dokumente
und Zugangsdaten stellen Sie freiwillig bereit, sie sind aber
je nach Projekt für die Umsetzung notwendig.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Auskunft und Datenexport
</h3>
<p className="leading-7">
Die meisten Ihrer Daten können Sie direkt in der Plattform
einsehen. Für eine vollständige Auskunft, einen Export oder die
Löschung Ihrer Daten schreiben Sie uns an{" "}
<a
href="mailto:info@since3.de"
className="underline underline-offset-2"
>
info@since3.de
</a>
.
</p>
</div>
</section>
<hr/>
{/* ================================================================ */}
{/* TEIL C: ALLGEMEIN */}
{/* ================================================================ */}
<section className="space-y-8">
<h2 className="text-3xl font-semibold">
Allgemeine Hinweise
</h2>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Ihre Rechte
</h3>
<p className="leading-7">
Sie haben im Rahmen der gesetzlichen Bestimmungen jederzeit das
Recht auf unentgeltliche Auskunft über Ihre gespeicherten
personenbezogenen Daten, deren Herkunft und Empfänger und den
Zweck der Verarbeitung (Art. 15 DSGVO) sowie auf Berichtigung
(Art. 16), Löschung (Art. 17), Einschränkung der Verarbeitung
(Art. 18) und Datenübertragbarkeit (Art. 20). Wenden Sie sich
dazu jederzeit an uns.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Widerruf Ihrer Einwilligung
</h3>
<p className="leading-7">
Viele Verarbeitungsvorgänge sind nur mit Ihrer Einwilligung
möglich. Eine erteilte Einwilligung können Sie jederzeit mit
Wirkung für die Zukunft widerrufen. Die Rechtmäßigkeit der bis
zum Widerruf erfolgten Verarbeitung bleibt unberührt.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Widerspruchsrecht (Art. 21 DSGVO)
</h3>
<p className="text-sm leading-7 uppercase">
Wenn die Datenverarbeitung auf Grundlage von Art. 6 Abs. 1 lit.
e oder f DSGVO erfolgt, haben Sie jederzeit das Recht, aus
Gründen, die sich aus Ihrer besonderen Situation ergeben, gegen
die Verarbeitung Ihrer personenbezogenen Daten Widerspruch
einzulegen. Wir verarbeiten die betroffenen Daten dann nicht
mehr, es sei denn, wir können zwingende schutzwürdige Gründe
für die Verarbeitung nachweisen, die Ihre Interessen, Rechte
und Freiheiten überwiegen, oder die Verarbeitung dient der
Geltendmachung, Ausübung oder Verteidigung von
Rechtsansprüchen.
</p>
<p className="text-sm leading-7 uppercase">
Werden Ihre personenbezogenen Daten verarbeitet, um
Direktwerbung zu betreiben, haben Sie das Recht, jederzeit
Widerspruch gegen die Verarbeitung Sie betreffender
personenbezogener Daten zum Zwecke derartiger Werbung
einzulegen.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Recht auf Einschränkung der Verarbeitung
</h3>
<p className="leading-7">
Sie können die Einschränkung der Verarbeitung Ihrer
personenbezogenen Daten verlangen, insbesondere wenn:
</p>
<ul className="list-disc space-y-2 pl-6 leading-7">
<li>Sie die Richtigkeit der Daten bestreiten (für die Dauer der Prüfung).</li>
<li>
die Verarbeitung unrechtmäßig ist und Sie statt der
Löschung die Einschränkung verlangen.
</li>
<li>
wir die Daten nicht mehr benötigen, Sie sie aber zur
Geltendmachung, Ausübung oder Verteidigung von
Rechtsansprüchen brauchen.
</li>
<li>
Sie Widerspruch nach Art. 21 Abs. 1 DSGVO eingelegt haben und
noch nicht feststeht, wessen Interessen überwiegen.
</li>
</ul>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
Beschwerderecht bei der Aufsichtsbehörde
</h3>
<p className="leading-7">
Im Falle von Verstößen gegen die DSGVO steht Ihnen ein
Beschwerderecht bei einer Aufsichtsbehörde zu, insbesondere in
dem Mitgliedstaat Ihres gewöhnlichen Aufenthalts, Ihres
Arbeitsplatzes oder des Orts des mutmaßlichen Verstoßes. Für uns
zuständig ist die Landesbeauftragte für Datenschutz und
Informationsfreiheit Nordrhein-Westfalen, Kavalleriestraße 2–4,
40213 Düsseldorf
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">
SSL- bzw. TLS-Verschlüsselung
</h3>
<p className="leading-7">
Diese Plattform nutzt aus Sicherheitsgründen und
zum Schutz der Übertragung vertraulicher Inhalte eine SSL- bzw.
TLS-Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie
daran, dass die Adresszeile des Browsers von „http://“ auf
„https://“ wechselt und am Schloss-Symbol in Ihrer Browserzeile.
</p>
</div>
<div className="space-y-3">
<h3 className="text-xl font-semibold">Stand und Änderungen</h3>
<p className="leading-7">
Stand: 01 Okt 2026. Wir passen diese Datenschutzerklärung
an, wenn sich unsere Verarbeitungen oder die rechtlichen
Vorgaben ändern.
</p>
</div>
</section>
<hr/>
<p className="text-sm">
Quelle:{" "}
<a
href="https://www.e-recht24.de"
target="_blank"
rel="noopener noreferrer"
className="underline underline-offset-2"
>
e-recht24.de
</a>
</p>
</div>
</div>
</div>
</div>
)
}
export default Datenschutz

View file

@ -0,0 +1,107 @@
import Image from "next/image"
import Link from "next/link"
const Impressum = () => {
return (
<div className="flex min-h-svh flex-col bg-background p-4 sm:p-6">
<Link href="/">
<Image
src="/pictures/since3-logo.svg" alt=""
width={1617}
height={332}
loading="eager"
className="h-5 w-auto self-start md:h-6 dark:hidden"/>
</Link>
<Link href="/">
<Image
src="/pictures/since3-logo-weiss.svg" alt=""
width={1617}
height={332}
loading="eager"
className="hidden h-5 w-auto self-start md:h-6 dark:block"/>
</Link>
<div className="flex flex-1 flex-col justify-center py-10">
<div className="mx-auto w-full max-w-3xl space-y-10">
<section>
<h1 className="mb-6 text-4xl font-semibold">Impressum</h1>
<div className="space-y-1">
<p className="font-medium">Since3 GbR</p>
<p>Sandweg 91</p>
<p>48565 Steinfurt</p>
</div>
<div className="mt-5">
<p className="font-medium">Vertreten durch:</p>
<p>Ben Dalhoff, Rajpreet Singh</p>
</div>
</section>
<hr/>
<section>
<h2 className="mb-3 text-xl font-semibold">Kontakt</h2>
<div className="space-y-1">
<p>
<span className="font-medium">Telefon:</span>{" "}
+49 176 47601638
</p>
<p>
<span className="font-medium">E-Mail:</span>{" "}
<a
href="mailto:info@since3.de"
className="underline underline-offset-2 "
>
info@since3.de
</a>
</p>
</div>
</section>
<hr/>
<section>
<h2 className="mb-3 text-xl font-semibold">
Redaktionell verantwortlich
</h2>
<p>
Ben Dalhoff, Rajpreet Singh
</p>
</section>
<hr/>
<section>
<h2 className="mb-3 text-xl font-semibold">
Verbraucherstreitbeilegung / Universalschlichtungsstelle
</h2>
<p className="leading-7">
Wir sind nicht bereit oder verpflichtet, an
Streitbeilegungsverfahren vor einer
Verbraucherschlichtungsstelle teilzunehmen.
</p>
</section>
<hr/>
<p className="text-sm ">
Quelle:{" "}
<a
href="https://www.e-recht24.de"
target="_blank"
rel="noopener noreferrer"
className="underline underline-offset-2 "
>
e-recht24.de
</a>
</p>
</div>
</div>
</div>
)
}
export default Impressum

View file

@ -1,12 +0,0 @@
const TermsPage = () => {
return (
<div className="mx-auto max-w-2xl px-4 py-8 sm:p-8">
<h1 className="mb-4 text-2xl font-semibold">Nutzungsbedingungen</h1>
<p className="text-muted-foreground">
TODO: Nutzungsbedingungen einfügen.
</p>
</div>
)
}
export default TermsPage

View file

@ -0,0 +1,7 @@
-- Projektstatus pro Client, wird vom Admin in der Clients-Übersicht gesetzt.
-- Ändern dürfen nur Admins (bestehende Policy profiles_admin_update).
create type public.client_status as enum ('upcoming', 'current', 'done');
alter table public.profiles
add column if not exists status public.client_status not null default 'upcoming';

View file

@ -7,6 +7,7 @@ import { createClient } from "@/lib/supabase/server";
import { verifySession } from "@/lib/supabase/dal";
import { generatePassword } from "@/lib/generate-password";
import { MIN_PASSWORD_LENGTH } from "@/modules/admin/lib/constants";
import { CLIENT_STATUSES } from "@/modules/admin/lib/client-status";
export type ResetPasswordState = { error: string } | { success: true; password: string } | undefined;
export type UpdateClientState = { error: string } | { success: true } | undefined;
@ -88,3 +89,21 @@ export async function updateClientAccount(_prev: UpdateClientState, formData: Fo
revalidatePath(`/admin/clients/${profileId}`, "layout");
return { success: true };
}
const StatusSchema = z.enum(CLIENT_STATUSES, { error: "Bitte einen gültigen Status wählen." });
export async function updateClientStatus(_prev: UpdateClientState, formData: FormData): Promise<UpdateClientState> {
const profileId = String(formData.get("profileId") ?? "");
const denied = await assertClientTarget(profileId);
if (denied) return denied;
const parsed = StatusSchema.safeParse(formData.get("status"));
if (!parsed.success) return { error: parsed.error.issues[0]?.message ?? "Ungültige Eingabe." };
const supabase = await createClient();
const { error } = await supabase.from("profiles").update({ status: parsed.data }).eq("id", profileId);
if (error) return { error: "Status konnte nicht gespeichert werden." };
revalidatePath("/admin/clients");
return { success: true };
}

View file

@ -0,0 +1,9 @@
export const CLIENT_STATUSES = ["upcoming", "current", "done"] as const;
export type ClientStatus = (typeof CLIENT_STATUSES)[number];
export const CLIENT_STATUS_CONFIG: Record<ClientStatus, { label: string; variant: "neutral" | "warning" | "success" }> = {
upcoming: { label: "Upcoming", variant: "neutral" },
current: { label: "Current", variant: "warning" },
done: { label: "Done", variant: "success" },
};

View file

@ -1,15 +1,16 @@
import "server-only"
import { createAdminClient } from "@/lib/supabase/admin"
import type { ClientStatus } from "@/modules/admin/lib/client-status"
export async function getClients() {
const supabase = createAdminClient()
const { data, error } = await supabase
.from("profiles")
.select("id, name, email")
.select("id, name, email, status")
.eq("role", "client")
.order("name")
if (error) throw new Error(`Failed to load clients: ${error.message}`)
return data
return data as { id: string; name: string; email: string; status: ClientStatus }[]
}

View file

@ -1,17 +1,19 @@
"use client";
import { useActionState, useState } from "react";
import { KeyRoundIcon, MoreHorizontalIcon, PencilIcon } from "lucide-react";
import { Info, KeyRoundIcon, MoreHorizontalIcon, PencilIcon } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Field, FieldDescription, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { resetClientPassword, updateClientAccount } from "@/modules/admin/actions/manage-client";
import { resetClientPassword, updateClientAccount, updateClientStatus } from "@/modules/admin/actions/manage-client";
import { CLIENT_STATUSES, CLIENT_STATUS_CONFIG, type ClientStatus } from "@/modules/admin/lib/client-status";
import { MIN_PASSWORD_LENGTH } from "@/modules/admin/lib/constants";
import { CopyField } from "./copy-field";
type Client = { id: string; name: string; email: string };
type Client = { id: string; name: string; email: string; status: ClientStatus };
function ResetPasswordContent({ client, onDone }: { client: Client; onDone: () => void }) {
const [mode, setMode] = useState<"generate" | "manual">("generate");
@ -133,8 +135,60 @@ function EditClientContent({ client, onDone }: { client: Client; onDone: () => v
);
}
function StatusClientContent({ client, onDone }: { client: Client; onDone: () => void }) {
const [status, setStatus] = useState<ClientStatus>(client.status);
async function run(prev: Parameters<typeof updateClientStatus>[0], formData: FormData) {
const result = await updateClientStatus(prev, formData);
if (result && "success" in result) onDone();
return result;
}
const [state, formAction, pending] = useActionState(run, undefined);
return (
<>
<DialogHeader className="mb-4">
<DialogTitle>Status ändern</DialogTitle>
<DialogDescription>
Projektstatus von <span className="font-medium text-foreground">{client.name}</span>.
</DialogDescription>
</DialogHeader>
<form action={formAction}>
<input type="hidden" name="profileId" value={client.id} />
<FieldGroup>
<div role="radiogroup" aria-label="Status" className="grid gap-2">
{CLIENT_STATUSES.map((value) => (
<label
key={value}
className="flex cursor-pointer items-center gap-3 rounded-md border border-border px-3 py-2.5 text-sm has-checked:border-primary has-checked:bg-surface"
>
<input
type="radio"
name="status"
value={value}
checked={status === value}
onChange={() => setStatus(value)}
className="accent-primary"
/>
<Badge variant={CLIENT_STATUS_CONFIG[value].variant}>{CLIENT_STATUS_CONFIG[value].label}</Badge>
</label>
))}
</div>
{state && "error" in state && <p className="text-sm text-destructive">{state.error}</p>}
</FieldGroup>
<DialogFooter className="mt-6">
<Button type="submit" disabled={pending || status === client.status}>
{pending ? "Wird gespeichert..." : "Speichern"}
</Button>
</DialogFooter>
</form>
</>
);
}
export function ClientActionsMenu({ client }: { client: Client }) {
const [dialog, setDialog] = useState<"password" | "edit" | null>(null);
const [dialog, setDialog] = useState<"password" | "edit" | "status" | null>(null);
const [instanceKey, setInstanceKey] = useState(0);
function close() {
@ -149,6 +203,9 @@ export function ClientActionsMenu({ client }: { client: Client }) {
<MoreHorizontalIcon />
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-52">
<DropdownMenuItem onClick={() => setDialog("status")}>
<Info/> Status ändern
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setDialog("edit")}>
<PencilIcon /> Bearbeiten
</DropdownMenuItem>
@ -162,6 +219,7 @@ export function ClientActionsMenu({ client }: { client: Client }) {
<DialogContent>
{dialog === "password" && <ResetPasswordContent key={instanceKey} client={client} onDone={close} />}
{dialog === "edit" && <EditClientContent key={instanceKey} client={client} onDone={close} />}
{dialog === "status" && <StatusClientContent key={instanceKey} client={client} onDone={close}/> }
</DialogContent>
</Dialog>
</>

View file

@ -16,26 +16,16 @@ import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/ui/input-group";
import { AddClientDialog } from "./add-client-dialog";
import { CLIENT_STATUS_CONFIG, type ClientStatus } from "@/modules/admin/lib/client-status";
import { ClientActionsMenu } from "./client-actions-menu";
type Client = {
id: string;
name: string;
email: string;
status: ClientStatus;
};
const STATUS_CONFIG = {
current: { label: "Current", variant: "warning" as const },
done: { label: "Done", variant: "success" as const },
upcoming: { label: "Upcoming", variant: "neutral" as const },
};
// TODO: Status kommt aktuell nicht aus der DB, sobald Projekte existieren durch echten Wert ersetzen.
function getPlaceholderStatus(index: number): keyof typeof STATUS_CONFIG {
const statuses: (keyof typeof STATUS_CONFIG)[] = ["current", "done", "upcoming"];
return statuses[index % statuses.length];
}
export function ClientsTable({ clients }: { clients: Client[] }) {
const [query, setQuery] = useState("");
@ -81,8 +71,7 @@ export function ClientsTable({ clients }: { clients: Client[] }) {
</TableHeader>
<TableBody>
{filteredClients.map((client) => {
const index = clients.indexOf(client);
const status = STATUS_CONFIG[getPlaceholderStatus(index)];
const status = CLIENT_STATUS_CONFIG[client.status];
return (
<TableRow key={client.id}>

View file

@ -7,6 +7,7 @@ import { Input } from "@/components/ui/input"
import Image from "next/image"
import { Button } from "@/components/ui/button";
import { login } from "../../actions/auth";
import Link from "next/link";
const LoginPageView = () => {
const [showPassword, setShowPassword] = useState(false)
@ -72,8 +73,13 @@ const LoginPageView = () => {
</FieldGroup>
</form>
</div>
<div>
<div className="w-full flex items-center justify-between">
<p className="text-center text-muted-foreground text-sm sm:text-left">Bei Fragen: <a href="mailto:info@since3.de" className="underline">info@since3.de</a></p>
<div className="flex gap-4 text-sm">
<Link href="/impressum" className="hover:underline cursor-pointer">Impressum</Link>
<Link href="/datenschutz" className="hover:underline cursor-pointer">Datenschutz</Link>
<Link href="/agb" className="hover:underline cursor-pointer">AGB</Link>
</div>
</div>
</div>
)

View file

@ -16,6 +16,7 @@ import { LogoutButton } from "./logout-button";
import { SidebarMenuLink } from "./sidebar-menu-link";
import { ThemeToggle } from "./theme-toggle";
import UserBadge from "./user-badge";
import LegalButton from "./legal-button";
export function AppSidebar({ session }: { session: Session }) {
const menu = session.isAdmin ? adminMenu : clientMenu;
@ -60,6 +61,7 @@ export function AppSidebar({ session }: { session: Session }) {
<div className="flex items-center gap-2">
<LogoutButton />
<ThemeToggle />
<LegalButton/>
</div>
</SidebarFooter>
<SidebarRail />

View file

@ -0,0 +1,23 @@
import { Button } from "@/components/ui/button"
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { Scale } from "lucide-react"
import Link from "next/link"
const LegalButton = () => {
return (
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline"/>}>
<Scale/>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel><Link href="/impressum" className="hover:underline hover:text-black">Impressum</Link></DropdownMenuLabel>
<DropdownMenuLabel><Link href="/datenschutz" className="hover:underline hover:text-black">Datenschutz</Link></DropdownMenuLabel>
<DropdownMenuLabel><Link href="/agb" className="hover:underline hover:text-black">AGB</Link></DropdownMenuLabel>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
)
}
export default LegalButton

View file

@ -40,7 +40,7 @@ export function TermsDialog() {
<DialogTitle>Nutzungsbedingungen</DialogTitle>
<DialogDescription>
Bitte lies unsere{" "}
<a href="/terms" target="_blank" rel="noopener noreferrer">
<a href="/agb" target="_blank" rel="noopener noreferrer" className="underline">
Nutzungsbedingungen
</a>{" "}
und akzeptiere sie, um fortzufahren.

View file

@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
import { createClient } from "./lib/supabase/proxy";
const publicRoutes = ["/"]
const publicRoutes = ["/", "/impressum", "/datenschutz", "/agb"]
export default async function proxy(request: NextRequest) {
const { supabase, response } = createClient(request)