chore: stabilize apps/web (lint, build, typecheck fixes)
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Failing after 1m27s
Build & Deploy / 🏗️ Build (push) Failing after 1m31s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s

This commit is contained in:
2026-02-11 11:56:13 +01:00
parent 8ba81809b0
commit ecea90dc91
50 changed files with 5596 additions and 3456 deletions

View File

@@ -1,23 +1,23 @@
'use client';
"use client";
import * as React from 'react';
import { FormState } from '../types';
import { DESIGN_VIBES } from '../constants';
import { motion, AnimatePresence } from 'framer-motion';
import { Plus, X, Palette, Pipette, RefreshCw } from 'lucide-react';
import { Reveal } from '../../Reveal';
import { Input } from '../components/Input';
import { RepeatableList } from '../components/RepeatableList';
import * as React from "react";
import { FormState } from "../types";
import { DESIGN_VIBES } from "../constants";
import { motion, AnimatePresence } from "framer-motion";
import { Plus, X, Palette, Pipette, RefreshCw } from "lucide-react";
import { Reveal } from "../../Reveal";
import { Input } from "../components/Input";
import { RepeatableList } from "../components/RepeatableList";
interface DesignStepProps {
state: FormState;
updateState: (updates: Partial<FormState>) => void;
updateState: (_updates: Partial<FormState>) => void;
}
export function DesignStep({ state, updateState }: DesignStepProps) {
const addColor = () => {
if (state.colorScheme.length < 5) {
updateState({ colorScheme: [...state.colorScheme, '#000000'] });
updateState({ colorScheme: [...state.colorScheme, "#000000"] });
}
};
@@ -38,7 +38,7 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
const toggleDontKnow = (id: string) => {
const current = state.dontKnows || [];
if (current.includes(id)) {
updateState({ dontKnows: current.filter(i => i !== id) });
updateState({ dontKnows: current.filter((i) => i !== id) });
} else {
updateState({ dontKnows: [...current, id] });
}
@@ -51,11 +51,13 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
const hslToHex = (h: number, s: number, l: number) => {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const a = (s * Math.min(l, 1 - l)) / 100;
const f = (n: number) => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0');
return Math.round(255 * color)
.toString(16)
.padStart(2, "0");
};
return `#${f(0)}${f(8)}${f(4)}`;
};
@@ -63,7 +65,7 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
const count = state.colorScheme.length;
const palette = [];
for (let i = 0; i < count; i++) {
const h = (hue + (i * (360 / count))) % 360;
const h = (hue + i * (360 / count)) % 360;
const l = i === 0 ? 95 : i === count - 1 ? 20 : lightness;
palette.push(hslToHex(h, saturation, l));
}
@@ -77,16 +79,22 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
<div className="space-y-8">
<div className="flex justify-between items-center">
<div className="space-y-1">
<h4 className="text-2xl font-bold text-slate-900">Design-Richtung</h4>
<p className="text-slate-500">Welche Ästhetik passt zu Ihrer Marke?</p>
<h4 className="text-2xl font-bold text-slate-900">
Design-Richtung
</h4>
<p className="text-slate-500">
Welche Ästhetik passt zu Ihrer Marke?
</p>
</div>
<motion.button
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
type="button"
onClick={() => toggleDontKnow('design_vibe')}
onClick={() => toggleDontKnow("design_vibe")}
className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${
state.dontKnows?.includes('design_vibe') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'
state.dontKnows?.includes("design_vibe")
? "bg-slate-900 text-white"
: "bg-slate-100 text-slate-500 hover:bg-slate-200"
}`}
>
Ich weiß es nicht
@@ -100,14 +108,31 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
type="button"
onClick={() => updateState({ designVibe: vibe.id })}
className={`p-8 rounded-[2.5rem] border-2 text-left transition-all duration-500 focus:outline-none overflow-hidden relative group ${
state.designVibe === vibe.id ? 'border-slate-900 bg-slate-900 text-white' : 'border-slate-100 bg-white hover:border-slate-300'
state.designVibe === vibe.id
? "border-slate-900 bg-slate-900 text-white"
: "border-slate-100 bg-white hover:border-slate-300"
}`}
>
<div className={`w-16 h-10 mb-6 transition-transform duration-500 group-hover:scale-110 ${state.designVibe === vibe.id ? 'text-white' : 'text-black'}`}>{vibe.illustration}</div>
<h4 className={`text-2xl font-bold mb-3 ${state.designVibe === vibe.id ? 'text-white' : 'text-slate-900'}`}>{vibe.label}</h4>
<p className={`text-lg leading-relaxed ${state.designVibe === vibe.id ? 'text-slate-200' : 'text-slate-500'}`}>{vibe.desc}</p>
<div
className={`w-16 h-10 mb-6 transition-transform duration-500 group-hover:scale-110 ${state.designVibe === vibe.id ? "text-white" : "text-black"}`}
>
{vibe.illustration}
</div>
<h4
className={`text-2xl font-bold mb-3 ${state.designVibe === vibe.id ? "text-white" : "text-slate-900"}`}
>
{vibe.label}
</h4>
<p
className={`text-lg leading-relaxed ${state.designVibe === vibe.id ? "text-slate-200" : "text-slate-500"}`}
>
{vibe.desc}
</p>
{state.designVibe === vibe.id && (
<motion.div layoutId="activeVibe" className="absolute top-4 right-4 w-3 h-3 bg-white rounded-full" />
<motion.div
layoutId="activeVibe"
className="absolute top-4 right-4 w-3 h-3 bg-white rounded-full"
/>
)}
</motion.button>
))}
@@ -121,10 +146,13 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
<div className="flex justify-between items-center">
<div className="space-y-1">
<h4 className="text-2xl font-bold text-slate-900">Farbschema</h4>
<p className="text-slate-500">Definieren Sie Ihre Markenfarben oder lassen Sie sich inspirieren.</p>
<p className="text-slate-500">
Definieren Sie Ihre Markenfarben oder lassen Sie sich
inspirieren.
</p>
</div>
<div className="flex items-center gap-4">
<motion.button
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
type="button"
@@ -134,13 +162,15 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
<RefreshCw size={16} />
Zufall
</motion.button>
<motion.button
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
type="button"
onClick={() => toggleDontKnow('color_scheme')}
onClick={() => toggleDontKnow("color_scheme")}
className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${
state.dontKnows?.includes('color_scheme') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'
state.dontKnows?.includes("color_scheme")
? "bg-slate-900 text-white"
: "bg-slate-100 text-slate-500 hover:bg-slate-200"
}`}
>
Ich weiß es nicht
@@ -157,7 +187,7 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
<div className="flex flex-wrap gap-6">
<AnimatePresence mode="popLayout">
{state.colorScheme.map((color, i) => (
<motion.div
<motion.div
key={`${i}-${color}`}
layout
initial={{ opacity: 0, scale: 0.8 }}
@@ -166,17 +196,19 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
className="relative group"
>
<div className="relative w-24 h-24 rounded-3xl overflow-hidden border-2 border-white group-hover:scale-105 transition-transform duration-300">
<input
type="color"
value={color}
<input
type="color"
value={color}
onChange={(e) => updateColor(i, e.target.value)}
className="absolute inset-[-100%] w-[300%] h-[300%] cursor-pointer outline-none border-none appearance-none bg-transparent"
/>
<div className="absolute inset-0 pointer-events-none border border-black/5 rounded-3xl" />
</div>
<div className="mt-2 text-center font-mono text-[10px] text-slate-400 uppercase">{color}</div>
<div className="mt-2 text-center font-mono text-[10px] text-slate-400 uppercase">
{color}
</div>
{state.colorScheme.length > 1 && (
<motion.button
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
type="button"
@@ -190,20 +222,29 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
))}
</AnimatePresence>
{state.colorScheme.length < 5 && (
<motion.button
<motion.button
layout
whileHover={{ scale: 1.05, borderColor: '#0f172a', color: '#0f172a' }}
whileHover={{
scale: 1.05,
borderColor: "#0f172a",
color: "#0f172a",
}}
whileTap={{ scale: 0.95 }}
type="button"
onClick={addColor}
className="w-24 h-24 rounded-3xl border-2 border-dashed border-slate-300 flex flex-col items-center justify-center text-slate-400 transition-all duration-300 bg-white/50 hover:bg-white"
>
<Plus size={32} />
<span className="text-[10px] font-bold uppercase mt-1">Add</span>
<span className="text-[10px] font-bold uppercase mt-1">
Add
</span>
</motion.button>
)}
</div>
<p className="text-sm text-slate-400 font-medium">Klicken Sie auf eine Farbe, um sie anzupassen. Sie können bis zu 5 Farben definieren.</p>
<p className="text-sm text-slate-400 font-medium">
Klicken Sie auf eine Farbe, um sie anzupassen. Sie können bis zu 5
Farben definieren.
</p>
</div>
</div>
</Reveal>
@@ -212,14 +253,26 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
<Reveal width="100%" delay={0.3}>
<div className="space-y-8">
<div className="space-y-1">
<h4 className="text-2xl font-bold text-slate-900">Referenz-Websites</h4>
<p className="text-slate-500">Gibt es Websites, die Ihnen besonders gut gefallen?</p>
<h4 className="text-2xl font-bold text-slate-900">
Referenz-Websites
</h4>
<p className="text-slate-500">
Gibt es Websites, die Ihnen besonders gut gefallen?
</p>
</div>
<div className="p-10 bg-white border border-slate-100 rounded-[3rem]">
<RepeatableList
items={state.references || []}
onAdd={(v) => updateState({ references: [...(state.references || []), v] })}
onRemove={(i) => updateState({ references: (state.references || []).filter((_, idx) => idx !== i) })}
onAdd={(v) =>
updateState({ references: [...(state.references || []), v] })
}
onRemove={(i) =>
updateState({
references: (state.references || []).filter(
(_, idx) => idx !== i,
),
})
}
placeholder="https://beispiel.de"
/>
</div>