First commit
This commit is contained in:
commit
7cf3558ba7
12933 changed files with 1180047 additions and 0 deletions
66
resources/css/app.css
Normal file
66
resources/css/app.css
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
@import 'tailwindcss';
|
||||
@import '../../vendor/livewire/flux/dist/flux.css';
|
||||
|
||||
@source '../views';
|
||||
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
|
||||
@source '../../vendor/livewire/flux-pro/stubs/**/*.blade.php';
|
||||
@source '../../vendor/livewire/flux/stubs/**/*.blade.php';
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
@theme {
|
||||
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
|
||||
--color-zinc-50: #fafafa;
|
||||
--color-zinc-100: #f5f5f5;
|
||||
--color-zinc-200: #e5e5e5;
|
||||
--color-zinc-300: #d4d4d4;
|
||||
--color-zinc-400: #a3a3a3;
|
||||
--color-zinc-500: #737373;
|
||||
--color-zinc-600: #525252;
|
||||
--color-zinc-700: #404040;
|
||||
--color-zinc-800: #262626;
|
||||
--color-zinc-900: #171717;
|
||||
--color-zinc-950: #0a0a0a;
|
||||
|
||||
--color-accent: var(--color-neutral-800);
|
||||
--color-accent-content: var(--color-neutral-800);
|
||||
--color-accent-foreground: var(--color-white);
|
||||
}
|
||||
|
||||
@layer theme {
|
||||
.dark {
|
||||
--color-accent: var(--color-white);
|
||||
--color-accent-content: var(--color-white);
|
||||
--color-accent-foreground: var(--color-neutral-800);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentColor);
|
||||
}
|
||||
}
|
||||
|
||||
[data-flux-field]:not(ui-radio, ui-checkbox) {
|
||||
@apply grid gap-2;
|
||||
}
|
||||
|
||||
[data-flux-label] {
|
||||
@apply !mb-0 !leading-tight;
|
||||
}
|
||||
|
||||
input:focus[data-flux-control],
|
||||
textarea:focus[data-flux-control],
|
||||
select:focus[data-flux-control] {
|
||||
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-accent-foreground;
|
||||
}
|
||||
|
||||
/* \[:where(&)\]:size-4 {
|
||||
@apply size-4;
|
||||
} */
|
||||
67
resources/css/portal.css
Normal file
67
resources/css/portal.css
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
@import "tailwindcss";
|
||||
@import "../../vendor/livewire/flux/dist/flux.css";
|
||||
|
||||
@source '../views';
|
||||
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
|
||||
@source '../../vendor/livewire/flux-pro/stubs/**/*.blade.php';
|
||||
@source '../../vendor/livewire/flux/stubs/**/*.blade.php';
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
@theme {
|
||||
--font-sans: "Instrument Sans", ui-sans-serif, system-ui, sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
|
||||
"Noto Color Emoji";
|
||||
|
||||
--color-zinc-50: #fafafa;
|
||||
--color-zinc-100: #f5f5f5;
|
||||
--color-zinc-200: #e5e5e5;
|
||||
--color-zinc-300: #d4d4d4;
|
||||
--color-zinc-400: #a3a3a3;
|
||||
--color-zinc-500: #737373;
|
||||
--color-zinc-600: #525252;
|
||||
--color-zinc-700: #404040;
|
||||
--color-zinc-800: #262626;
|
||||
--color-zinc-900: #171717;
|
||||
--color-zinc-950: #0a0a0a;
|
||||
|
||||
--color-accent: var(--color-neutral-800);
|
||||
--color-accent-content: var(--color-neutral-800);
|
||||
--color-accent-foreground: var(--color-white);
|
||||
}
|
||||
|
||||
@layer theme {
|
||||
.dark {
|
||||
--color-accent: var(--color-white);
|
||||
--color-accent-content: var(--color-white);
|
||||
--color-accent-foreground: var(--color-neutral-800);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentColor);
|
||||
}
|
||||
}
|
||||
|
||||
[data-flux-field]:not(ui-radio, ui-checkbox) {
|
||||
@apply grid gap-2;
|
||||
}
|
||||
|
||||
[data-flux-label] {
|
||||
@apply !mb-0 !leading-tight;
|
||||
}
|
||||
|
||||
input:focus[data-flux-control],
|
||||
textarea:focus[data-flux-control],
|
||||
select:focus[data-flux-control] {
|
||||
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-accent-foreground;
|
||||
}
|
||||
|
||||
/* \[:where(&)\]:size-4 {
|
||||
@apply size-4;
|
||||
} */
|
||||
437
resources/css/web/shared-styles.css
Normal file
437
resources/css/web/shared-styles.css
Normal file
|
|
@ -0,0 +1,437 @@
|
|||
/* Shared styles for all web themes - no @apply directives */
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: hsl(var(--border));
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: hsl(var(--background));
|
||||
color: hsl(var(--foreground));
|
||||
font-family: var(--font-primary, 'Inter'), system-ui, -apple-system, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.025em;
|
||||
font-family: var(--font-secondary, 'Inter'), var(--font-primary, 'Inter'), system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
/* Typography scales */
|
||||
.text-hero {
|
||||
font-size: clamp(3rem, 4vw, 6rem);
|
||||
line-height: 1.1;
|
||||
font-weight: 300;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.text-section-title {
|
||||
font-size: clamp(1.6rem, 3vw, 3rem);
|
||||
font-weight: 300;
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.text-large {
|
||||
font-size: clamp(1.1rem, 2vw, 1.2rem);
|
||||
line-height: 1.625;
|
||||
}
|
||||
|
||||
/* Border utilities to override the global border-width: 0 */
|
||||
.border-t {
|
||||
border-top-width: 1px !important;
|
||||
}
|
||||
.border-b {
|
||||
border-bottom-width: 1px !important;
|
||||
}
|
||||
.border-l {
|
||||
border-left-width: 1px !important;
|
||||
}
|
||||
.border-r {
|
||||
border-right-width: 1px !important;
|
||||
}
|
||||
.border {
|
||||
border-width: 1px !important;
|
||||
}
|
||||
|
||||
/* Button styles */
|
||||
.btn-primary {
|
||||
background-color: hsl(var(--primary));
|
||||
color: hsl(var(--primary-foreground));
|
||||
padding: 0.75rem 2rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: hsl(var(--secondary));
|
||||
color: hsl(var(--secondary-foreground));
|
||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
.btn-primary-accent {
|
||||
background-color: hsl(var(--primary));
|
||||
color: hsl(var(--primary-foreground));
|
||||
border: 1px solid hsl(var(--border));
|
||||
padding: 0.75rem 2rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-primary-accent:hover {
|
||||
background-color: hsl(var(--accent));
|
||||
color: hsl(var(--accent-foreground));
|
||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: hsl(var(--secondary));
|
||||
color: hsl(var(--secondary-foreground));
|
||||
border: 1px solid hsl(var(--border));
|
||||
padding: 0.75rem 2rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: hsl(var(--primary));
|
||||
color: hsl(var(--primary-foreground));
|
||||
}
|
||||
|
||||
.btn-secondary-accent {
|
||||
background-color: hsl(var(--secondary));
|
||||
color: hsl(var(--secondary-foreground));
|
||||
border: 1px solid hsl(var(--border));
|
||||
padding: 0.75rem 2rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-secondary-accent:hover {
|
||||
background-color: hsl(var(--accent));
|
||||
color: hsl(var(--accent-foreground));
|
||||
}
|
||||
|
||||
.btn-accent {
|
||||
background-color: hsl(var(--accent));
|
||||
color: hsl(var(--accent-foreground));
|
||||
padding: 0.75rem 2rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-accent:hover {
|
||||
background-color: hsl(var(--secondary));
|
||||
color: hsl(var(--secondary-foreground));
|
||||
box-shadow: var(--shadow-accent-glow);
|
||||
}
|
||||
|
||||
/* Card styles */
|
||||
.card-elevated {
|
||||
background-color: hsl(var(--card));
|
||||
border-radius: 1rem;
|
||||
box-shadow: var(--shadow-card);
|
||||
border: 1px solid hsl(var(--border) / 0.5);
|
||||
}
|
||||
|
||||
/* Section styles */
|
||||
.section-padding {
|
||||
padding-top: 4rem;
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.section-padding {
|
||||
padding-top: 6rem;
|
||||
padding-bottom: 6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.section-dark {
|
||||
background-color: hsl(var(--dark-bg));
|
||||
color: hsl(var(--dark-text));
|
||||
}
|
||||
|
||||
.text-dark-muted {
|
||||
color: hsl(var(--dark-muted));
|
||||
}
|
||||
|
||||
/* Container styles */
|
||||
.container-padding {
|
||||
max-width: 80rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.container-padding {
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.container-padding {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.container-narrow {
|
||||
max-width: 56rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.container-narrow {
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.container-narrow {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Spacing utilities */
|
||||
.spacing-section > * + * {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.spacing-content > * + * {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.spacing-small > * + * {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
/* Additional utility classes for better consistency */
|
||||
.text-muted-foreground {
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.bg-background {
|
||||
background-color: hsl(var(--background));
|
||||
}
|
||||
|
||||
.text-foreground {
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
.bg-card {
|
||||
background-color: hsl(var(--card));
|
||||
}
|
||||
|
||||
.text-card-foreground {
|
||||
color: hsl(var(--card-foreground));
|
||||
}
|
||||
|
||||
.border-border {
|
||||
border-color: hsl(var(--border));
|
||||
}
|
||||
|
||||
.text-secondary {
|
||||
color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.bg-secondary {
|
||||
background-color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.text-secondary-foreground {
|
||||
color: hsl(var(--secondary-foreground));
|
||||
}
|
||||
|
||||
.bg-primary {
|
||||
background-color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.text-primary-foreground {
|
||||
color: hsl(var(--primary-foreground));
|
||||
}
|
||||
|
||||
.bg-accent {
|
||||
background-color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
.text-accent-foreground {
|
||||
color: hsl(var(--accent-foreground));
|
||||
}
|
||||
|
||||
.bg-muted {
|
||||
background-color: hsl(var(--muted));
|
||||
}
|
||||
|
||||
.bg-muted\/20 {
|
||||
background-color: hsl(var(--muted) / 0.2);
|
||||
}
|
||||
|
||||
.bg-secondary\/10 {
|
||||
background-color: hsl(var(--secondary) / 0.1);
|
||||
}
|
||||
|
||||
.bg-secondary\/20 {
|
||||
background-color: hsl(var(--secondary) / 0.2);
|
||||
}
|
||||
|
||||
.bg-card\/95 {
|
||||
background-color: hsl(var(--card) / 0.95);
|
||||
}
|
||||
|
||||
.border-border\/50 {
|
||||
border-color: hsl(var(--border) / 0.5);
|
||||
}
|
||||
|
||||
.border-border\/30 {
|
||||
border-color: hsl(var(--border) / 0.3);
|
||||
}
|
||||
|
||||
.text-dark-muted {
|
||||
color: hsl(var(--dark-muted));
|
||||
}
|
||||
|
||||
.border-dark-muted\/30 {
|
||||
border-color: hsl(var(--dark-muted) / 0.3);
|
||||
}
|
||||
|
||||
.text-dark-text {
|
||||
color: hsl(var(--dark-text));
|
||||
}
|
||||
|
||||
.bg-dark-bg {
|
||||
background-color: hsl(var(--dark-bg));
|
||||
}
|
||||
|
||||
.bg-hero-container {
|
||||
background-color: hsl(var(--hero-container));
|
||||
}
|
||||
|
||||
.shadow-elevated {
|
||||
box-shadow: var(--shadow-elevated);
|
||||
}
|
||||
|
||||
.shadow-card {
|
||||
box-shadow: var(--shadow-card);
|
||||
}
|
||||
|
||||
.shadow-accent-glow {
|
||||
box-shadow: var(--shadow-accent-glow);
|
||||
}
|
||||
|
||||
/* Theme-spezifische Farben für Tailwind-Kompatibilität */
|
||||
.text-primary {
|
||||
color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.text-secondary {
|
||||
color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.text-muted-foreground {
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.bg-primary {
|
||||
background-color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.bg-secondary {
|
||||
background-color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.border-primary {
|
||||
border-color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.border-secondary {
|
||||
border-color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
/* Hover-Effekte für Navigation */
|
||||
.hover-text-secondary:hover {
|
||||
color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.hover-text-primary:hover {
|
||||
color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.hover-bg-primary:hover {
|
||||
background-color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.hover-bg-secondary:hover {
|
||||
background-color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.hover-border-secondary:hover {
|
||||
border-color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.hover-shadow-accent-glow:hover {
|
||||
box-shadow: var(--shadow-accent-glow);
|
||||
}
|
||||
|
||||
/* TopBar specific styles */
|
||||
.topbar-normal {
|
||||
background-color: hsl(var(--muted) / 0.2);
|
||||
border-bottom: 1px solid hsl(var(--border) / 0.3);
|
||||
}
|
||||
|
||||
/* Sticky Header Verhalten */
|
||||
.header-sticky {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 50;
|
||||
background-color: hsl(var(--background) / 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.header-normal {
|
||||
position: relative;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.bg-muted\/20 {
|
||||
background-color: hsl(var(--muted) / 0.2);
|
||||
}
|
||||
|
||||
.border-border\/30 {
|
||||
border-color: hsl(var(--border) / 0.3);
|
||||
}
|
||||
55
resources/css/web/theme-b2a.css
Normal file
55
resources/css/web/theme-b2a.css
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
/* B2A Domain Theme - Azur Blue & Liberty Red */
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* Base colors */
|
||||
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
|
||||
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
--card: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
|
||||
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
|
||||
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* B2A Theme Colors */
|
||||
--primary: 207 70% 26%; /* #123f6d - Azur Blue */
|
||||
--primary-foreground: 30 25% 98%; /* #faf9f7 - Off White */
|
||||
--secondary: 352 76% 48%; /* #ce1d2e - Liberty Red */
|
||||
--secondary-foreground: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
|
||||
|
||||
/* Neutral colors */
|
||||
--muted: 0 0% 92%; /* hsl(0 0% 92%) - Light Muted */
|
||||
--muted-foreground: 199 50% 45%; /* #4a8bb5 - Muted Blue */
|
||||
--accent: 210 20% 95%; /* hsl(201 20% 95%) - Light Accent */
|
||||
--accent-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Dark section colors */
|
||||
--dark-bg: 207 70% 26%; /* #123f6d - Azur Blue */
|
||||
--dark-text: 30 25% 98%; /* #faf9f7 - Off White */
|
||||
--dark-muted: 30 20% 70%; /* #b8b0a7 - Dark Muted */
|
||||
|
||||
/* Interactive elements */
|
||||
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
|
||||
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
|
||||
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
|
||||
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
|
||||
--ring: 20 14% 16%; /* #2a2a2a - Focus Ring */
|
||||
--radius: 0.75rem;
|
||||
|
||||
/* Hero container background */
|
||||
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
|
||||
|
||||
/* Shadows */
|
||||
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
|
||||
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
|
||||
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
|
||||
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
|
||||
|
||||
/* Font families */
|
||||
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
--font-secondary: 'Merriweather', Georgia, serif;
|
||||
}
|
||||
}
|
||||
|
||||
@import "./shared-styles.css";
|
||||
68
resources/css/web/theme-b2in.css
Normal file
68
resources/css/web/theme-b2in.css
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
/* B2IN Domain Theme - Anthracite & Dynamic Blue */
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* Base colors */
|
||||
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
|
||||
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Card colors */
|
||||
--card: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
|
||||
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
|
||||
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* B2IN Theme Colors */
|
||||
--primary: 209 32% 25%; /* #2b3f51 - Anthracite */
|
||||
--primary-foreground: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
|
||||
|
||||
--secondary: 199 74% 49%; /* #20a0da - Dynamic Blue */
|
||||
--secondary-foreground: 0 25% 96%; /* hsl(0 25% 96%) - Off White */
|
||||
|
||||
/* Neutral colors */
|
||||
--muted: 0 0% 92%; /* hsl(0 0% 92%) - Light Muted */
|
||||
--muted-foreground: 199 50% 45%; /* #4a8bb5 - Muted Blue */
|
||||
|
||||
--accent: 210 0% 94%; /* hsl(210 5.26% 92.55%) - Light Accent */
|
||||
--accent-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Dark section colors */
|
||||
--dark-bg: 209 32% 25%; /* Matching primary */
|
||||
--dark-text: 0 0% 100%; /* hsl(0 0% 100%) - Off White */
|
||||
--dark-muted: 0 0% 80%; /* hsl(0 0% 80%) - Dark Muted */
|
||||
|
||||
/* Interactive elements */
|
||||
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
|
||||
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
|
||||
|
||||
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
|
||||
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
|
||||
--ring: 20 14% 16%; /* #2a2a2a - Focus Ring */
|
||||
|
||||
--radius: 0.75rem;
|
||||
|
||||
/* Hero container background */
|
||||
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
|
||||
|
||||
/* Consistent shadows */
|
||||
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
|
||||
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
|
||||
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
|
||||
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
|
||||
|
||||
/* Transitions */
|
||||
--transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--transition-bounce: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
|
||||
/* Font families */
|
||||
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
--font-secondary: 'IBM Plex Sans', 'Inter', system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
}
|
||||
.text-section-title {
|
||||
line-height: 0.95em;
|
||||
}
|
||||
@import "./shared-styles.css";
|
||||
63
resources/css/web/theme-main.css
Normal file
63
resources/css/web/theme-main.css
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
@source '../../views/web/layout.blade.php';
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
@theme {
|
||||
--font-sans: "Instrument Sans", ui-sans-serif, system-ui, sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
|
||||
"Noto Color Emoji";
|
||||
|
||||
--color-zinc-50: #fafafa;
|
||||
--color-zinc-100: #f5f5f5;
|
||||
--color-zinc-200: #e5e5e5;
|
||||
--color-zinc-300: #d4d4d4;
|
||||
--color-zinc-400: #a3a3a3;
|
||||
--color-zinc-500: #737373;
|
||||
--color-zinc-600: #525252;
|
||||
--color-zinc-700: #404040;
|
||||
--color-zinc-800: #262626;
|
||||
--color-zinc-900: #171717;
|
||||
--color-zinc-950: #0a0a0a;
|
||||
|
||||
--color-accent: var(--color-neutral-800);
|
||||
--color-accent-content: var(--color-neutral-800);
|
||||
--color-accent-foreground: var(--color-white);
|
||||
}
|
||||
|
||||
@layer theme {
|
||||
.dark {
|
||||
--color-accent: var(--color-white);
|
||||
--color-accent-content: var(--color-white);
|
||||
--color-accent-foreground: var(--color-neutral-800);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentColor);
|
||||
}
|
||||
}
|
||||
|
||||
[data-flux-field]:not(ui-radio, ui-checkbox) {
|
||||
@apply grid gap-2;
|
||||
}
|
||||
|
||||
[data-flux-label] {
|
||||
@apply !mb-0 !leading-tight;
|
||||
}
|
||||
|
||||
input:focus[data-flux-control],
|
||||
textarea:focus[data-flux-control],
|
||||
select:focus[data-flux-control] {
|
||||
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-accent-foreground;
|
||||
}
|
||||
|
||||
/* \[:where(&)\]:size-4 {
|
||||
@apply size-4;
|
||||
} */
|
||||
58
resources/css/web/theme-stileigentum.css
Normal file
58
resources/css/web/theme-stileigentum.css
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
/* Stileigentum Domain Theme - Style Blue & Style Sun */
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* Base colors */
|
||||
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
|
||||
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
--card: 38 40% 97%; /* #hsl(60 53.33% 88.24%) - Off White */
|
||||
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
|
||||
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Stileigentum Theme Colors */
|
||||
--primary: 209 65% 20%; /* #123453 - Imperial Blue */
|
||||
--primary-foreground: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
|
||||
--secondary: 38 40% 66%; /* #c9ac84 - Sand Gold */
|
||||
--secondary-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Neutral colors */
|
||||
--muted: 209 35% 94%; /* #f0f2f5 - Very Light Imperial Blue */
|
||||
--muted-foreground: 209 10% 40%; /* hsl(208 9.09% 32.35%) - Muted Imperial Blue */
|
||||
--accent: 38 40% 88%; /* hsl(38 40% 88%) - Very Light Sand Gold */
|
||||
--accent-foreground: 209 10% 40%; /* hsl(204 4.35% 22.55%) - Darker Imperial Blue */
|
||||
|
||||
/* Dark section colors */
|
||||
--dark-bg: 209 65% 20%; /* #123453 - Imperial Blue */
|
||||
--dark-text: 0 0% 100%; /* hsl(0 0% 100%) - Off White */
|
||||
--dark-muted: 30 20% 70%; /* #b8b0a7 - Dark Muted */
|
||||
|
||||
/* Interactive elements */
|
||||
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
|
||||
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
|
||||
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
|
||||
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
|
||||
--radius: 0.75rem;
|
||||
|
||||
/* Hero container background */
|
||||
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
|
||||
|
||||
/* Shadows */
|
||||
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
|
||||
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
|
||||
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
|
||||
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
|
||||
|
||||
/* Font families */
|
||||
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
--font-secondary: 'EB Garamond', Georgia, serif;
|
||||
}
|
||||
}
|
||||
|
||||
.text-section-title {
|
||||
line-height: 0.95em;
|
||||
}
|
||||
|
||||
@import "./shared-styles.css";
|
||||
72
resources/css/web/theme-style2own.css
Normal file
72
resources/css/web/theme-style2own.css
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
/* Style2own Domain Theme - Imperial Blue & Sand Gold */
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* Base colors */
|
||||
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
|
||||
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
--card: 30 25% 98%; /* #faf9f7 - Off White */
|
||||
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
|
||||
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Style2own Theme Colors */
|
||||
--primary: 195 100% 34%; /* #007aab - Style Blue */
|
||||
--primary-foreground: 30 25% 98%; /* #faf9f7 - Off White */
|
||||
--secondary: 46 95% 56%; /* #fbaf22 - Style Sun */
|
||||
--secondary-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Neutral colors */
|
||||
--muted: 0 0% 92%; /* hsl(0 0% 92%) - Light Muted */
|
||||
--muted-foreground: 199 50% 45%; /* #4a8bb5 - Muted Blue */
|
||||
--accent: 210 20% 95%; /* #f2f5f7 - Light Accent */
|
||||
--accent-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
|
||||
|
||||
/* Dark section colors */
|
||||
--dark-bg: 195 100% 34%; /* #007aab - Style Blue */
|
||||
--dark-text: 30 25% 98%; /* #faf9f7 - Off White */
|
||||
--dark-muted: 30 20% 70%; /* #b8b0a7 - Dark Muted */
|
||||
|
||||
/* Interactive elements */
|
||||
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
|
||||
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
|
||||
--border: 32 20% 90%; /* #e6e0d8 - Light Border */
|
||||
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
|
||||
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
|
||||
--radius: 0.75rem;
|
||||
|
||||
/* Hero container background */
|
||||
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
|
||||
|
||||
/* Shadows */
|
||||
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
|
||||
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
|
||||
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
|
||||
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
|
||||
|
||||
/* Font families */
|
||||
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
--font-secondary: 'Ephesis', cursive;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Font size adjustments for Ephesis font - 30% larger */
|
||||
.text-hero {
|
||||
font-size: clamp(3.6rem, 4.2vw, 7.8rem) !important;
|
||||
}
|
||||
|
||||
.text-section-title {
|
||||
font-size: clamp(2.1rem, 3.9vw, 3.9rem) !important;
|
||||
line-height: 0.85em;
|
||||
}
|
||||
|
||||
.text-xl {
|
||||
font-size: clamp(1.3rem, 2.2vw, 2.2rem) !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@import "./shared-styles.css";
|
||||
0
resources/js/admin.js
Normal file
0
resources/js/admin.js
Normal file
1
resources/js/app.js
Normal file
1
resources/js/app.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
// App JS ohne Alpine-Initialisierung. Alpine wird von Livewire verwaltet.
|
||||
6
resources/lang/de/messages.php
Normal file
6
resources/lang/de/messages.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Willkommen bei :domain' => 'Willkommen bei :domain',
|
||||
'Sprache' => 'Sprache',
|
||||
];
|
||||
6
resources/lang/en/messages.php
Normal file
6
resources/lang/en/messages.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Willkommen bei :domain' => 'Welcome to :domain',
|
||||
'Sprache' => 'Language',
|
||||
];
|
||||
6
resources/lang/es/messages.php
Normal file
6
resources/lang/es/messages.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Willkommen bei :domain' => 'Bienvenido a :domain',
|
||||
'Sprache' => 'Idioma',
|
||||
];
|
||||
6
resources/lang/fr/messages.php
Normal file
6
resources/lang/fr/messages.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Willkommen bei :domain' => 'Bienvenue chez :domain',
|
||||
'Sprache' => 'Langue',
|
||||
];
|
||||
18
resources/views/admin/dashboard.blade.php
Normal file
18
resources/views/admin/dashboard.blade.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<x-layouts.app title="Dashboard">
|
||||
<div class="flex h-full w-full flex-1 flex-col gap-4 rounded-xl">
|
||||
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
|
||||
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700 p-4">
|
||||
<livewire:notifications />
|
||||
</div>
|
||||
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
|
||||
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
|
||||
</div>
|
||||
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
|
||||
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative h-full flex-1 overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
|
||||
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
|
||||
</div>
|
||||
</div>
|
||||
</x-layouts.app>
|
||||
14
resources/views/components/action-message.blade.php
Normal file
14
resources/views/components/action-message.blade.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
@props([
|
||||
'on',
|
||||
])
|
||||
|
||||
<div
|
||||
x-data="{ shown: false, timeout: null }"
|
||||
x-init="@this.on('{{ $on }}', () => { clearTimeout(timeout); shown = true; timeout = setTimeout(() => { shown = false }, 2000); })"
|
||||
x-show.transition.out.opacity.duration.1500ms="shown"
|
||||
x-transition:leave.opacity.duration.1500ms
|
||||
style="display: none"
|
||||
{{ $attributes->merge(['class' => 'text-sm']) }}
|
||||
>
|
||||
{{ $slot->isEmpty() ? __('Saved.') : $slot }}
|
||||
</div>
|
||||
8
resources/views/components/app-logo-icon.blade.php
Normal file
8
resources/views/components/app-logo-icon.blade.php
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 42" {{ $attributes }}>
|
||||
<path
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M17.2 5.633 8.6.855 0 5.633v26.51l16.2 9 16.2-9v-8.442l7.6-4.223V9.856l-8.6-4.777-8.6 4.777V18.3l-5.6 3.111V5.633ZM38 18.301l-5.6 3.11v-6.157l5.6-3.11V18.3Zm-1.06-7.856-5.54 3.078-5.54-3.079 5.54-3.078 5.54 3.079ZM24.8 18.3v-6.157l5.6 3.111v6.158L24.8 18.3Zm-1 1.732 5.54 3.078-13.14 7.302-5.54-3.078 13.14-7.3v-.002Zm-16.2 7.89 7.6 4.222V38.3L2 30.966V7.92l5.6 3.111v16.892ZM8.6 9.3 3.06 6.222 8.6 3.143l5.54 3.08L8.6 9.3Zm21.8 15.51-13.2 7.334V38.3l13.2-7.334v-6.156ZM9.6 11.034l5.6-3.11v14.6l-5.6 3.11v-14.6Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 714 B |
6
resources/views/components/app-logo.blade.php
Normal file
6
resources/views/components/app-logo.blade.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<div class="flex aspect-square size-8 items-center justify-center rounded-md bg-accent-content text-accent-foreground">
|
||||
<x-app-logo-icon class="size-5 fill-current text-white dark:text-black" />
|
||||
</div>
|
||||
<div class="ms-1 grid flex-1 text-start text-sm">
|
||||
<span class="mb-0.5 truncate leading-none font-semibold">B2IN</span>
|
||||
</div>
|
||||
9
resources/views/components/auth-header.blade.php
Normal file
9
resources/views/components/auth-header.blade.php
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
@props([
|
||||
'title',
|
||||
'description',
|
||||
])
|
||||
|
||||
<div class="flex w-full flex-col text-center">
|
||||
<flux:heading size="xl">{{ $title }}</flux:heading>
|
||||
<flux:subheading>{{ $description }}</flux:subheading>
|
||||
</div>
|
||||
9
resources/views/components/auth-session-status.blade.php
Normal file
9
resources/views/components/auth-session-status.blade.php
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
@props([
|
||||
'status',
|
||||
])
|
||||
|
||||
@if ($status)
|
||||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600']) }}>
|
||||
{{ $status }}
|
||||
</div>
|
||||
@endif
|
||||
5
resources/views/components/layouts/app.blade.php
Normal file
5
resources/views/components/layouts/app.blade.php
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<x-layouts.app.sidebar :title="$title ?? null">
|
||||
<flux:main>
|
||||
{{ $slot }}
|
||||
</flux:main>
|
||||
</x-layouts.app.sidebar>
|
||||
124
resources/views/components/layouts/app/header.blade.php
Normal file
124
resources/views/components/layouts/app/header.blade.php
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
||||
<head>
|
||||
@include('partials.head')
|
||||
</head>
|
||||
<body class="min-h-screen bg-white dark:bg-zinc-800">
|
||||
<flux:header container class="border-b border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />
|
||||
|
||||
<a href="{{ route('dashboard') }}" class="ms-2 me-5 flex items-center space-x-2 rtl:space-x-reverse lg:ms-0" wire:navigate>
|
||||
<x-app-logo />
|
||||
</a>
|
||||
|
||||
<flux:navbar class="-mb-px max-lg:hidden">
|
||||
<flux:navbar.item icon="layout-grid" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
|
||||
{{ __('Dashboard') }}
|
||||
</flux:navbar.item>
|
||||
</flux:navbar>
|
||||
|
||||
<flux:spacer />
|
||||
|
||||
<flux:navbar class="me-1.5 space-x-0.5 rtl:space-x-reverse py-0!">
|
||||
<flux:tooltip :content="__('Search')" position="bottom">
|
||||
<flux:navbar.item class="!h-10 [&>div>svg]:size-5" icon="magnifying-glass" href="#" :label="__('Search')" />
|
||||
</flux:tooltip>
|
||||
<flux:tooltip :content="__('Repository')" position="bottom">
|
||||
<flux:navbar.item
|
||||
class="h-10 max-lg:hidden [&>div>svg]:size-5"
|
||||
icon="folder-git-2"
|
||||
href="https://github.com/laravel/livewire-starter-kit"
|
||||
target="_blank"
|
||||
:label="__('Repository')"
|
||||
/>
|
||||
</flux:tooltip>
|
||||
<flux:tooltip :content="__('Documentation')" position="bottom">
|
||||
<flux:navbar.item
|
||||
class="h-10 max-lg:hidden [&>div>svg]:size-5"
|
||||
icon="book-open-text"
|
||||
href="https://laravel.com/docs/starter-kits#livewire"
|
||||
target="_blank"
|
||||
label="Documentation"
|
||||
/>
|
||||
</flux:tooltip>
|
||||
</flux:navbar>
|
||||
|
||||
<!-- Desktop User Menu -->
|
||||
<flux:dropdown position="top" align="end">
|
||||
<flux:profile
|
||||
class="cursor-pointer"
|
||||
:initials="auth()->user()->initials()"
|
||||
/>
|
||||
|
||||
<flux:menu>
|
||||
<flux:menu.radio.group>
|
||||
<div class="p-0 text-sm font-normal">
|
||||
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
|
||||
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
|
||||
<span
|
||||
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
|
||||
>
|
||||
{{ auth()->user()->initials() }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="grid flex-1 text-start text-sm leading-tight">
|
||||
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
|
||||
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</flux:menu.radio.group>
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
<flux:menu.radio.group>
|
||||
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
|
||||
</flux:menu.radio.group>
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
<form method="POST" action="{{ route('logout') }}" class="w-full">
|
||||
@csrf
|
||||
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
|
||||
{{ __('Log Out') }}
|
||||
</flux:menu.item>
|
||||
</form>
|
||||
</flux:menu>
|
||||
</flux:dropdown>
|
||||
</flux:header>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<flux:sidebar stashable sticky class="lg:hidden border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
|
||||
|
||||
<a href="{{ route('dashboard') }}" class="ms-1 flex items-center space-x-2 rtl:space-x-reverse" wire:navigate>
|
||||
<x-app-logo />
|
||||
</a>
|
||||
|
||||
<flux:navlist variant="outline">
|
||||
<flux:navlist.group :heading="__('Platform')">
|
||||
<flux:navlist.item icon="layout-grid" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
|
||||
{{ __('Dashboard') }}
|
||||
</flux:navlist.item>
|
||||
</flux:navlist.group>
|
||||
</flux:navlist>
|
||||
|
||||
<flux:spacer />
|
||||
|
||||
<flux:navlist variant="outline">
|
||||
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
|
||||
{{ __('Repository') }}
|
||||
</flux:navlist.item>
|
||||
|
||||
<flux:navlist.item icon="book-open-text" href="https://laravel.com/docs/starter-kits#livewire" target="_blank">
|
||||
{{ __('Documentation') }}
|
||||
</flux:navlist.item>
|
||||
</flux:navlist>
|
||||
</flux:sidebar>
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
@fluxScripts
|
||||
</body>
|
||||
</html>
|
||||
166
resources/views/components/layouts/app/sidebar.blade.php
Normal file
166
resources/views/components/layouts/app/sidebar.blade.php
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
||||
<head>
|
||||
@include('partials.head')
|
||||
</head>
|
||||
<body class="min-h-screen bg-white dark:bg-zinc-800">
|
||||
<flux:sidebar sticky stashable class="border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
|
||||
<a href="{{ config('domains.domain_main_url') }}" class="me-5 flex items-center space-x-2 rtl:space-x-reverse">
|
||||
<x-app-logo />
|
||||
</a>
|
||||
|
||||
<flux:navlist variant="outline">
|
||||
<flux:navlist.group :heading="__('Trader')" class="grid mb-4">
|
||||
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
||||
</flux:navlist.group>
|
||||
|
||||
<flux:navlist.group :heading="__('Customer')" class="grid mb-4">
|
||||
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
||||
</flux:navlist.group>
|
||||
|
||||
<flux:navlist.group :heading="__('Admin')" class="grid mb-4">
|
||||
<flux:navlist.item icon="user-group" :href="route('admin.users')" :current="request()->routeIs('admin.users')" wire:navigate>{{ __('Users') }}</flux:navlist.item>
|
||||
<flux:navlist.item icon="user-group" :href="route('admin.users.table')" :current="request()->routeIs('admin.users.table')" wire:navigate>{{ __('Users Table') }}</flux:navlist.item>
|
||||
<flux:navlist.group expandable expanded="false" heading="Favorites" class="hidden lg:grid">
|
||||
<flux:navlist.item icon="user-group" :href="route('admin.users')" :current="request()->routeIs('admin.users')" wire:navigate>{{ __('Users') }}</flux:navlist.item>
|
||||
<flux:navlist.item icon="user-group" :href="route('admin.users.table')" :current="request()->routeIs('admin.users.table')" wire:navigate>{{ __('Users Table') }}</flux:navlist.item>
|
||||
</flux:navlist.group>
|
||||
</flux:navlist.group>
|
||||
|
||||
<flux:navlist.group :heading="__('CMS')" class="grid mb-4">
|
||||
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
||||
</flux:navlist.group>
|
||||
|
||||
|
||||
<flux:navlist.group :heading="__('Superadmin')" class="grid mb-4">
|
||||
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
|
||||
</flux:navlist.group>
|
||||
</flux:navlist>
|
||||
|
||||
<flux:spacer />
|
||||
|
||||
<flux:navlist variant="outline">
|
||||
<flux:navlist.group :heading="__('Resources')">
|
||||
<flux:navlist.item icon="pencil" href="https://tailwindcss.com/docs/installation/using-vite" target="_blank">
|
||||
{{ __('Tailwind CSS') }}
|
||||
</flux:navlist.item>
|
||||
<flux:navlist.item icon="shield-check" href="https://heroicons.com" target="_blank">
|
||||
{{ __('Hero Icons') }}
|
||||
</flux:navlist.item>
|
||||
<flux:navlist.item icon="bolt" href="https://fluxui.dev/docs/installation" target="_blank">
|
||||
{{ __('Flux UI') }}
|
||||
</flux:navlist.item>
|
||||
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
|
||||
{{ __('Repository') }}
|
||||
</flux:navlist.item>
|
||||
|
||||
<flux:navlist.item icon="book-open-text" href="https://laravel.com/docs/starter-kits" target="_blank">
|
||||
{{ __('Documentation') }}
|
||||
</flux:navlist.item>
|
||||
</flux:navlist.group>
|
||||
</flux:navlist>
|
||||
<!-- Desktop User Menu -->
|
||||
<flux:dropdown position="bottom" align="start">
|
||||
<flux:profile
|
||||
:name="auth()->user()->name"
|
||||
:initials="auth()->user()->initials()"
|
||||
icon-trailing="chevrons-up-down"
|
||||
/>
|
||||
|
||||
<flux:menu class="w-[220px]">
|
||||
<flux:menu.radio.group>
|
||||
<div class="p-0 text-sm font-normal">
|
||||
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
|
||||
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
|
||||
<span
|
||||
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
|
||||
>
|
||||
{{ auth()->user()->initials() }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="grid flex-1 text-start text-sm leading-tight">
|
||||
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
|
||||
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</flux:menu.radio.group>
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
<flux:menu.radio.group>
|
||||
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
|
||||
</flux:menu.radio.group>
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
<form method="POST" action="{{ route('logout') }}" class="w-full">
|
||||
@csrf
|
||||
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
|
||||
{{ __('Log Out') }}
|
||||
</flux:menu.item>
|
||||
</form>
|
||||
</flux:menu>
|
||||
</flux:dropdown>
|
||||
</flux:sidebar>
|
||||
|
||||
<!-- Mobile User Menu -->
|
||||
<flux:header class="lg:hidden">
|
||||
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />
|
||||
|
||||
<a href="{{ config('domains.domain_main_url') }}" class="me-5 ml-2 flex items-center space-x-2 rtl:space-x-reverse">
|
||||
<x-app-logo />
|
||||
</a>
|
||||
<flux:spacer />
|
||||
|
||||
<flux:dropdown position="top" align="end">
|
||||
<flux:profile
|
||||
:initials="auth()->user()->initials()"
|
||||
icon-trailing="chevron-down"
|
||||
/>
|
||||
|
||||
<flux:menu>
|
||||
<flux:menu.radio.group>
|
||||
<div class="p-0 text-sm font-normal">
|
||||
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
|
||||
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
|
||||
<span
|
||||
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
|
||||
>
|
||||
{{ auth()->user()->initials() }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<div class="grid flex-1 text-start text-sm leading-tight">
|
||||
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
|
||||
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</flux:menu.radio.group>
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
<flux:menu.radio.group>
|
||||
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
|
||||
</flux:menu.radio.group>
|
||||
|
||||
<flux:menu.separator />
|
||||
|
||||
<form method="POST" action="{{ route('logout') }}" class="w-full">
|
||||
@csrf
|
||||
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
|
||||
{{ __('Log Out') }}
|
||||
</flux:menu.item>
|
||||
</form>
|
||||
</flux:menu>
|
||||
</flux:dropdown>
|
||||
</flux:header>
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
@fluxScripts
|
||||
</body>
|
||||
</html>
|
||||
3
resources/views/components/layouts/auth.blade.php
Normal file
3
resources/views/components/layouts/auth.blade.php
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<x-layouts.auth.simple :title="$title ?? null">
|
||||
{{ $slot }}
|
||||
</x-layouts.auth.simple>
|
||||
26
resources/views/components/layouts/auth/card.blade.php
Normal file
26
resources/views/components/layouts/auth/card.blade.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
||||
<head>
|
||||
@include('partials.head')
|
||||
</head>
|
||||
<body class="min-h-screen bg-neutral-100 antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
|
||||
<div class="bg-muted flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
|
||||
<div class="flex w-full max-w-md flex-col gap-6">
|
||||
<a href="{{ route('home') }}" class="flex flex-col items-center gap-2 font-medium" wire:navigate>
|
||||
<span class="flex h-9 w-9 items-center justify-center rounded-md">
|
||||
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
|
||||
</span>
|
||||
|
||||
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
|
||||
</a>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<div class="rounded-xl border bg-white dark:bg-stone-950 dark:border-stone-800 text-stone-800 shadow-xs">
|
||||
<div class="px-10 py-8">{{ $slot }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@fluxScripts
|
||||
</body>
|
||||
</html>
|
||||
35
resources/views/components/layouts/auth/simple.blade.php
Normal file
35
resources/views/components/layouts/auth/simple.blade.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
||||
<head>
|
||||
@include('partials.head')
|
||||
</head>
|
||||
<body class="min-h-screen bg-white antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
|
||||
<div class="bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
|
||||
<div class="flex w-full max-w-sm flex-col gap-2">
|
||||
<a href="{{ route('home') }}" class="flex flex-col items-center gap-2 font-medium" wire:navigate>
|
||||
<span class="flex h-9 w-9 mb-1 items-center justify-center rounded-md">
|
||||
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
|
||||
</span>
|
||||
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
|
||||
</a>
|
||||
<div class="flex flex-col gap-6">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@livewireScripts
|
||||
@fluxScripts
|
||||
<script src="{{ asset('vendor/livewire/livewire.js') }}"></script>
|
||||
|
||||
<!-- Debug: Script-Status -->
|
||||
<script>
|
||||
console.log('Body Scripts geladen');
|
||||
console.log('Livewire JS:', {{ file_exists(public_path('vendor/livewire/livewire.js')) ? 'true' : 'false' }});
|
||||
if (typeof Livewire !== 'undefined') {
|
||||
console.log('Livewire verfügbar:', true);
|
||||
} else {
|
||||
console.log('Livewire verfügbar:', false);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
43
resources/views/components/layouts/auth/split.blade.php
Normal file
43
resources/views/components/layouts/auth/split.blade.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
||||
<head>
|
||||
@include('partials.head')
|
||||
</head>
|
||||
<body class="min-h-screen bg-white antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
|
||||
<div class="relative grid h-dvh flex-col items-center justify-center px-8 sm:px-0 lg:max-w-none lg:grid-cols-2 lg:px-0">
|
||||
<div class="bg-muted relative hidden h-full flex-col p-10 text-white lg:flex dark:border-e dark:border-neutral-800">
|
||||
<div class="absolute inset-0 bg-neutral-900"></div>
|
||||
<a href="{{ route('home') }}" class="relative z-20 flex items-center text-lg font-medium" wire:navigate>
|
||||
<span class="flex h-10 w-10 items-center justify-center rounded-md">
|
||||
<x-app-logo-icon class="me-2 h-7 fill-current text-white" />
|
||||
</span>
|
||||
{{ config('app.name', 'Laravel') }}
|
||||
</a>
|
||||
|
||||
@php
|
||||
[$message, $author] = str(Illuminate\Foundation\Inspiring::quotes()->random())->explode('-');
|
||||
@endphp
|
||||
|
||||
<div class="relative z-20 mt-auto">
|
||||
<blockquote class="space-y-2">
|
||||
<flux:heading size="lg">“{{ trim($message) }}”</flux:heading>
|
||||
<footer><flux:heading>{{ trim($author) }}</flux:heading></footer>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:p-8">
|
||||
<div class="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
|
||||
<a href="{{ route('home') }}" class="z-20 flex flex-col items-center gap-2 font-medium lg:hidden" wire:navigate>
|
||||
<span class="flex h-9 w-9 items-center justify-center rounded-md">
|
||||
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
|
||||
</span>
|
||||
|
||||
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
|
||||
</a>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@fluxScripts
|
||||
</body>
|
||||
</html>
|
||||
12
resources/views/components/placeholder-pattern.blade.php
Normal file
12
resources/views/components/placeholder-pattern.blade.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
@props([
|
||||
'id' => uniqid(),
|
||||
])
|
||||
|
||||
<svg {{ $attributes }} fill="none">
|
||||
<defs>
|
||||
<pattern id="pattern-{{ $id }}" x="0" y="0" width="8" height="8" patternUnits="userSpaceOnUse">
|
||||
<path d="M-1 5L5 -1M3 9L8.5 3.5" stroke-width="0.5"></path>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect stroke="none" fill="url(#pattern-{{ $id }})" width="100%" height="100%"></rect>
|
||||
</svg>
|
||||
20
resources/views/components/settings/layout.blade.php
Normal file
20
resources/views/components/settings/layout.blade.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<div class="flex items-start max-md:flex-col">
|
||||
<div class="me-10 w-full pb-4 md:w-[220px]">
|
||||
<flux:navlist>
|
||||
<flux:navlist.item :href="route('settings.profile')" wire:navigate>{{ __('Profile') }}</flux:navlist.item>
|
||||
<flux:navlist.item :href="route('settings.password')" wire:navigate>{{ __('Password') }}</flux:navlist.item>
|
||||
<flux:navlist.item :href="route('settings.appearance')" wire:navigate>{{ __('Appearance') }}</flux:navlist.item>
|
||||
</flux:navlist>
|
||||
</div>
|
||||
|
||||
<flux:separator class="md:hidden" />
|
||||
|
||||
<div class="flex-1 self-stretch max-md:pt-6">
|
||||
<flux:heading>{{ $heading ?? '' }}</flux:heading>
|
||||
<flux:subheading>{{ $subheading ?? '' }}</flux:subheading>
|
||||
|
||||
<div class="mt-5 w-full max-w-lg">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
51
resources/views/flux/navlist/group.blade.php
Normal file
51
resources/views/flux/navlist/group.blade.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
@props([
|
||||
'expandable' => false,
|
||||
'expanded' => true,
|
||||
'heading' => null,
|
||||
])
|
||||
|
||||
<?php if ($expandable && $heading): ?>
|
||||
|
||||
<ui-disclosure
|
||||
{{ $attributes->class('group/disclosure') }}
|
||||
@if ($expanded === true) open @endif
|
||||
data-flux-navlist-group
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="group/disclosure-button mb-[2px] flex h-10 w-full items-center rounded-lg text-zinc-500 hover:bg-zinc-800/5 hover:text-zinc-800 lg:h-8 dark:text-white/80 dark:hover:bg-white/[7%] dark:hover:text-white"
|
||||
>
|
||||
<div class="ps-3 pe-4">
|
||||
<flux:icon.chevron-down class="hidden size-3! group-data-open/disclosure-button:block" />
|
||||
<flux:icon.chevron-right class="block size-3! group-data-open/disclosure-button:hidden" />
|
||||
</div>
|
||||
|
||||
<span class="text-sm font-medium leading-none">{{ $heading }}</span>
|
||||
</button>
|
||||
|
||||
<div class="relative hidden space-y-[2px] ps-7 data-open:block" @if ($expanded === true) data-open @endif>
|
||||
<div class="absolute inset-y-[3px] start-0 ms-4 w-px bg-zinc-200 dark:bg-white/30"></div>
|
||||
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</ui-disclosure>
|
||||
|
||||
<?php elseif ($heading): ?>
|
||||
|
||||
<div {{ $attributes->class('block space-y-[2px]') }}>
|
||||
<div class="px-1 py-2">
|
||||
<div class="text-xs leading-none text-zinc-400">{{ $heading }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div {{ $attributes->class('block space-y-[2px]') }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
149
resources/views/layouts/admin-master.blade.php
Normal file
149
resources/views/layouts/admin-master.blade.php
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>@yield('title', $domainName ?? 'Admin - ' . config('app.name'))</title>
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" href="{{ asset('img/favicons/admin-favicon.ico') }}">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600,700" rel="stylesheet" />
|
||||
|
||||
<!-- Styles -->
|
||||
@vite(['resources/css/admin.css', 'resources/js/app.js'])
|
||||
|
||||
<!-- Additional Styles -->
|
||||
@stack('styles')
|
||||
</head>
|
||||
<body class="antialiased bg-gray-50 dark:bg-gray-900">
|
||||
<div class="min-h-screen flex">
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="w-64 bg-white dark:bg-gray-800 shadow-md hidden md:block">
|
||||
<div class="p-6">
|
||||
<a href="{{ route('admin.home') }}" class="text-xl font-bold text-gray-900 dark:text-white">
|
||||
{{ $domainName ?? config('app.name') . ' Admin' }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<nav class="mt-10 px-6">
|
||||
<a href="{{ route('admin.dashboard') }}" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-100 dark:hover:bg-gray-700 {{ request()->routeIs('admin.dashboard') ? 'bg-gray-100 dark:bg-gray-700' : '' }}">
|
||||
Dashboard
|
||||
</a>
|
||||
<a href="{{ route('admin.settings.profile') }}" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-100 dark:hover:bg-gray-700 {{ request()->routeIs('admin.settings.profile') ? 'bg-gray-100 dark:bg-gray-700' : '' }}">
|
||||
Profil
|
||||
</a>
|
||||
<!-- Weitere Navigationspunkte hier -->
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<div class="flex-1 flex flex-col">
|
||||
<!-- Top Navigation -->
|
||||
<header class="bg-white dark:bg-gray-800 shadow-sm">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between h-16">
|
||||
<div class="flex items-center md:hidden">
|
||||
<!-- Mobile menu button -->
|
||||
<button type="button" class="text-gray-500 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" id="mobile-menu-button">
|
||||
<span class="sr-only">Menu öffnen</span>
|
||||
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
@if(app()->environment('local'))
|
||||
<!-- Domain-Informationsanzeige (nur in local) -->
|
||||
<div class="mr-4 text-xs px-2 py-1 rounded bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200">
|
||||
{{ Request::getHost() }}
|
||||
@if(config('domains.dev_settings.simulate_domain'))
|
||||
<span class="inline-flex items-center ml-1 px-1.5 py-0.5 rounded-full text-xs bg-yellow-100 text-yellow-800">
|
||||
Simuliert
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- User Dropdown -->
|
||||
<div class="ml-3 relative">
|
||||
<div>
|
||||
<button type="button" class="flex text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" id="user-menu-button">
|
||||
<span class="sr-only">Benutzermenü öffnen</span>
|
||||
<div class="h-8 w-8 rounded-full bg-gray-200 flex items-center justify-center">
|
||||
<span class="text-xs font-medium">{{ Auth::user()->name[0] ?? 'U' }}</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Dropdown menu -->
|
||||
<div class="hidden origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white dark:bg-gray-700 ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" id="user-menu">
|
||||
<a href="{{ route('admin.settings.profile') }}" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600" role="menuitem">Profil</a>
|
||||
<a href="{{ route('admin.settings.appearance') }}" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600" role="menuitem">Einstellungen</a>
|
||||
<form method="POST" action="{{ route('logout') }}">
|
||||
@csrf
|
||||
<button type="submit" class="block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600" role="menuitem">Abmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Mobile menu (off-canvas) -->
|
||||
<div class="md:hidden hidden" id="mobile-menu">
|
||||
<div class="px-2 pt-2 pb-3 space-y-1 bg-white dark:bg-gray-800 shadow-lg">
|
||||
<a href="{{ route('admin.dashboard') }}" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Dashboard</a>
|
||||
<a href="{{ route('admin.settings.profile') }}" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Profil</a>
|
||||
<!-- Weitere mobile Navigationspunkte hier -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main class="flex-1 py-10">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
@yield('content')
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script>
|
||||
// Toggle user dropdown
|
||||
const userMenuButton = document.getElementById('user-menu-button');
|
||||
const userMenu = document.getElementById('user-menu');
|
||||
|
||||
if (userMenuButton && userMenu) {
|
||||
userMenuButton.addEventListener('click', function() {
|
||||
userMenu.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
// Close the dropdown when clicked outside
|
||||
document.addEventListener('click', function(event) {
|
||||
if (!userMenuButton.contains(event.target) && !userMenu.contains(event.target)) {
|
||||
userMenu.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Mobile menu toggle
|
||||
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
||||
const mobileMenu = document.getElementById('mobile-menu');
|
||||
|
||||
if (mobileMenuButton && mobileMenu) {
|
||||
mobileMenuButton.addEventListener('click', function() {
|
||||
mobileMenu.classList.toggle('hidden');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Additional Scripts -->
|
||||
@stack('scripts')
|
||||
</body>
|
||||
</html>
|
||||
165
resources/views/layouts/web-master.blade.php
Normal file
165
resources/views/layouts/web-master.blade.php
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>@yield('title', $domainName ?? config('app.name', 'Laravel'))</title>
|
||||
|
||||
<!-- Domain-spezifisches Favicon -->
|
||||
<link rel="icon" href="{{ asset('img/favicons/' . $theme . '-favicon.ico') }}">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
|
||||
@if($theme === 'landing1')
|
||||
<link href="https://fonts.bunny.net/css?family=inter:400,500,600,700" rel="stylesheet" />
|
||||
@elseif($theme === 'landing2')
|
||||
<link href="https://fonts.bunny.net/css?family=poppins:400,500,600,700" rel="stylesheet" />
|
||||
@else
|
||||
<link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600,700" rel="stylesheet" />
|
||||
@endif
|
||||
|
||||
<!-- Dynamisches CSS basierend auf Domain-Konfiguration -->
|
||||
@if($theme === 'landing1')
|
||||
@vite('resources/css/web/theme-landing1.css')
|
||||
@elseif($theme === 'landing2')
|
||||
@vite('resources/css/web/theme-landing2.css')
|
||||
@else
|
||||
@vite('resources/css/web/theme-main.css')
|
||||
@endif
|
||||
|
||||
@vite('resources/js/app.js')
|
||||
|
||||
<!-- Additional Styles -->
|
||||
@stack('styles')
|
||||
|
||||
<!-- Domain-spezifische Inline-Styles -->
|
||||
{{-- @if(isset($domainConfig['color_scheme']))
|
||||
<style>
|
||||
:root {
|
||||
@if(isset($domainConfig['color_scheme']['primary']))
|
||||
--primary-color: {{ $domainConfig['color_scheme']['primary'] }};
|
||||
@endif
|
||||
@if(isset($domainConfig['color_scheme']['accent']))
|
||||
--accent-color: {{ $domainConfig['color_scheme']['accent'] }};
|
||||
@endif
|
||||
}
|
||||
</style>
|
||||
@endif --}}
|
||||
</head>
|
||||
<body class="antialiased">
|
||||
<div class="min-h-screen bg-gray-100 dark:bg-gray-900 flex flex-col">
|
||||
<!-- Header -->
|
||||
<header class="bg-white dark:bg-gray-800 shadow">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between h-16">
|
||||
<div class="flex items-center">
|
||||
<a href="{{ url('/') }}" class="text-xl font-bold text-primary-800 dark:text-primary-200">
|
||||
{{ $domainName ?? config('app.name', 'Laravel') }}
|
||||
</a>
|
||||
|
||||
<nav class="ml-10 space-x-4">
|
||||
<a href="{{ url('/') }}" class="text-primary-600 hover:text-primary-900 dark:text-primary-300 dark:hover:text-primary-100">Home</a>
|
||||
<a href="{{ url('/welcome') }}" class="text-primary-600 hover:text-primary-900 dark:text-primary-300 dark:hover:text-primary-100">Welcome</a>
|
||||
<a href="https://portal.b2in.test" class="text-primary-600 hover:text-primary-900 dark:text-primary-300 dark:hover:text-primary-100">Portal</a>
|
||||
|
||||
<!-- Weitere Navigationspunkte hier -->
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<!-- Theme-Switcher -->
|
||||
<button id="theme-toggle" type="button" class="text-accent-600 dark:text-accent-400 hover:text-accent-800 dark:hover:text-accent-200 rounded-lg text-sm p-2.5">
|
||||
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path></svg>
|
||||
<svg id="theme-toggle-light-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>
|
||||
</button>
|
||||
|
||||
@if(app()->environment('local'))
|
||||
<!-- Domain-Simulationsanzeige (nur in local) -->
|
||||
<div class="ml-4 text-xs px-2 py-1 rounded bg-accent-100 text-accent-800 dark:bg-accent-800 dark:text-accent-100">
|
||||
{{ $theme }} / {{ Request::getHost() }}
|
||||
@if(config('domains.dev_settings.simulate_domain'))
|
||||
<span class="inline-flex items-center ml-1 px-1.5 py-0.5 rounded-full text-xs bg-yellow-100 text-yellow-800">
|
||||
Simuliert
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main class="flex-grow py-10">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
@yield('content')
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-white dark:bg-gray-800 shadow py-6">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<p class="text-gray-500 dark:text-gray-400">
|
||||
© {{ date('Y') }} {{ $domainName ?? config('app.name', 'Laravel') }}. Alle Rechte vorbehalten.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<!-- Footer-Links -->
|
||||
<div class="flex space-x-4">
|
||||
<a href="#" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300">Impressum</a>
|
||||
<a href="#" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300">Datenschutz</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Dark Mode Toggle Script -->
|
||||
<script>
|
||||
const themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
||||
const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
||||
|
||||
// Set initial icon state
|
||||
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
themeToggleLightIcon.classList.remove('hidden');
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
themeToggleDarkIcon.classList.remove('hidden');
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
|
||||
// Toggle theme
|
||||
document.getElementById('theme-toggle').addEventListener('click', function() {
|
||||
themeToggleDarkIcon.classList.toggle('hidden');
|
||||
themeToggleLightIcon.classList.toggle('hidden');
|
||||
|
||||
if (localStorage.getItem('color-theme')) {
|
||||
if (localStorage.getItem('color-theme') === 'light') {
|
||||
document.documentElement.classList.add('dark');
|
||||
localStorage.setItem('color-theme', 'dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
localStorage.setItem('color-theme', 'light');
|
||||
}
|
||||
} else {
|
||||
if (document.documentElement.classList.contains('dark')) {
|
||||
document.documentElement.classList.remove('dark');
|
||||
localStorage.setItem('color-theme', 'light');
|
||||
} else {
|
||||
document.documentElement.classList.add('dark');
|
||||
localStorage.setItem('color-theme', 'dark');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Additional Scripts -->
|
||||
@stack('scripts')
|
||||
</body>
|
||||
</html>
|
||||
57
resources/views/livewire/auth/confirm-password.blade.php
Normal file
57
resources/views/livewire/auth/confirm-password.blade.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
public string $password = '';
|
||||
|
||||
/**
|
||||
* Confirm the current user's password.
|
||||
*/
|
||||
public function confirmPassword(): void
|
||||
{
|
||||
$this->validate([
|
||||
'password' => ['required', 'string'],
|
||||
]);
|
||||
|
||||
if (! Auth::guard('web')->validate([
|
||||
'email' => Auth::user()->email,
|
||||
'password' => $this->password,
|
||||
])) {
|
||||
throw ValidationException::withMessages([
|
||||
'password' => __('auth.password'),
|
||||
]);
|
||||
}
|
||||
|
||||
session(['auth.password_confirmed_at' => time()]);
|
||||
|
||||
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header
|
||||
:title="__('Confirm password')"
|
||||
:description="__('This is a secure area of the application. Please confirm your password before continuing.')"
|
||||
/>
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
|
||||
<form wire:submit="confirmPassword" class="flex flex-col gap-6">
|
||||
<!-- Password -->
|
||||
<flux:input
|
||||
wire:model="password"
|
||||
:label="__('Password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Password')"
|
||||
/>
|
||||
|
||||
<flux:button variant="primary" type="submit" class="w-full">{{ __('Confirm') }}</flux:button>
|
||||
</form>
|
||||
</div>
|
||||
49
resources/views/livewire/auth/forgot-password.blade.php
Normal file
49
resources/views/livewire/auth/forgot-password.blade.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
public string $email = '';
|
||||
|
||||
/**
|
||||
* Send a password reset link to the provided email address.
|
||||
*/
|
||||
public function sendPasswordResetLink(): void
|
||||
{
|
||||
$this->validate([
|
||||
'email' => ['required', 'string', 'email'],
|
||||
]);
|
||||
|
||||
Password::sendResetLink($this->only('email'));
|
||||
|
||||
session()->flash('status', __('A reset link will be sent if the account exists.'));
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Forgot password')" :description="__('Enter your email to receive a password reset link')" />
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
|
||||
<form wire:submit="sendPasswordResetLink" class="flex flex-col gap-6">
|
||||
<!-- Email Address -->
|
||||
<flux:input
|
||||
wire:model="email"
|
||||
:label="__('Email Address')"
|
||||
type="email"
|
||||
required
|
||||
autofocus
|
||||
placeholder="email@example.com"
|
||||
/>
|
||||
|
||||
<flux:button variant="primary" type="submit" class="w-full">{{ __('Email password reset link') }}</flux:button>
|
||||
</form>
|
||||
|
||||
<div class="space-x-1 text-center text-sm text-zinc-400">
|
||||
{{ __('Or, return to') }}
|
||||
<flux:link :href="route('login')" wire:navigate>{{ __('log in') }}</flux:link>
|
||||
</div>
|
||||
</div>
|
||||
153
resources/views/livewire/auth/login-simple.blade.php
Normal file
153
resources/views/livewire/auth/login-simple.blade.php
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Auth\Events\Lockout;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
#[Validate('required|string|email')]
|
||||
public string $email = '';
|
||||
|
||||
#[Validate('required|string')]
|
||||
public string $password = '';
|
||||
|
||||
public bool $remember = false;
|
||||
|
||||
/**
|
||||
* Handle an incoming authentication request.
|
||||
*/
|
||||
public function login(): void
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$this->ensureIsNotRateLimited();
|
||||
|
||||
if (! Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => __('auth.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
RateLimiter::clear($this->throttleKey());
|
||||
Session::regenerate();
|
||||
|
||||
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the authentication request is not rate limited.
|
||||
*/
|
||||
protected function ensureIsNotRateLimited(): void
|
||||
{
|
||||
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event(new Lockout(request()));
|
||||
|
||||
$seconds = RateLimiter::availableIn($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => __('auth.throttle', [
|
||||
'seconds' => $seconds,
|
||||
'minutes' => ceil($seconds / 60),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authentication rate limiting throttle key.
|
||||
*/
|
||||
protected function throttleKey(): string
|
||||
{
|
||||
return Str::transliterate(Str::lower($this->email).'|'.request()->ip());
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6 p-8 bg-white rounded-lg shadow-lg">
|
||||
<div class="text-center">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Log in to your account</h1>
|
||||
<p class="text-gray-600 mt-2">Enter your email and password below to log in</p>
|
||||
</div>
|
||||
|
||||
<!-- Session Status -->
|
||||
@if (session('status'))
|
||||
<div class="text-center text-sm text-green-600">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form wire:submit="login" class="flex flex-col gap-6">
|
||||
<!-- Email Address -->
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium text-gray-700">Email address</label>
|
||||
<input
|
||||
wire:model="email"
|
||||
id="email"
|
||||
type="email"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="email"
|
||||
placeholder="email@example.com"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
||||
/>
|
||||
@error('email')
|
||||
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="relative">
|
||||
<label for="password" class="block text-sm font-medium text-gray-700">Password</label>
|
||||
<input
|
||||
wire:model="password"
|
||||
id="password"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
placeholder="Password"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
||||
/>
|
||||
@error('password')
|
||||
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
|
||||
@enderror
|
||||
|
||||
@if (Route::has('password.request'))
|
||||
<a href="{{ route('password.request') }}" class="absolute right-0 top-0 text-sm text-blue-600 hover:text-blue-500">
|
||||
Forgot your password?
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Remember Me -->
|
||||
<div class="flex items-center">
|
||||
<input
|
||||
wire:model="remember"
|
||||
id="remember"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||
/>
|
||||
<label for="remember" class="ml-2 block text-sm text-gray-900">Remember me</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
|
||||
Log in
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@if (Route::has('register'))
|
||||
<div class="text-center text-sm text-gray-600">
|
||||
Don't have an account?
|
||||
<a href="{{ route('register') }}" class="text-blue-600 hover:text-blue-500">Sign up</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
126
resources/views/livewire/auth/login.blade.php
Normal file
126
resources/views/livewire/auth/login.blade.php
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Auth\Events\Lockout;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
#[Validate('required|string|email')]
|
||||
public string $email = '';
|
||||
|
||||
#[Validate('required|string')]
|
||||
public string $password = '';
|
||||
|
||||
public bool $remember = false;
|
||||
|
||||
/**
|
||||
* Handle an incoming authentication request.
|
||||
*/
|
||||
public function login(): void
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$this->ensureIsNotRateLimited();
|
||||
|
||||
if (! Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => __('auth.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
RateLimiter::clear($this->throttleKey());
|
||||
Session::regenerate();
|
||||
|
||||
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the authentication request is not rate limited.
|
||||
*/
|
||||
protected function ensureIsNotRateLimited(): void
|
||||
{
|
||||
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event(new Lockout(request()));
|
||||
|
||||
$seconds = RateLimiter::availableIn($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => __('auth.throttle', [
|
||||
'seconds' => $seconds,
|
||||
'minutes' => ceil($seconds / 60),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authentication rate limiting throttle key.
|
||||
*/
|
||||
protected function throttleKey(): string
|
||||
{
|
||||
return Str::transliterate(Str::lower($this->email).'|'.request()->ip());
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Log in to your account')" :description="__('Enter your email and password below to log in')" />
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
|
||||
<form wire:submit="login" class="flex flex-col gap-6">
|
||||
<!-- Email Address -->
|
||||
<flux:input
|
||||
wire:model="email"
|
||||
:label="__('Email address')"
|
||||
type="email"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="email"
|
||||
placeholder="email@example.com"
|
||||
/>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="relative">
|
||||
<flux:input
|
||||
wire:model="password"
|
||||
:label="__('Password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
:placeholder="__('Password')"
|
||||
/>
|
||||
|
||||
@if (Route::has('password.request'))
|
||||
<flux:link class="absolute right-0 top-0 text-sm" :href="route('password.request')" wire:navigate>
|
||||
{{ __('Forgot your password?') }}
|
||||
</flux:link>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Remember Me -->
|
||||
<flux:checkbox wire:model="remember" :label="__('Remember me')" />
|
||||
|
||||
<div class="flex items-center justify-end">
|
||||
<flux:button variant="primary" type="submit" class="w-full">{{ __('Log in') }}</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if (Route::has('register'))
|
||||
<div class="space-x-1 text-center text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ __('Don\'t have an account?') }}
|
||||
<flux:link :href="route('register')" wire:navigate>{{ __('Sign up') }}</flux:link>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
97
resources/views/livewire/auth/register.blade.php
Normal file
97
resources/views/livewire/auth/register.blade.php
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
public string $name = '';
|
||||
public string $email = '';
|
||||
public string $password = '';
|
||||
public string $password_confirmation = '';
|
||||
|
||||
/**
|
||||
* Handle an incoming registration request.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$validated = $this->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:' . User::class],
|
||||
'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
$validated['password'] = Hash::make($validated['password']);
|
||||
|
||||
event(new Registered(($user = User::create($validated))));
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
$this->redirectIntended(route('dashboard', absolute: false), navigate: true);
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Create an account')" :description="__('Enter your details below to create your account')" />
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
|
||||
<form wire:submit="register" class="flex flex-col gap-6">
|
||||
<!-- Name -->
|
||||
<flux:input
|
||||
wire:model="name"
|
||||
:label="__('Name')"
|
||||
type="text"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="name"
|
||||
:placeholder="__('Full name')"
|
||||
/>
|
||||
|
||||
<!-- Email Address -->
|
||||
<flux:input
|
||||
wire:model="email"
|
||||
:label="__('Email address')"
|
||||
type="email"
|
||||
required
|
||||
autocomplete="email"
|
||||
placeholder="email@example.com"
|
||||
/>
|
||||
|
||||
<!-- Password -->
|
||||
<flux:input
|
||||
wire:model="password"
|
||||
:label="__('Password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Password')"
|
||||
/>
|
||||
|
||||
<!-- Confirm Password -->
|
||||
<flux:input
|
||||
wire:model="password_confirmation"
|
||||
:label="__('Confirm password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Confirm password')"
|
||||
/>
|
||||
|
||||
<div class="flex items-center justify-end">
|
||||
<flux:button type="submit" variant="primary" class="w-full">
|
||||
{{ __('Create account') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="space-x-1 text-center text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ __('Already have an account?') }}
|
||||
<flux:link :href="route('login')" wire:navigate>{{ __('Log in') }}</flux:link>
|
||||
</div>
|
||||
</div>
|
||||
113
resources/views/livewire/auth/reset-password.blade.php
Normal file
113
resources/views/livewire/auth/reset-password.blade.php
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rules;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
#[Locked]
|
||||
public string $token = '';
|
||||
public string $email = '';
|
||||
public string $password = '';
|
||||
public string $password_confirmation = '';
|
||||
|
||||
/**
|
||||
* Mount the component.
|
||||
*/
|
||||
public function mount(string $token): void
|
||||
{
|
||||
$this->token = $token;
|
||||
|
||||
$this->email = request()->string('email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the password for the given user.
|
||||
*/
|
||||
public function resetPassword(): void
|
||||
{
|
||||
$this->validate([
|
||||
'token' => ['required'],
|
||||
'email' => ['required', 'string', 'email'],
|
||||
'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
// Here we will attempt to reset the user's password. If it is successful we
|
||||
// will update the password on an actual user model and persist it to the
|
||||
// database. Otherwise we will parse the error and return the response.
|
||||
$status = Password::reset(
|
||||
$this->only('email', 'password', 'password_confirmation', 'token'),
|
||||
function ($user) {
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($this->password),
|
||||
'remember_token' => Str::random(60),
|
||||
])->save();
|
||||
|
||||
event(new PasswordReset($user));
|
||||
}
|
||||
);
|
||||
|
||||
// If the password was successfully reset, we will redirect the user back to
|
||||
// the application's home authenticated view. If there is an error we can
|
||||
// redirect them back to where they came from with their error message.
|
||||
if ($status != Password::PasswordReset) {
|
||||
$this->addError('email', __($status));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Session::flash('status', __($status));
|
||||
|
||||
$this->redirectRoute('login', navigate: true);
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<x-auth-header :title="__('Reset password')" :description="__('Please enter your new password below')" />
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="text-center" :status="session('status')" />
|
||||
|
||||
<form wire:submit="resetPassword" class="flex flex-col gap-6">
|
||||
<!-- Email Address -->
|
||||
<flux:input
|
||||
wire:model="email"
|
||||
:label="__('Email')"
|
||||
type="email"
|
||||
required
|
||||
autocomplete="email"
|
||||
/>
|
||||
|
||||
<!-- Password -->
|
||||
<flux:input
|
||||
wire:model="password"
|
||||
:label="__('Password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Password')"
|
||||
/>
|
||||
|
||||
<!-- Confirm Password -->
|
||||
<flux:input
|
||||
wire:model="password_confirmation"
|
||||
:label="__('Confirm password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Confirm password')"
|
||||
/>
|
||||
|
||||
<div class="flex items-center justify-end">
|
||||
<flux:button type="submit" variant="primary" class="w-full">
|
||||
{{ __('Reset password') }}
|
||||
</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
57
resources/views/livewire/auth/verify-email.blade.php
Normal file
57
resources/views/livewire/auth/verify-email.blade.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
use App\Livewire\Actions\Logout;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('components.layouts.auth')] class extends Component {
|
||||
/**
|
||||
* Send an email verification notification to the user.
|
||||
*/
|
||||
public function sendVerification(): void
|
||||
{
|
||||
if (Auth::user()->hasVerifiedEmail()) {
|
||||
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Auth::user()->sendEmailVerificationNotification();
|
||||
|
||||
Session::flash('status', 'verification-link-sent');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the current user out of the application.
|
||||
*/
|
||||
public function logout(Logout $logout): void
|
||||
{
|
||||
$logout();
|
||||
|
||||
$this->redirect('/', navigate: true);
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="mt-4 flex flex-col gap-6">
|
||||
<flux:text class="text-center">
|
||||
{{ __('Please verify your email address by clicking on the link we just emailed to you.') }}
|
||||
</flux:text>
|
||||
|
||||
@if (session('status') == 'verification-link-sent')
|
||||
<flux:text class="text-center font-medium !dark:text-green-400 !text-green-600">
|
||||
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
|
||||
</flux:text>
|
||||
@endif
|
||||
|
||||
<div class="flex flex-col items-center justify-between space-y-3">
|
||||
<flux:button wire:click="sendVerification" variant="primary" class="w-full">
|
||||
{{ __('Resend verification email') }}
|
||||
</flux:button>
|
||||
|
||||
<flux:link class="text-sm cursor-pointer" wire:click="logout">
|
||||
{{ __('Log out') }}
|
||||
</flux:link>
|
||||
</div>
|
||||
</div>
|
||||
11
resources/views/livewire/notifications.blade.php
Normal file
11
resources/views/livewire/notifications.blade.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
public bool $notifications = false;
|
||||
}; ?>
|
||||
|
||||
<div>
|
||||
<flux:switch wire:model.live="notifications" label="Enable notifications" />
|
||||
</div>
|
||||
189
resources/views/livewire/portal/users.blade.php
Normal file
189
resources/views/livewire/portal/users.blade.php
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithPagination; // Wichtig für Paginierung
|
||||
|
||||
|
||||
new class extends Component {
|
||||
use WithPagination;
|
||||
|
||||
// Optional: Such- und Filter-Properties
|
||||
public string $search = '';
|
||||
public string $statusFilter = '';
|
||||
public string $roleFilter = '';
|
||||
|
||||
// Optional: Sortierung
|
||||
public string $sortField = 'name';
|
||||
public string $sortDirection = 'asc';
|
||||
|
||||
|
||||
/**
|
||||
* Mount the component.
|
||||
*/
|
||||
public function mount(): void
|
||||
{
|
||||
// Standardwerte für Sortierung setzen
|
||||
$this->sortField = 'name';
|
||||
$this->sortDirection = 'asc';
|
||||
}
|
||||
|
||||
public function sortBy(string $field): void
|
||||
{
|
||||
if ($this->sortField === $field) {
|
||||
$this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
|
||||
} else {
|
||||
$this->sortDirection = 'asc';
|
||||
}
|
||||
$this->sortField = $field;
|
||||
}
|
||||
|
||||
// Die Hauptmethode, um Daten zu laden
|
||||
public function users()
|
||||
{
|
||||
return User::query()
|
||||
->when($this->search, fn($query, $search) =>
|
||||
$query->where('name', 'like', '%' . $search . '%')
|
||||
->orWhere('email', 'like', '%' . $search . '%')
|
||||
)
|
||||
->when($this->statusFilter, fn($query, $status) =>
|
||||
$query->where('status', $status)
|
||||
)
|
||||
->when($this->roleFilter, fn($query, $role) =>
|
||||
$query->where('role', $role) // oder 'role_id' wenn du IDs verwendest
|
||||
)
|
||||
->orderBy($this->sortField, $this->sortDirection)
|
||||
->paginate(10); // 10 Einträge pro Seite
|
||||
}
|
||||
|
||||
// Optional: Lifecycle hook für das Zurücksetzen der Paginierung bei Suche/Filterung
|
||||
public function updatedSearch() { $this->resetPage(); }
|
||||
public function updatedStatusFilter() { $this->resetPage(); }
|
||||
public function updatedRoleFilter() { $this->resetPage(); }
|
||||
|
||||
// Wird für die Paginierung mit Tailwind benötigt (Standard in Livewire 3)
|
||||
// Wenn FluxUI Bootstrap-basierte Paginierung braucht, musst du das anpassen
|
||||
// public function paginationView()
|
||||
// {
|
||||
// return 'vendor.livewire.tailwind'; // oder 'livewire::bootstrap'
|
||||
// }
|
||||
|
||||
// Wenn du mit Relationen arbeitest (z.B. user->role->name)
|
||||
// public function with(): array
|
||||
// {
|
||||
// return [
|
||||
// 'users' => User::with(['role', 'group']) // Eager loading
|
||||
// // ... deine Query-Logik von oben ...
|
||||
// ->paginate(10),
|
||||
// ];
|
||||
// }
|
||||
}; ?>
|
||||
|
||||
<div>
|
||||
{{-- Filter und Suchleiste (Beispiel, FluxUI Klassen anpassen) --}}
|
||||
<div class="mb-4 grid grid-cols-1 md:grid-cols-3 gap-4 p-4 bg-gray-100 rounded">
|
||||
<div>
|
||||
<label for="search" class="block text-sm font-medium text-gray-700">Suche</label>
|
||||
<input wire:model.live.debounce.300ms="search" id="search" type="text" placeholder="Name oder E-Mail..."
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
|
||||
</div>
|
||||
<div>
|
||||
<label for="statusFilter" class="block text-sm font-medium text-gray-700">Status</label>
|
||||
<select wire:model.live="statusFilter" id="statusFilter"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
|
||||
<option value="">Alle</option>
|
||||
<option value="active">Aktiv</option>
|
||||
<option value="inactive">Inaktiv</option>
|
||||
<option value="pending">Ausstehend</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="roleFilter" class="block text-sm font-medium text-gray-700">Rolle</label>
|
||||
<input wire:model.live.debounce.300ms="roleFilter" id="roleFilter" type="text" placeholder="Rolle..."
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Tabelle (FluxUI Klassen anpassen!) --}}
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200 shadow">
|
||||
<thead class="bg-gray-50"> {{-- FluxUI Klasse für Thead --}}
|
||||
<tr>
|
||||
<th scope="col" wire:click="sortBy('name')"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
|
||||
Name @if($sortField === 'name')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
|
||||
</th>
|
||||
<th scope="col" wire:click="sortBy('email')"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
|
||||
E-Mail @if($sortField === 'email')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
|
||||
</th>
|
||||
<th scope="col" wire:click="sortBy('status')"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
|
||||
Status @if($sortField === 'status')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
|
||||
</th>
|
||||
<th scope="col" wire:click="sortBy('role')"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
|
||||
Rolle @if($sortField === 'role')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Gruppe
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">
|
||||
Rechte
|
||||
</th>
|
||||
<th scope="col" class="relative px-6 py-3">
|
||||
<span class="sr-only">Aktionen</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200"> {{-- FluxUI Klasse für Tbody --}}
|
||||
@forelse ($this->users() as $user)
|
||||
<tr wire:key="{{ $user->id }}">
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ $user->name }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $user->email }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm">
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
|
||||
{{ $user->status === 'active' ? 'bg-green-100 text-green-800' : ($user->status === 'inactive' ? 'bg-red-100 text-red-800' : 'bg-yellow-100 text-yellow-800') }}">
|
||||
{{ ucfirst($user->status) }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
{{ $user->role }} {{-- Oder $user->role->name, wenn es eine Relation ist --}}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
{{ $user->group }} {{-- Oder $user->group->name --}}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
{{-- Darstellung der Rechte. Wenn es eine Many-to-Many Relation ist: --}}
|
||||
{{-- @foreach($user->permissions as $permission)
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800">
|
||||
{{ $permission->name }}
|
||||
</span>
|
||||
@endforeach --}}
|
||||
{{-- Oder wenn es ein JSON-Feld ist, musst du es parsen und anzeigen --}}
|
||||
Einfache Rechte-Anzeige (Todo)
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<a href="#" class="text-indigo-600 hover:text-indigo-900">Bearbeiten</a> {{-- FluxUI Button-Klassen --}}
|
||||
<button wire:click="$dispatch('openModal', { component: 'admin.delete-user-modal', arguments: { userId: {{ $user->id }} }})"
|
||||
class="text-red-600 hover:text-red-900 ml-2">Löschen</button> {{-- FluxUI Button-Klassen --}}
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center">
|
||||
Keine Benutzer gefunden.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
{{ $this->users()->links() }} {{-- Stellt sicher, dass die Paginierungs-Views für dein UI-Kit konfiguriert sind --}}
|
||||
</div>
|
||||
</div>
|
||||
144
resources/views/livewire/portal/users/table.blade.php
Normal file
144
resources/views/livewire/portal/users/table.blade.php
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Livewire\Volt\Component;
|
||||
use Livewire\WithPagination; // Wichtig für Paginierung
|
||||
|
||||
|
||||
new class extends Component {
|
||||
use WithPagination;
|
||||
|
||||
// Optional: Such- und Filter-Properties
|
||||
public string $search = '';
|
||||
public string $statusFilter = '';
|
||||
public string $roleFilter = '';
|
||||
|
||||
// Optional: Sortierung
|
||||
public $sortBy = 'name';
|
||||
public $sortDirection = 'asc';
|
||||
|
||||
|
||||
/**
|
||||
* Mount the component.
|
||||
*/
|
||||
public function mount(): void
|
||||
{
|
||||
// Standardwerte für Sortierung setzen
|
||||
$this->sortBy = 'name';
|
||||
$this->sortDirection = 'asc';
|
||||
}
|
||||
|
||||
|
||||
public function sort($column) {
|
||||
if ($this->sortBy === $column) {
|
||||
$this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
|
||||
} else {
|
||||
$this->sortBy = $column;
|
||||
$this->sortDirection = 'asc';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*public function orders()
|
||||
{
|
||||
return \App\Models\Order::query()
|
||||
->tap(fn ($query) => $this->sortBy ? $query->orderBy($this->sortBy, $this->sortDirection) : $query)
|
||||
->paginate(5);
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
// Die Hauptmethode, um Daten zu laden
|
||||
#[\Livewire\Attributes\Computed]
|
||||
public function users()
|
||||
{
|
||||
return User::query()
|
||||
->when($this->search, fn($query, $search) =>
|
||||
$query->where('name', 'like', '%' . $search . '%')
|
||||
->orWhere('email', 'like', '%' . $search . '%')
|
||||
)
|
||||
->when($this->statusFilter, fn($query, $status) =>
|
||||
$query->where('status', $status)
|
||||
)
|
||||
->when($this->roleFilter, fn($query, $role) =>
|
||||
$query->where('role', $role) // oder 'role_id' wenn du IDs verwendest
|
||||
)
|
||||
->orderBy($this->sortBy, $this->sortDirection)
|
||||
->paginate(10); // 10 Einträge pro Seite
|
||||
}
|
||||
|
||||
// Optional: Lifecycle hook für das Zurücksetzen der Paginierung bei Suche/Filterung
|
||||
public function updatedSearch() { $this->resetPage(); }
|
||||
public function updatedStatusFilter() { $this->resetPage(); }
|
||||
public function updatedRoleFilter() { $this->resetPage(); }
|
||||
|
||||
// Wird für die Paginierung mit Tailwind benötigt (Standard in Livewire 3)
|
||||
// Wenn FluxUI Bootstrap-basierte Paginierung braucht, musst du das anpassen
|
||||
// public function paginationView()
|
||||
// {
|
||||
// return 'vendor.livewire.tailwind'; // oder 'livewire::bootstrap'
|
||||
// }
|
||||
|
||||
// Wenn du mit Relationen arbeitest (z.B. user->role->name)
|
||||
// public function with(): array
|
||||
// {
|
||||
// return [
|
||||
// 'users' => User::with(['role', 'group']) // Eager loading
|
||||
// // ... deine Query-Logik von oben ...
|
||||
// ->paginate(10),
|
||||
// ];
|
||||
// }
|
||||
}; ?>
|
||||
<flux:table :paginate="$this->users">
|
||||
<flux:table.columns>
|
||||
<flux:table.column>Customer</flux:table.column>
|
||||
<flux:table.column sortable :sorted="$sortBy === 'date'" :direction="$sortDirection" wire:click="sort('date')">Date</flux:table.column>
|
||||
<flux:table.column sortable :sorted="$sortBy === 'status'" :direction="$sortDirection" wire:click="sort('status')">Status</flux:table.column>
|
||||
<flux:table.column sortable :sorted="$sortBy === 'amount'" :direction="$sortDirection" wire:click="sort('amount')">Amount</flux:table.column>
|
||||
</flux:table.columns>
|
||||
|
||||
<flux:table.rows>
|
||||
@foreach ($this->users as $user)
|
||||
<flux:table.row :key="$user->id">
|
||||
<flux:table.cell class="flex items-center gap-3">
|
||||
<flux:avatar size="xs" src="{{ $user->avatar }}" />
|
||||
|
||||
{{ $user->name }}
|
||||
</flux:table.cell>
|
||||
|
||||
<flux:table.cell class="whitespace-nowrap">{{ $user->email }}</flux:table.cell>
|
||||
|
||||
<flux:table.cell>
|
||||
<flux:badge size="sm" color="lime" inset="top bottom">RTest</flux:badge>
|
||||
</flux:table.cell>
|
||||
|
||||
<flux:table.cell variant="strong">{{ $user->role }}</flux:table.cell>
|
||||
|
||||
<flux:table.cell>
|
||||
<flux:dropdown>
|
||||
<flux:button variant="ghost" size="sm" icon="ellipsis-horizontal" inset="top bottom"></flux:button>
|
||||
<flux:menu>
|
||||
<flux:menu.item icon="plus">New post</flux:menu.item>
|
||||
<flux:menu.separator />
|
||||
<flux:menu.submenu heading="Sort by">
|
||||
<flux:menu.radio.group>
|
||||
<flux:menu.radio checked>Name</flux:menu.radio>
|
||||
<flux:menu.radio>Date</flux:menu.radio>
|
||||
<flux:menu.radio>Popularity</flux:menu.radio>
|
||||
</flux:menu.radio.group>
|
||||
</flux:menu.submenu>
|
||||
<flux:menu.submenu heading="Filter">
|
||||
<flux:menu.checkbox checked>Draft</flux:menu.checkbox>
|
||||
<flux:menu.checkbox checked>Published</flux:menu.checkbox>
|
||||
<flux:menu.checkbox>Archived</flux:menu.checkbox>
|
||||
</flux:menu.submenu>
|
||||
<flux:menu.separator />
|
||||
<flux:menu.item variant="danger" icon="trash">Delete</flux:menu.item>
|
||||
</flux:menu>
|
||||
</flux:dropdown>
|
||||
</flux:table.cell>
|
||||
</flux:table.row>
|
||||
@endforeach
|
||||
</flux:table.rows>
|
||||
</flux:table>
|
||||
|
||||
19
resources/views/livewire/settings/appearance.blade.php
Normal file
19
resources/views/livewire/settings/appearance.blade.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
//
|
||||
}; ?>
|
||||
|
||||
<section class="w-full">
|
||||
@include('partials.settings-heading')
|
||||
|
||||
<x-settings.layout :heading="__('Appearance')" :subheading=" __('Update the appearance settings for your account')">
|
||||
<flux:radio.group x-data variant="segmented" x-model="$flux.appearance">
|
||||
<flux:radio value="light" icon="sun">{{ __('Light') }}</flux:radio>
|
||||
<flux:radio value="dark" icon="moon">{{ __('Dark') }}</flux:radio>
|
||||
<flux:radio value="system" icon="computer-desktop">{{ __('System') }}</flux:radio>
|
||||
</flux:radio.group>
|
||||
</x-settings.layout>
|
||||
</section>
|
||||
58
resources/views/livewire/settings/delete-user-form.blade.php
Normal file
58
resources/views/livewire/settings/delete-user-form.blade.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
use App\Livewire\Actions\Logout;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
public string $password = '';
|
||||
|
||||
/**
|
||||
* Delete the currently authenticated user.
|
||||
*/
|
||||
public function deleteUser(Logout $logout): void
|
||||
{
|
||||
$this->validate([
|
||||
'password' => ['required', 'string', 'current_password'],
|
||||
]);
|
||||
|
||||
tap(Auth::user(), $logout(...))->delete();
|
||||
|
||||
$this->redirect('/', navigate: true);
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<section class="mt-10 space-y-6">
|
||||
<div class="relative mb-5">
|
||||
<flux:heading>{{ __('Delete account') }}</flux:heading>
|
||||
<flux:subheading>{{ __('Delete your account and all of its resources') }}</flux:subheading>
|
||||
</div>
|
||||
|
||||
<flux:modal.trigger name="confirm-user-deletion">
|
||||
<flux:button variant="danger" x-data="" x-on:click.prevent="$dispatch('open-modal', 'confirm-user-deletion')">
|
||||
{{ __('Delete account') }}
|
||||
</flux:button>
|
||||
</flux:modal.trigger>
|
||||
|
||||
<flux:modal name="confirm-user-deletion" :show="$errors->isNotEmpty()" focusable class="max-w-lg">
|
||||
<form wire:submit="deleteUser" class="space-y-6">
|
||||
<div>
|
||||
<flux:heading size="lg">{{ __('Are you sure you want to delete your account?') }}</flux:heading>
|
||||
|
||||
<flux:subheading>
|
||||
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }}
|
||||
</flux:subheading>
|
||||
</div>
|
||||
|
||||
<flux:input wire:model="password" :label="__('Password')" type="password" />
|
||||
|
||||
<div class="flex justify-end space-x-2 rtl:space-x-reverse">
|
||||
<flux:modal.close>
|
||||
<flux:button variant="filled">{{ __('Cancel') }}</flux:button>
|
||||
</flux:modal.close>
|
||||
|
||||
<flux:button variant="danger" type="submit">{{ __('Delete account') }}</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
</flux:modal>
|
||||
</section>
|
||||
78
resources/views/livewire/settings/password.blade.php
Normal file
78
resources/views/livewire/settings/password.blade.php
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
public string $current_password = '';
|
||||
public string $password = '';
|
||||
public string $password_confirmation = '';
|
||||
|
||||
/**
|
||||
* Update the password for the currently authenticated user.
|
||||
*/
|
||||
public function updatePassword(): void
|
||||
{
|
||||
try {
|
||||
$validated = $this->validate([
|
||||
'current_password' => ['required', 'string', 'current_password'],
|
||||
'password' => ['required', 'string', Password::defaults(), 'confirmed'],
|
||||
]);
|
||||
} catch (ValidationException $e) {
|
||||
$this->reset('current_password', 'password', 'password_confirmation');
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
Auth::user()->update([
|
||||
'password' => Hash::make($validated['password']),
|
||||
]);
|
||||
|
||||
$this->reset('current_password', 'password', 'password_confirmation');
|
||||
|
||||
$this->dispatch('password-updated');
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<section class="w-full">
|
||||
@include('partials.settings-heading')
|
||||
|
||||
<x-settings.layout :heading="__('Update password')" :subheading="__('Ensure your account is using a long, random password to stay secure')">
|
||||
<form wire:submit="updatePassword" class="mt-6 space-y-6">
|
||||
<flux:input
|
||||
wire:model="current_password"
|
||||
:label="__('Current password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
<flux:input
|
||||
wire:model="password"
|
||||
:label="__('New password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<flux:input
|
||||
wire:model="password_confirmation"
|
||||
:label="__('Confirm Password')"
|
||||
type="password"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex items-center justify-end">
|
||||
<flux:button variant="primary" type="submit" class="w-full">{{ __('Save') }}</flux:button>
|
||||
</div>
|
||||
|
||||
<x-action-message class="me-3" on="password-updated">
|
||||
{{ __('Saved.') }}
|
||||
</x-action-message>
|
||||
</div>
|
||||
</form>
|
||||
</x-settings.layout>
|
||||
</section>
|
||||
114
resources/views/livewire/settings/profile.blade.php
Normal file
114
resources/views/livewire/settings/profile.blade.php
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new class extends Component {
|
||||
public string $name = '';
|
||||
public string $email = '';
|
||||
|
||||
/**
|
||||
* Mount the component.
|
||||
*/
|
||||
public function mount(): void
|
||||
{
|
||||
$this->name = Auth::user()->name;
|
||||
$this->email = Auth::user()->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the profile information for the currently authenticated user.
|
||||
*/
|
||||
public function updateProfileInformation(): void
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
$validated = $this->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'lowercase',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique(User::class)->ignore($user->id)
|
||||
],
|
||||
]);
|
||||
|
||||
$user->fill($validated);
|
||||
|
||||
if ($user->isDirty('email')) {
|
||||
$user->email_verified_at = null;
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
$this->dispatch('profile-updated', name: $user->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email verification notification to the current user.
|
||||
*/
|
||||
public function resendVerificationNotification(): void
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if ($user->hasVerifiedEmail()) {
|
||||
$this->redirectIntended(default: route('dashboard', absolute: false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$user->sendEmailVerificationNotification();
|
||||
|
||||
Session::flash('status', 'verification-link-sent');
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<section class="w-full">
|
||||
@include('partials.settings-heading')
|
||||
|
||||
<x-settings.layout :heading="__('Profile')" :subheading="__('Update your name and email address')">
|
||||
<form wire:submit="updateProfileInformation" class="my-6 w-full space-y-6">
|
||||
<flux:input wire:model="name" :label="__('Name')" type="text" required autofocus autocomplete="name" />
|
||||
|
||||
<div>
|
||||
<flux:input wire:model="email" :label="__('Email')" type="email" required autocomplete="email" />
|
||||
|
||||
@if (auth()->user() instanceof \Illuminate\Contracts\Auth\MustVerifyEmail &&! auth()->user()->hasVerifiedEmail())
|
||||
<div>
|
||||
<flux:text class="mt-4">
|
||||
{{ __('Your email address is unverified.') }}
|
||||
|
||||
<flux:link class="text-sm cursor-pointer" wire:click.prevent="resendVerificationNotification">
|
||||
{{ __('Click here to re-send the verification email.') }}
|
||||
</flux:link>
|
||||
</flux:text>
|
||||
|
||||
@if (session('status') === 'verification-link-sent')
|
||||
<flux:text class="mt-2 font-medium !dark:text-green-400 !text-green-600">
|
||||
{{ __('A new verification link has been sent to your email address.') }}
|
||||
</flux:text>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex items-center justify-end">
|
||||
<flux:button variant="primary" type="submit" class="w-full">{{ __('Save') }}</flux:button>
|
||||
</div>
|
||||
|
||||
<x-action-message class="me-3" on="profile-updated">
|
||||
{{ __('Saved.') }}
|
||||
</x-action-message>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<livewire:settings.delete-user-form />
|
||||
</x-settings.layout>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-8">Button-Demo</h2>
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
<button class="btn-primary">Primary Button</button>
|
||||
<button class="btn-secondary">Secondary Button</button>
|
||||
<button class="btn-accent">Accent Button</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<p class="text-sm text-muted-foreground mb-4">Hover-Effekte:</p>
|
||||
<div class="flex flex-wrap justify-center gap-4">
|
||||
<button class="btn-primary-accent">
|
||||
Primary → Accent (Hover)
|
||||
</button>
|
||||
<button class="btn-secondary-accent">
|
||||
Secondary → Accent (Hover)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-8">Farb-Demo</h2>
|
||||
<div class="grid md:grid-cols-3 gap-6">
|
||||
<div class="card-elevated p-6">
|
||||
<div class="w-full h-20 bg-primary rounded-lg mb-4"></div>
|
||||
<h3 class="font-medium">Primary</h3>
|
||||
<p class="text-sm text-muted-foreground">{{ \App\Helpers\ThemeHelper::getPrimaryColor() }}</p>
|
||||
</div>
|
||||
<div class="card-elevated p-6">
|
||||
<div class="w-full h-20 bg-secondary rounded-lg mb-4"></div>
|
||||
<h3 class="font-medium">Secondary</h3>
|
||||
<p class="text-sm text-muted-foreground">{{ \App\Helpers\ThemeHelper::getSecondaryColor() }}</p>
|
||||
</div>
|
||||
<div class="card-elevated p-6">
|
||||
<div class="w-full h-20 bg-accent rounded-lg mb-4"></div>
|
||||
<h3 class="font-medium">Accent</h3>
|
||||
<p class="text-sm text-muted-foreground">Neutral</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-8">{{ $title }}</h2>
|
||||
@if ($description)
|
||||
<p class="text-muted-foreground mb-8 max-w-2xl mx-auto">{{ $description }}</p>
|
||||
@endif
|
||||
|
||||
<div class="card-elevated p-8">
|
||||
@if ($component)
|
||||
<livewire:web.components.{{ $component }} />
|
||||
@else
|
||||
{{ $slot }}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-8">Logo-Demo</h2>
|
||||
<div class="grid md:grid-cols-2 gap-8">
|
||||
<div class="card-elevated p-8">
|
||||
<h3 class="text-lg font-medium mb-4">Positives Logo</h3>
|
||||
<div class="flex justify-center">
|
||||
<img src="{{ asset(\App\Helpers\ThemeHelper::getLogoPath('positive')) }}"
|
||||
alt="{{ $domainName ?? 'B2IN' }} Logo" class="h-16 w-auto" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-elevated p-8 bg-dark-bg">
|
||||
<h3 class="text-lg font-medium mb-4 text-dark-text">Negatives Logo</h3>
|
||||
<div class="flex justify-center">
|
||||
<img src="{{ asset(\App\Helpers\ThemeHelper::getLogoPath('negative')) }}"
|
||||
alt="{{ $domainName ?? 'B2IN' }} Logo" class="h-16 w-auto" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<div class="text-center mb-16">
|
||||
<h1 class="text-hero mb-8">
|
||||
Theme Demo für <span class="text-secondary">{{ $domainName ?? 'B2IN' }}</span>
|
||||
</h1>
|
||||
|
||||
<div class="card-elevated p-8 max-w-4xl mx-auto">
|
||||
<div class="grid md:grid-cols-2 gap-8 text-left">
|
||||
<div>
|
||||
<h3 class="text-xl font-medium mb-4">Aktuelle Domain-Konfiguration</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
<p><strong>Domain:</strong> {{ $domainName ?? 'Nicht erkannt' }}</p>
|
||||
<p><strong>Theme:</strong> {{ $theme ?? 'b2in' }}</p>
|
||||
<p><strong>View Prefix:</strong> {{ $viewPrefix ?? 'b2in' }}</p>
|
||||
<p><strong>URL:</strong> {{ $domainUrl ?? config('app.url') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="text-xl font-medium mb-4">Theme-Details</h3>
|
||||
<div class="space-y-2 text-sm">
|
||||
@php
|
||||
$domainConfig = \App\Helpers\ThemeHelper::getDomainConfig();
|
||||
@endphp
|
||||
<p><strong>Primärfarbe:</strong>
|
||||
<span class="inline-block w-4 h-4 rounded-full mr-2"
|
||||
style="background-color: {{ \App\Helpers\ThemeHelper::getPrimaryColor() }}"></span>
|
||||
{{ \App\Helpers\ThemeHelper::getPrimaryColor() }}
|
||||
</p>
|
||||
<p><strong>Sekundärfarbe:</strong>
|
||||
<span class="inline-block w-4 h-4 rounded-full mr-2"
|
||||
style="background-color: {{ \App\Helpers\ThemeHelper::getSecondaryColor() }}"></span>
|
||||
{{ \App\Helpers\ThemeHelper::getSecondaryColor() }}
|
||||
</p>
|
||||
<p><strong>Primärschrift:</strong> {{ \App\Helpers\ThemeHelper::getPrimaryFont() }}</p>
|
||||
<p><strong>Sekundärschrift:</strong> {{ \App\Helpers\ThemeHelper::getSecondaryFont() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<div class="text-center">
|
||||
<h2 class="text-section-title mb-8">Domain-Switching</h2>
|
||||
<div class="card-elevated p-8 max-w-4xl mx-auto">
|
||||
<p class="text-muted-foreground mb-6">Testen Sie das Theme-Switching mit verschiedenen Domains:</p>
|
||||
|
||||
<!-- Domain-basierte Links -->
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
||||
@foreach ($domains as $domain)
|
||||
<a href="{{ $domain['url'] }}/theme-demo" class="btn-secondary text-center">{{ $domain['domain_name'] }} Theme</a>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
{{-- <div class="border-t pt-6">
|
||||
<p class="text-muted-foreground mb-4">Oder testen Sie das Theme-Switching über URL-Parameter:</p>
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
||||
<a href="/theme-demo?theme=b2in" class="btn-accent text-center">B2IN (URL)</a>
|
||||
<a href="/theme-demo?theme=b2a" class="btn-accent text-center">B2A (URL)</a>
|
||||
<a href="/theme-demo?theme=stileigentum" class="btn-accent text-center">Stileigentum (URL)</a>
|
||||
<a href="/theme-demo?theme=style2own" class="btn-accent text-center">Style2own (URL)</a>
|
||||
</div>
|
||||
|
||||
<div class="border-t pt-6">
|
||||
<p class="text-muted-foreground mb-4">Für lokale Entwicklung ohne Domain-Setup (Pfad-basiert):</p>
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<a href="/b2in/theme-demo" class="btn-primary text-center">B2IN (Pfad)</a>
|
||||
<a href="/b2a/theme-demo" class="btn-primary text-center">B2A (Pfad)</a>
|
||||
<a href="/stileigentum/theme-demo" class="btn-primary text-center">Stileigentum (Pfad)</a>
|
||||
<a href="/style2own/theme-demo" class="btn-primary text-center">Style2own (Pfad)</a>
|
||||
</div>
|
||||
</div>
|
||||
--}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<section class="section-padding flex items-center relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-[hsl(var(--hero-container))] rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<h1 class="text-hero">
|
||||
{!! $content['title'] !!}
|
||||
</h1>
|
||||
|
||||
<blockquote class="text-large text-muted-foreground italic leading-relaxed border-l-4 border-secondary pl-6">
|
||||
{{ $content['quote'] }}
|
||||
</blockquote>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-16 h-px bg-secondary"></div>
|
||||
<div>
|
||||
<p class="font-semibold text-foreground">{{ $content['founder_name'] }}</p>
|
||||
<p class="text-sm text-muted-foreground">{{ $content['founder_title'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-96 lg:h-[500px] object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div class="absolute -bottom-6 -right-6 bg-secondary text-secondary-foreground p-6 rounded-2xl">
|
||||
<div class="text-3xl font-bold">{{ $content['year'] }}</div>
|
||||
<p class="text-sm opacity-90">{{ $content['year_text'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<section class="section-padding {{ $bg }}">
|
||||
<div class="container-padding">
|
||||
{{-- Section Title --}}
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title">{{ $title }}</h2>
|
||||
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
|
||||
{{ $subtitle }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{-- Brand Cards --}}
|
||||
<div class="grid md:grid-cols-3 gap-8">
|
||||
@foreach ($worlds as $world)
|
||||
<div class="card-elevated overflow-hidden group hover:shadow-elevated transition-all duration-300">
|
||||
<div class="relative">
|
||||
<img src="{{ asset('img/assets/' . $world['image']) }}" alt="{{ $world['title'] }}"
|
||||
class="w-full h-64 object-cover group-hover:scale-105 transition-transform duration-500" />
|
||||
</div>
|
||||
|
||||
<div class="p-6 spacing-small">
|
||||
<h3 class="text-xl font-medium">{{ $world['title'] }}</h3>
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $world['description'] }}
|
||||
</p>
|
||||
|
||||
<a href="{{ $world['link'] }}"
|
||||
class="inline-flex items-center gap-2 text-secondary font-medium hover:gap-3 transition-all duration-300">
|
||||
Mehr erfahren
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7">
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<section class="section-padding bg-background">
|
||||
<div class="container-padding">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="relative order-2 lg:order-1">
|
||||
<div class="card-elevated rounded-3xl p-12">
|
||||
<div class="text-center mb-8">
|
||||
<div class="w-20 h-20 mx-auto rounded-full bg-gradient-to-br from-secondary to-secondary/60 flex items-center justify-center mb-6">
|
||||
<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-semibold text-foreground mb-4">
|
||||
{{ $content['card_title'] }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="bg-accent/30 rounded-xl p-6">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<span class="text-sm text-muted-foreground">Erstverkauf</span>
|
||||
<span class="text-lg font-semibold text-secondary">{{ $content['compensation']['initial_sale'] }}</span>
|
||||
</div>
|
||||
<div class="w-full bg-accent/50 rounded-full h-2">
|
||||
<div class="bg-secondary h-2 rounded-full w-[35%]"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-accent/30 rounded-xl p-6">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<span class="text-sm text-muted-foreground">Folgegeschäfte</span>
|
||||
<span class="text-lg font-semibold text-secondary">{{ $content['compensation']['follow_up'] }}</span>
|
||||
</div>
|
||||
<div class="w-full bg-accent/50 rounded-full h-2">
|
||||
<div class="bg-secondary h-2 rounded-full w-[15%]"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center pt-4">
|
||||
<p class="text-sm text-muted-foreground">
|
||||
{{ $content['compensation_text'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-8 order-1 lg:order-2">
|
||||
<div>
|
||||
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>
|
||||
</svg>
|
||||
Für Makler
|
||||
</div>
|
||||
|
||||
<h2 class="text-section-title mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
|
||||
<p class="text-large text-muted-foreground leading-relaxed">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach($content['benefits'] as $benefit)
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
|
||||
@if($benefit['icon'] === 'trending-up')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'clock')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'target')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 1.657-2.657 1.657-2.657A8 8 0 0118.657 17.657zM12 12l1 1"/>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h3>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<section class="{{ $bg }} text-secondary-foreground section-padding">
|
||||
<div class="container-narrow text-center">
|
||||
<div class="spacing-section">
|
||||
<h2 class="text-section-title text-white">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
|
||||
<p class="text-large text-secondary-foreground max-w-2xl mx-auto leading-relaxed">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
|
||||
<div class="pt-4">
|
||||
<a
|
||||
href="{{ $content['button_link'] }}"
|
||||
class="btn-primary-accent px-8 py-4 text-lg"
|
||||
>
|
||||
{{ $content['button_text'] }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<section class="section-padding text-center">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title text-foreground mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
@foreach($content['testimonials'] as $testimonial)
|
||||
<div class="card-elevated rounded-2xl p-8 text-left space-y-6">
|
||||
<div class="flex items-center gap-4">
|
||||
<img src="{{ asset('img/assets/' . $testimonial['image']) }}" alt="{{ $testimonial['author'] }}" class="w-16 h-16 rounded-full object-cover">
|
||||
<div>
|
||||
<h4 class="font-bold text-foreground">{{ $testimonial['author'] }}</h4>
|
||||
<p class="text-sm text-muted-foreground">{{ $testimonial['author_title'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
@for ($i = 0; $i < 5; $i++)
|
||||
<svg class="w-5 h-5 {{ $i < $testimonial['rating'] ? 'text-secondary' : 'text-muted/20' }}" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
|
||||
</svg>
|
||||
@endfor
|
||||
</div>
|
||||
<blockquote class="text-muted-foreground italic leading-relaxed">
|
||||
"{{ $testimonial['quote'] }}"
|
||||
</blockquote>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<section class="section-padding {{ $bg }}">
|
||||
<div class="container-padding">
|
||||
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
|
||||
|
||||
@if($layout === 'right')
|
||||
{{-- Layout Right: Image zuerst, dann Content --}}
|
||||
{{-- Image --}}
|
||||
<div class="relative lg:order-1">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-[500px] object-cover"
|
||||
/>
|
||||
<div class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">{{ $content['image_caption'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Content --}}
|
||||
<div class="spacing-section lg:order-2">
|
||||
<div class="spacing-content">
|
||||
<h2 class="text-section-title">{{ $content['title'] }}</h2>
|
||||
<div class="spacing-small text-large text-muted-foreground leading-relaxed">
|
||||
@foreach($content['paragraphs'] as $paragraph)
|
||||
<p>{{ $paragraph }}</p>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
{{-- Layout Left (Standard): Content zuerst, dann Image --}}
|
||||
{{-- Content --}}
|
||||
<div class="spacing-section">
|
||||
<div class="spacing-content">
|
||||
<h2 class="text-section-title">{{ $content['title'] }}</h2>
|
||||
<div class="spacing-small text-large text-muted-foreground leading-relaxed">
|
||||
@foreach($content['paragraphs'] as $paragraph)
|
||||
<p>{{ $paragraph }}</p>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Image --}}
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-[500px] object-cover"
|
||||
/>
|
||||
<div class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">{{ $content['image_caption'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<section class="section-padding">
|
||||
<div class="container-padding">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-12">
|
||||
<div class="grid grid-cols-2 gap-8">
|
||||
@foreach($content['stats'] as $stat)
|
||||
<div>
|
||||
<div class="text-6xl font-light text-foreground mb-2">{{ $stat['number'] }}</div>
|
||||
<p class="text-muted-foreground text-sm">{{ $stat['text'] }}</p>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<h3 class="text-section-title">
|
||||
{!! $content['title'] !!}
|
||||
</h3>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $content['description'] }}
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 pt-8">
|
||||
@foreach($content['features'] as $feature)
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
|
||||
<span class="text-primary text-sm">✓</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-foreground font-medium text-sm">{{ $feature['title'] }}</p>
|
||||
<p class="text-muted-foreground text-xs">{{ $feature['subtitle'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated bg-muted p-0 overflow-hidden rounded-3xl">
|
||||
<img src="{{ asset('img/assets/' . $content['image']) }}" alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-96 object-cover" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<section class="section-padding bg-background">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
@foreach($content['features'] as $index => $feature)
|
||||
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
|
||||
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
|
||||
<div class="text-center space-y-6">
|
||||
<div class="w-16 h-16 mx-auto rounded-xl bg-secondary/10 flex items-center justify-center mb-6">
|
||||
@if($feature['icon'] === 'cloud')
|
||||
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'shield')
|
||||
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'layers')
|
||||
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'database')
|
||||
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<h3 class="text-xl font-semibold text-foreground">
|
||||
{{ $feature['title'] }}
|
||||
</h3>
|
||||
|
||||
<div class="w-12 h-px bg-secondary mx-auto"></div>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $feature['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-secondary/20 via-secondary to-secondary/20 transform scale-x-0 group-hover:scale-x-100 transition-transform duration-300"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
{{-- Hero Icons Helper Function --}}
|
||||
@php
|
||||
function renderHeroIcon($iconName, $style = 'outline') {
|
||||
$iconPath = public_path("heroicons/optimized/24/{$style}/{$iconName}.svg");
|
||||
$fallbackPath = public_path("heroicons/optimized/24/outline/sparkles.svg");
|
||||
|
||||
if (file_exists($iconPath)) {
|
||||
$svg = file_get_contents($iconPath);
|
||||
// Add classes for styling
|
||||
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
|
||||
} elseif (file_exists($fallbackPath)) {
|
||||
$svg = file_get_contents($fallbackPath);
|
||||
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
|
||||
}
|
||||
|
||||
// Ultimate fallback - simple star icon
|
||||
return '<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.563.563 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"/>
|
||||
</svg>';
|
||||
}
|
||||
@endphp
|
||||
|
||||
<section class="section-padding {{ $bg }}">
|
||||
<div class="container-padding">
|
||||
{{-- Section Title --}}
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title">{{ $content['title'] }}</h2>
|
||||
@if(isset($content['subtitle']))
|
||||
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Pillars Grid --}}
|
||||
<div class="grid md:grid-cols-3 gap-8 lg:gap-12">
|
||||
@foreach($content['pillars'] as $index => $pillar)
|
||||
<div class="card-elevated rounded-2xl p-8 text-center">
|
||||
<div class="text-center spacing-content group">
|
||||
<div class="mx-auto w-20 h-20 bg-secondary/10 rounded-2xl flex items-center justify-center group-hover:bg-secondary/20 transition-colors duration-300">
|
||||
{!! renderHeroIcon($pillar['icon'], $pillar['icon_style'] ?? 'outline') !!}
|
||||
</div>
|
||||
|
||||
<div class="spacing-small">
|
||||
<h3 class="text-xl font-medium">{{ $pillar['title'] }}</h3>
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $pillar['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<section class="section-padding flex items-center relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-[hsl(var(--hero-container))] rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<h1 class="text-hero">
|
||||
{!! $content['title'] !!}
|
||||
</h1>
|
||||
|
||||
<p class="text-large text-muted-foreground leading-relaxed">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
@foreach ($content['features'] as $feature)
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center">
|
||||
@if ($feature['icon'] === 'users')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z" />
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'building-2')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'network')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z" />
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-semibold text-foreground">{{ $feature['title'] }}</p>
|
||||
<p class="text-sm text-muted-foreground">{{ $feature['description'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-[600px] object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
|
||||
{{-- Floating info card --}}
|
||||
<div
|
||||
class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-24 h-24 mx-auto rounded-full bg-secondary flex items-center justify-center mb-4">
|
||||
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-foreground">{{ $content['hub']['title'] }}</h3>
|
||||
<p class="text-sm text-muted-foreground">{{ $content['hub']['subtitle'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<section class="section-padding bg-background">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
@foreach ($content['stats'] as $stat)
|
||||
<div class="card-elevated rounded-2xl p-8 text-center">
|
||||
<h2 class="text-4xl lg:text-5xl font-bold text-secondary mb-4">
|
||||
{{ $stat['number'] }}
|
||||
</h2>
|
||||
<h3 class="text-xl lg:text-2xl font-semibold text-foreground mb-3">
|
||||
{{ $stat['label'] }}
|
||||
</h3>
|
||||
<p class="text-md text-muted-foreground leading-relaxed">
|
||||
{{ $stat['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<section class="section-padding {{ $bg }}">
|
||||
<div class="container-padding">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<div>
|
||||
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/>
|
||||
</svg>
|
||||
{{ $content['tag'] }}
|
||||
</div>
|
||||
|
||||
<h2 class="text-section-title mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
|
||||
<p class="text-large text-muted-foreground leading-relaxed">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach($content['benefits'] as $benefit)
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
|
||||
@if($benefit['icon'] === 'credit-card')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'star')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'home')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h3>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-[600px] object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
|
||||
{{-- Floating info card --}}
|
||||
<div
|
||||
class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-24 h-24 mx-auto rounded-full bg-secondary flex items-center justify-center mb-4">
|
||||
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-foreground">{{ $content['card_title'] }}</h3>
|
||||
<p class="text-sm text-muted-foreground">{{ $content['card_title'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<div x-data="{ openIndex: null }">
|
||||
<section class="section-padding {{ $bg }}">
|
||||
<div class="container-padding">
|
||||
{{-- Section Title --}}
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-hero mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
@if(!empty($content['subtitle']))
|
||||
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
|
||||
{!! $content['subtitle'] !!}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- FAQ Container --}}
|
||||
<div class="max-w-4xl mx-auto">
|
||||
@if(!empty($content['questions']))
|
||||
<div class="space-y-4">
|
||||
@foreach($content['questions'] as $index => $faq)
|
||||
<div class="card-elevated rounded-xl overflow-hidden">
|
||||
<dt>
|
||||
<button
|
||||
@click="openIndex = openIndex === {{ $index }} ? null : {{ $index }}"
|
||||
class="flex w-full items-center justify-between p-6 text-left hover:bg-muted/30 transition-colors duration-200"
|
||||
:aria-expanded="openIndex === {{ $index }}"
|
||||
>
|
||||
<span class="text-lg font-medium text-foreground pr-6">
|
||||
{{ $faq['question'] }}
|
||||
</span>
|
||||
<span class="flex-shrink-0 ml-6 flex h-8 w-8 items-center justify-center rounded-full bg-secondary/10 transition-all duration-200"
|
||||
:class="openIndex === {{ $index }} ? 'bg-secondary text-white' : 'text-secondary hover:bg-secondary/20'">
|
||||
<svg class="w-5 h-5 transition-transform duration-200"
|
||||
:class="openIndex === {{ $index }} ? 'rotate-180' : ''"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</dt>
|
||||
<dd x-show="openIndex === {{ $index }}"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 transform -translate-y-2"
|
||||
x-transition:enter-end="opacity-100 transform translate-y-0"
|
||||
x-transition:leave="transition ease-in duration-150"
|
||||
x-transition:leave-start="opacity-100 transform translate-y-0"
|
||||
x-transition:leave-end="opacity-0 transform -translate-y-2"
|
||||
class="px-6 pb-6">
|
||||
<div class="border-t border-border pt-4">
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $faq['answer'] }}
|
||||
</p>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
{{-- Fallback wenn keine FAQ-Daten vorhanden --}}
|
||||
<div class="text-center py-12">
|
||||
<p class="text-muted-foreground">Keine FAQ-Inhalte verfügbar.</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<section class="section-padding text-center">
|
||||
<div class="container-narrow">
|
||||
<h2 class="text-section-title text-foreground leading-tight mb-8">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
|
||||
<div class="flex justify-center mb-8">
|
||||
<div class="w-16 h-px bg-secondary"></div>
|
||||
</div>
|
||||
|
||||
<p class="text-large text-muted-foreground">
|
||||
{{ $content['author'] }} <br />
|
||||
<span class="text-sm">{{ $content['author_title'] }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<section class="section-padding relative">
|
||||
<div class="container-padding">
|
||||
{{-- Header Content --}}
|
||||
<div class="text-center mb-12 max-w-4xl mx-auto">
|
||||
<h1 class="text-hero mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h1>
|
||||
<p class="text-large text-muted-foreground mt-4 max-w-3xl mx-auto">
|
||||
{!! $content['subtitle'] !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{-- CTA Buttons --}}
|
||||
@if(isset($content['cta1_text']) && isset($content['cta2_text']))
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center mb-16">
|
||||
<a href="{{ $content['cta1_link'] }}" class="btn-primary-accent">
|
||||
{{ $content['cta1_text'] }}
|
||||
</a>
|
||||
<a href="{{ $content['cta2_link'] }}" class="btn-secondary-accent">
|
||||
{{ $content['cta2_text'] }}
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Full Width Hero Image --}}
|
||||
<div class="relative w-full">
|
||||
<div class="relative rounded-2xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . ($content['hero_image'] ?? $content['tiles'][0]['image'])) }}"
|
||||
alt="{{ $content['hero_image_alt'] ?? $content['tiles'][0]['alt'] ?? '' }}"
|
||||
class="w-full h-64 md:h-80 lg:h-96 object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/30 via-black/10 to-transparent"></div>
|
||||
|
||||
{{-- Optional overlay content --}}
|
||||
@if(isset($content['stats']) && count($content['stats']) > 0)
|
||||
<div class="absolute bottom-0 left-0 right-0 p-8">
|
||||
<div class="flex items-center justify-center space-x-8 text-white/90 text-sm">
|
||||
@foreach ($content['stats'] as $stat)
|
||||
<span class="font-medium">{{ $stat }}</span>
|
||||
@if (!$loop->last)
|
||||
<span class="opacity-60">•</span>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
<div x-data="heroSlider()" x-init="init()">
|
||||
<section class="relative mb-10">
|
||||
<!-- Slider Container -->
|
||||
<div class="absolute inset-0 overflow-hidden">
|
||||
@if(!empty($content['slides']))
|
||||
@foreach($content['slides'] as $index => $slide)
|
||||
<div
|
||||
class="absolute inset-0 transition-opacity duration-1000 ease-in-out"
|
||||
:class="currentSlide === {{ $index }} ? 'opacity-100' : 'opacity-0'"
|
||||
>
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $slide['image']) }}"
|
||||
alt="{{ $slide['image_alt'] }}"
|
||||
class="size-full object-cover"
|
||||
/>
|
||||
<div class="absolute inset-0 bg-gray-900 opacity-20"></div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="relative mx-auto flex max-w-3xl flex-col items-center px-6 py-32 text-center sm:py-64 lg:px-0">
|
||||
<h1 class="text-hero text-white">
|
||||
{!! $content['title'] !!}
|
||||
</h1>
|
||||
<p class="mt-4 text-xl text-white">{!! $content['subtitle'] !!}</p>
|
||||
<a href="{{ $content['cta1_link'] }}" class="mt-8 inline-block btn-secondary-accent">{{ $content['cta1_text'] }}</a>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Dots -->
|
||||
@if(!empty($content['slides']) && count($content['slides']) > 1)
|
||||
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2">
|
||||
<div class="flex space-x-3">
|
||||
@foreach($content['slides'] as $index => $slide)
|
||||
<button
|
||||
@click="setSlide({{ $index }})"
|
||||
class="w-3 h-3 rounded-full border-2 border-white/50 transition-all duration-300"
|
||||
:class="currentSlide === {{ $index }} ? 'bg-white border-white' : 'bg-transparent hover:border-white/80'"
|
||||
aria-label="Slide {{ $index + 1 }} anzeigen"
|
||||
></button>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Arrow Navigation (Optional) -->
|
||||
@if(!empty($content['slides']) && count($content['slides']) > 1)
|
||||
<button
|
||||
@click="previousSlide()"
|
||||
class="absolute left-6 top-1/2 transform -translate-y-1/2 text-white/70 hover:text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-white/50 rounded-full p-2"
|
||||
aria-label="Vorheriges Bild"
|
||||
>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="nextSlide()"
|
||||
class="absolute right-6 top-1/2 transform -translate-y-1/2 text-white/70 hover:text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-white/50 rounded-full p-2"
|
||||
aria-label="Nächstes Bild"
|
||||
>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||
</svg>
|
||||
</button>
|
||||
@endif
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function heroSlider() {
|
||||
return {
|
||||
currentSlide: 0,
|
||||
totalSlides: {{ !empty($content['slides']) ? count($content['slides']) : 0 }},
|
||||
autoplayInterval: null,
|
||||
autoplayTimeout: null,
|
||||
|
||||
init() {
|
||||
if (this.totalSlides > 1) {
|
||||
this.startAutoplay();
|
||||
}
|
||||
},
|
||||
|
||||
// Automatischer Wechsel (nur für Intervall)
|
||||
autoNextSlide() {
|
||||
this.currentSlide = (this.currentSlide + 1) % this.totalSlides;
|
||||
},
|
||||
|
||||
// Manuelle Navigation
|
||||
nextSlide() {
|
||||
this.currentSlide = (this.currentSlide + 1) % this.totalSlides;
|
||||
this.resetAutoplay();
|
||||
},
|
||||
|
||||
previousSlide() {
|
||||
this.currentSlide = (this.currentSlide - 1 + this.totalSlides) % this.totalSlides;
|
||||
this.resetAutoplay();
|
||||
},
|
||||
|
||||
setSlide(index) {
|
||||
this.currentSlide = index;
|
||||
this.resetAutoplay();
|
||||
},
|
||||
|
||||
startAutoplay() {
|
||||
// Zuerst alle bestehenden Timer löschen
|
||||
this.stopAutoplay();
|
||||
|
||||
this.autoplayInterval = setInterval(() => {
|
||||
this.autoNextSlide();
|
||||
}, 5000); // Wechsel alle 5 Sekunden
|
||||
},
|
||||
|
||||
stopAutoplay() {
|
||||
if (this.autoplayInterval) {
|
||||
clearInterval(this.autoplayInterval);
|
||||
this.autoplayInterval = null;
|
||||
}
|
||||
if (this.autoplayTimeout) {
|
||||
clearTimeout(this.autoplayTimeout);
|
||||
this.autoplayTimeout = null;
|
||||
}
|
||||
},
|
||||
|
||||
resetAutoplay() {
|
||||
// Alle Timer stoppen
|
||||
this.stopAutoplay();
|
||||
|
||||
// Nach 5 Sekunden Pause wieder starten
|
||||
this.autoplayTimeout = setTimeout(() => {
|
||||
this.startAutoplay();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<section class="section-padding flex items-center relative">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 card-elevated rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
|
||||
{{-- Left Content --}}
|
||||
<div class="space-y-8">
|
||||
<div class="space-y-6">
|
||||
<h1 class="text-hero">
|
||||
{!! $content['title'] !!}
|
||||
</h1>
|
||||
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
|
||||
{!! $content['subtitle'] !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-4">
|
||||
<a href="{{ $content['cta1_link'] }}" class="btn-primary-accent">
|
||||
{{ $content['cta1_text'] }}
|
||||
</a>
|
||||
<a href="{{ $content['cta2_link'] }}" class="btn-secondary-accent">
|
||||
{{ $content['cta2_text'] }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-8 text-sm text-muted-foreground">
|
||||
@foreach ($content['stats'] as $stat)
|
||||
<span>{{ $stat }}</span>
|
||||
@if (!$loop->last)
|
||||
<span>•</span>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Right Image Tiles --}}
|
||||
<div class="relative">
|
||||
<div class="flex justify-end gap-8 sm:-mt-44 sm:justify-start sm:pl-20 lg:mt-0 lg:pl-0">
|
||||
{{-- First Column --}}
|
||||
<div class="ml-auto w-44 flex-none space-y-8 pt-32 sm:ml-0 sm:pt-80 lg:order-last lg:pt-36 xl:order-0 xl:pt-80">
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['tiles'][0]['image']) }}"
|
||||
alt="{{ $content['tiles'][0]['alt'] ?? '' }}"
|
||||
class="aspect-2/3 w-full object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Second Column --}}
|
||||
<div class="mr-auto w-44 flex-none space-y-8 sm:mr-0 sm:pt-52 lg:pt-36">
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['tiles'][1]['image']) }}"
|
||||
alt="{{ $content['tiles'][1]['alt'] ?? '' }}"
|
||||
class="aspect-2/3 w-full object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['tiles'][2]['image']) }}"
|
||||
alt="{{ $content['tiles'][2]['alt'] ?? '' }}"
|
||||
class="aspect-2/3 w-full object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Third Column --}}
|
||||
<div class="w-44 flex-none space-y-8 pt-32 sm:pt-0">
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['tiles'][3]['image']) }}"
|
||||
alt="{{ $content['tiles'][3]['alt'] ?? '' }}"
|
||||
class="aspect-2/3 w-full object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['tiles'][4]['image']) }}"
|
||||
alt="{{ $content['tiles'][4]['alt'] ?? '' }}"
|
||||
class="aspect-2/3 w-full object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<section class="section-padding flex items-center relative">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-hero-container rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
|
||||
{{-- Left Content --}}
|
||||
<div class="space-y-8">
|
||||
<div class="space-y-6">
|
||||
<h1 class="text-hero">
|
||||
{!! $content['title'] !!}
|
||||
</h1>
|
||||
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
|
||||
{!! $content['subtitle'] !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-4">
|
||||
<a href="{{ $content['cta1_link'] }}" class="btn-primary-accent">
|
||||
{{ $content['cta1_text'] }}
|
||||
</a>
|
||||
<a href="{{ $content['cta2_link'] }}" class="btn-secondary-accent">
|
||||
{{ $content['cta2_text'] }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-8 text-sm text-muted-foreground">
|
||||
@foreach ($content['stats'] as $stat)
|
||||
<span>{{ $stat }}</span>
|
||||
@if (!$loop->last)
|
||||
<span>•</span>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Right Image --}}
|
||||
<div class="relative">
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-[600px] object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
|
||||
{{-- Floating info card --}}
|
||||
<div
|
||||
class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">
|
||||
<div class="text-sm text-muted-foreground">{{ $content['card_title'] }}</div>
|
||||
<div class="text-2xl font-medium">{!! $content['card_text'] !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<section class="section-padding bg-accent">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8">
|
||||
@foreach($content['team'] as $member)
|
||||
<div class="group">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden hover:scale-105 transition-all duration-300">
|
||||
<div class="relative">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $member['image']) }}"
|
||||
alt="{{ $member['name'] }} - {{ $member['position'] }}"
|
||||
class="w-full h-80 object-cover"
|
||||
/>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent"></div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 space-y-4">
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-foreground mb-1">
|
||||
{{ $member['name'] }}
|
||||
</h3>
|
||||
<p class="text-secondary font-medium text-sm">
|
||||
{{ $member['position'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="text-muted-foreground text-sm leading-relaxed">
|
||||
{{ $member['expertise'] }}
|
||||
</p>
|
||||
|
||||
<div class="flex items-center gap-2 pt-2">
|
||||
<div class="w-8 h-px bg-secondary"></div>
|
||||
<span class="text-xs text-secondary font-medium">{{ $content['team_tag'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
<div>
|
||||
<!-- Back Navigation -->
|
||||
<div class="pt-20 pb-4">
|
||||
<div class="container-narrow">
|
||||
<a href="/magazin" class="inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
|
||||
</svg>
|
||||
{{ $content['back_to_magazine'] }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Article Header -->
|
||||
<article class="pb-16">
|
||||
<div class="container-narrow">
|
||||
<header class="text-center mb-12">
|
||||
<h1 class="text-section-title mb-6 leading-tight">
|
||||
{{ $article['title'] }}
|
||||
</h1>
|
||||
<p class="text-large text-muted-foreground mb-8 max-w-3xl mx-auto">
|
||||
{{ $article['subtitle'] }}
|
||||
</p>
|
||||
<div class="flex items-center justify-center gap-6 text-sm text-muted-foreground">
|
||||
<div class="flex items-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
<span>{{ $article['date'] }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<span>{{ $article['readTime'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Featured Image -->
|
||||
<div class="mb-12 overflow-hidden rounded-lg">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $article['image']) }}"
|
||||
alt="{{ $article['title'] }}"
|
||||
class="w-full h-64 md:h-96 object-cover"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-4 gap-12">
|
||||
<!-- Main Content -->
|
||||
<div class="md:col-span-3">
|
||||
<div class="prose prose-lg max-w-none">
|
||||
<p class="text-large text-muted-foreground leading-relaxed mb-8">
|
||||
{{ $article['content']['intro'] }}
|
||||
</p>
|
||||
|
||||
@foreach($article['content']['sections'] as $index => $section)
|
||||
<section class="mb-10" id="section-{{ $index }}">
|
||||
<h2 class="text-2xl font-medium text-foreground mb-4">
|
||||
{{ $index + 1 }}. {{ $section['title'] }}
|
||||
</h2>
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $section['content'] }}
|
||||
</p>
|
||||
</section>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="md:col-span-1">
|
||||
<div class="sticky top-24">
|
||||
|
||||
<div class="card-elevated rounded-lg p-6">
|
||||
<h3 class="font-medium text-foreground mb-4">{{ $content['share_article'] }}</h3>
|
||||
<div class="space-y-3">
|
||||
<button class="btn-secondary-accent w-full">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||
</svg>
|
||||
<span class="font-medium">LinkedIn</span>
|
||||
</button>
|
||||
|
||||
<button class="btn-secondary-accent w-full">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
|
||||
</svg>
|
||||
<span class="font-medium text-sm">Facebook</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<!-- Bottom CTA -->
|
||||
<section class="bg-secondary text-secondary-foreground section-padding">
|
||||
<div class="container-narrow text-center">
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<h2 class="text-3xl font-light mb-6 text-white">
|
||||
{!! $content['cta_title'] !!}
|
||||
</h2>
|
||||
|
||||
<a href="/magazin" class="btn-primary-accent">
|
||||
{{ $content['cta_button'] }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<section class="section-padding">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-hero mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground mt-4 max-w-3xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-8">
|
||||
@foreach($this->posts as $post)
|
||||
<article class="group">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden h-full hover:scale-[1.02] transition-all duration-300">
|
||||
<div class="flex flex-col md:flex-row">
|
||||
<div class="relative md:w-3/4 aspect-[2/1] md:aspect-[2/1]">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $post['image']) }}"
|
||||
alt="{{ $post['title'] }}"
|
||||
class="w-full h-full object-cover"
|
||||
>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
|
||||
<div class="lg:w-2/3 p-6 lg:p-8 flex flex-col justify-between">
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<time>{{ $post['date'] }}</time>
|
||||
<span class="w-1 h-1 bg-muted-foreground rounded-full"></span>
|
||||
<span>{{ $post['readTime'] }}</span>
|
||||
</div>
|
||||
|
||||
<h3 class="text-xl lg:text-2xl font-semibold text-foreground leading-tight group-hover:text-secondary transition-colors duration-200">
|
||||
<a href="/magazin/{{ $post['id'] }}" class="stretched-link">
|
||||
{{ $post['title'] }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed text-base lg:text-lg">
|
||||
{{ $post['excerpt'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between mt-6">
|
||||
<div class="flex items-center text-secondary font-medium group-hover:text-secondary-dark transition-colors duration-200">
|
||||
<a href="/magazin/{{ $post['id'] }}" class="text-sm">{{ $content['read_more'] }}</a>
|
||||
<svg class="w-4 h-4 ml-2 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="w-10 h-10 bg-primary rounded-full flex items-center justify-center group-hover:bg-secondary transition-colors duration-200">
|
||||
<a href="/magazin/{{ $post['id'] }}">
|
||||
<svg class="w-4 h-4 text-white transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-16">
|
||||
<a href="/magazin?page=2" class="btn-primary-accent">
|
||||
{{ $content['load_more'] }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<section class="section-padding">
|
||||
<div class="container-padding text-center">
|
||||
<h2 class="text-section-title text-foreground mb-12">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
@foreach($content['timeline'] as $index => $item)
|
||||
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
|
||||
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
|
||||
<div class="text-center space-y-6">
|
||||
<div class="w-12 h-12 mx-auto bg-secondary/20 rounded-full flex items-center justify-center">
|
||||
<div class="w-6 h-6 bg-secondary rounded-full"></div>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-foreground">{{ $item['title'] }}</h3>
|
||||
|
||||
<p class="text-muted-foreground text-sm leading-relaxed">
|
||||
{{ $item['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-secondary/20 via-secondary to-secondary/20 transform scale-x-0 group-hover:scale-x-100 transition-transform duration-300"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
<p class="text-large text-muted-foreground leading-relaxed max-w-3xl mx-auto mt-12">
|
||||
{{ $content['summary'] }}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
{{-- Hero Icons Helper Function --}}
|
||||
@php
|
||||
function renderHeroIcon($iconName, $style = 'outline') {
|
||||
$iconPath = public_path("heroicons/optimized/24/{$style}/{$iconName}.svg");
|
||||
$fallbackPath = public_path("heroicons/optimized/24/outline/sparkles.svg");
|
||||
|
||||
if (file_exists($iconPath)) {
|
||||
$svg = file_get_contents($iconPath);
|
||||
// Add classes for styling
|
||||
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
|
||||
} elseif (file_exists($fallbackPath)) {
|
||||
$svg = file_get_contents($fallbackPath);
|
||||
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
|
||||
}
|
||||
|
||||
// Ultimate fallback - simple star icon
|
||||
return '<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.563.563 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"/>
|
||||
</svg>';
|
||||
}
|
||||
@endphp
|
||||
<section class="section-padding">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
@foreach($content['values'] as $index => $value)
|
||||
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
|
||||
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
|
||||
<div class="text-center space-y-6">
|
||||
<div class="mx-auto w-20 h-20 bg-secondary/10 rounded-2xl flex items-center justify-center group-hover:bg-secondary/20 transition-colors duration-300">
|
||||
{!! renderHeroIcon($value['icon'], $value['icon_style'] ?? 'outline') !!}
|
||||
</div>
|
||||
|
||||
<h3 class="text-2xl font-semibold text-foreground">
|
||||
{{ $value['title'] }}
|
||||
</h3>
|
||||
|
||||
<div class="w-12 h-px bg-secondary mx-auto"></div>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $value['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-secondary/20 via-secondary to-secondary/20 transform scale-x-0 group-hover:scale-x-100 transition-transform duration-300"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
<section class="section-padding">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title text-foreground mb-6">
|
||||
{{ $content['title'] }}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid lg:grid-cols-2 gap-16">
|
||||
{{-- Für Makler --}}
|
||||
<div class="space-y-8">
|
||||
<div class="text-center lg:text-left">
|
||||
<div
|
||||
class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
|
||||
</svg>
|
||||
{{ $content['broker']['tag'] }}
|
||||
</div>
|
||||
<h3 class="text-3xl font-light text-foreground mb-6">
|
||||
{!! $content['broker']['title'] !!}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach ($content['broker']['benefits'] as $index => $benefit)
|
||||
<div class="card-elevated p-6 rounded-xl">
|
||||
<div class="flex gap-4">
|
||||
<div
|
||||
class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
|
||||
@if ($benefit['icon'] === 'trending-up')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'target')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z">
|
||||
</path>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h4>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="bg-secondary/5 rounded-xl p-6">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl font-bold text-secondary mb-2">{{ $content['broker']['highlight']['value'] }}</div>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
{{ $content['broker']['highlight']['text'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Für Lieferanten --}}
|
||||
<div class="space-y-8">
|
||||
<div class="text-center lg:text-left">
|
||||
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
|
||||
</path>
|
||||
</svg>
|
||||
{{ $content['supplier']['tag'] }}
|
||||
</div>
|
||||
<h3 class="text-3xl font-light text-foreground mb-6">
|
||||
{!! $content['supplier']['title'] !!}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach ($content['supplier']['benefits'] as $index => $benefit)
|
||||
<div class="card-elevated p-6 rounded-xl">
|
||||
<div class="flex gap-4">
|
||||
<div
|
||||
class="flex-shrink-0 w-12 h-12 rounded-xl bg-accent/20 flex items-center justify-center">
|
||||
@if ($benefit['icon'] === 'globe')
|
||||
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
|
||||
</path>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'handshake')
|
||||
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z">
|
||||
</path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z">
|
||||
</path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h4>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated p-0 overflow-hidden rounded-xl">
|
||||
<img src="{{ asset('img/assets/' . $content['supplier']['highlight']['image']) }}" alt="{{ $content['supplier']['highlight']['alt'] }}"
|
||||
class="w-full h-48 object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent flex items-end">
|
||||
<div class="p-6 text-white">
|
||||
<div class="text-2xl font-bold mb-1">{{ $content['supplier']['highlight']['value'] }}</div>
|
||||
<p class="text-sm opacity-90">{{ $content['supplier']['highlight']['text'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<section class="{{ $bg }} text-secondary-foreground section-padding">
|
||||
<div class="container-narrow text-center">
|
||||
<div class="spacing-section">
|
||||
<h2 class="text-section-title text-white">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
|
||||
|
||||
<p class="text-large text-secondary-foreground max-w-2xl mx-auto leading-relaxed">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8 py-8">
|
||||
@foreach($content['stats'] as $stat)
|
||||
<div class="text-center space-y-3">
|
||||
<div class="text-4xl font-light text-secondary-foreground">{{ $stat['number'] }}</div>
|
||||
<p class="text-secondary-foreground text-sm">{{ $stat['label'] }}</p>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="spacing-content">
|
||||
<a href="{{ $content['button_link'] }}" class="btn-primary-accent">
|
||||
{{ $content['button_text'] }}
|
||||
</a>
|
||||
|
||||
<p class="text-secondary-foreground text-sm">
|
||||
{{ $content['small_text'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
<section class="section-padding flex items-center relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-hero-container rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<h1 class="text-hero">
|
||||
{!! $content['title'] !!}
|
||||
</h1>
|
||||
|
||||
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
@foreach ($content['partner_types'] as $partner)
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center">
|
||||
@if ($partner['icon'] === 'trending-up')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
|
||||
</svg>
|
||||
@elseif($partner['icon'] === 'globe')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
@elseif($partner['icon'] === 'handshake')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-semibold text-foreground">{{ $partner['title'] }}</p>
|
||||
<p class="text-sm text-muted-foreground">{{ $partner['description'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="relative">
|
||||
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
|
||||
<img src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-[600px] object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
|
||||
{{-- Floating info card --}}
|
||||
<div
|
||||
class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-24 h-24 mx-auto rounded-full bg-secondary flex items-center justify-center mb-4">
|
||||
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-foreground">{{ $content['hub']['title'] }}</h3>
|
||||
<p class="text-sm text-muted-foreground">{{ $content['hub']['subtitle'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<section class="section-padding bg-accent">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title text-foreground mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8 mb-16">
|
||||
@foreach ($content['steps'] as $index => $step)
|
||||
<div class="card-elevated p-0 overflow-hidden group hover:shadow-elevated transition-all duration-300">
|
||||
<div class="relative overflow-hidden">
|
||||
<img src="{{ asset('img/assets/' . $step['image']) }}" alt="{{ $step['title'] }}"
|
||||
class="w-full h-64 object-cover group-hover:scale-105 transition-transform duration-300" />
|
||||
<div
|
||||
class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
</div>
|
||||
|
||||
{{-- Step Number Badge --}}
|
||||
<div
|
||||
class="absolute top-4 left-4 w-12 h-12 rounded-full bg-secondary text-white flex items-center justify-center font-bold text-lg">
|
||||
{{ $step['step'] }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-8">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-lg bg-secondary/10 flex items-center justify-center">
|
||||
@if ($step['icon'] === 'file-text')
|
||||
<svg class="w-5 h-5 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">
|
||||
</path>
|
||||
</svg>
|
||||
@elseif($step['icon'] === 'search')
|
||||
<svg class="w-5 h-5 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-5 h-5 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<h3 class="text-2xl font-medium text-foreground">
|
||||
{{ $step['title'] }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed mb-6">
|
||||
{{ $step['description'] }}
|
||||
</p>
|
||||
|
||||
@if ($index === count($content['steps']) - 1)
|
||||
<a href="/contact">
|
||||
<button class="btn-secondary-accent w-full">
|
||||
Jetzt starten
|
||||
</button>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
{{-- CTA Section --}}
|
||||
<div class="text-center">
|
||||
<div class="card-elevated p-12 rounded-3xl bg-gradient-to-br from-secondary/10 to-secondary/5">
|
||||
<h3 class="text-3xl font-light text-foreground mb-6">
|
||||
{!! $content['cta']['title'] !!}
|
||||
</h3>
|
||||
<p class="text-large text-muted-foreground mb-8 max-w-2xl mx-auto">
|
||||
{{ $content['cta']['subtitle'] }}
|
||||
</p>
|
||||
<a href="{{ $content['cta']['button_link'] }}">
|
||||
<button class="btn-primary-accent">
|
||||
{{ $content['cta']['button_text'] }}
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
|
||||
|
||||
<section class="section-padding">
|
||||
<div class="container-padding">
|
||||
<!-- Header -->
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-hero mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
|
||||
{!! $content['subtitle'] !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Filter Navigation -->
|
||||
<div class="flex flex-wrap justify-center gap-3 mb-12">
|
||||
|
||||
|
||||
@foreach($this->filters as $filterKey => $filterLabel)
|
||||
<button
|
||||
wire:click="filterBy('{{ $filterKey }}')"
|
||||
class="{{ $activeFilter === $filterKey
|
||||
? 'btn-primary-accent'
|
||||
: 'btn-secondary-accent' }}"
|
||||
>
|
||||
{{ $filterLabel }}
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Portfolio Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"
|
||||
x-data
|
||||
x-init="$nextTick(() => {
|
||||
// Smooth animation for grid changes
|
||||
$el.style.opacity = '0';
|
||||
setTimeout(() => { $el.style.opacity = '1'; }, 100);
|
||||
})">
|
||||
|
||||
@foreach($this->getFilteredProjects() as $index => $project)
|
||||
<div class="group card-elevated rounded-3xl overflow-hidden h-full hover:scale-[1.02] transition-all duration-300"
|
||||
x-data="{ loaded: false }"
|
||||
x-init="setTimeout(() => loaded = true, {{ $index * 100 }})"
|
||||
x-show="loaded"
|
||||
x-transition:enter="transition ease-out duration-700"
|
||||
x-transition:enter-start="opacity-0 transform translate-y-8"
|
||||
x-transition:enter-end="opacity-100 transform translate-y-0">
|
||||
|
||||
<!-- Image Container -->
|
||||
<div class="relative aspect-[4/3] overflow-hidden cursor-pointer"
|
||||
wire:click="openModal({{ json_encode($project) }})">
|
||||
<img src="{{ asset('img/assets/' . $project['image']) }}"
|
||||
alt="{{ $project['title'] }}"
|
||||
class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110">
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
|
||||
<!-- View Button -->
|
||||
<div class="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all duration-300">
|
||||
<button class="btn-primary-accent">
|
||||
<div class="flex items-center justify-center">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
|
||||
</svg>
|
||||
<span class="font-medium"> Ansehen</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Category Badge -->
|
||||
<div class="absolute top-4 left-4">
|
||||
<span class="bg-primary text-white px-3 py-1 rounded-full text-xs font-medium">
|
||||
{{ $project['category'] }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="p-6 lg:p-8 flex flex-col justify-between">
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-2xl lg:text-3xl font-semibold text-foreground leading-tight group-hover:text-secondary transition-colors duration-200">
|
||||
{{ $project['title'] }}
|
||||
</h3>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed text-base line-clamp-2">
|
||||
{{ $project['description'] }}
|
||||
</p>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@foreach($project['features'] as $feature)
|
||||
<span class="text-xs bg-muted text-muted-foreground px-2 py-1 rounded">
|
||||
{{ $feature }}
|
||||
</span>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Location and Price -->
|
||||
<div class="flex items-center justify-between mt-6">
|
||||
<div class="flex items-center text-sm text-muted-foreground gap-4">
|
||||
@if(isset($project['location']) && $project['location'] != '')
|
||||
<div class="flex items-center gap-1">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
{{ $project['location'] }}
|
||||
</div>
|
||||
@endif
|
||||
@if(isset($project['price']) && $project['price'] != '')
|
||||
<span class="w-1 h-1 bg-muted-foreground rounded-full"></span>
|
||||
<span class="font-medium text-secondary">{{ $project['price'] }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@if(empty($this->getFilteredProjects()))
|
||||
<div class="text-center py-16">
|
||||
<div class="w-24 h-24 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center">
|
||||
<svg class="w-12 h-12 text-muted-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-medium text-foreground mb-2">Keine Projekte gefunden</h3>
|
||||
<p class="text-muted-foreground">Versuchen Sie einen anderen Filter</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div x-data="{ show: @entangle('showModal').live }"
|
||||
x-show="show"
|
||||
x-cloak
|
||||
class="fixed inset-0 z-50 overflow-y-auto"
|
||||
x-transition:enter="transition ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="transition ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
@click="$wire.closeModal()">
|
||||
|
||||
<!-- Backdrop -->
|
||||
<div class="fixed inset-0 bg-black/70 backdrop-blur-sm"></div>
|
||||
|
||||
<!-- Modal Content -->
|
||||
<div class="relative min-h-screen flex items-center justify-center p-4">
|
||||
<div class="relative card-elevated rounded-3xl max-w-4xl w-full max-h-[90vh] overflow-hidden"
|
||||
x-show="show"
|
||||
x-transition:enter="transition ease-out duration-300 transform"
|
||||
x-transition:enter-start="opacity-0 scale-95"
|
||||
x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-200 transform"
|
||||
x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
@click.stop>
|
||||
|
||||
@if($selectedProject)
|
||||
<!-- Close Button -->
|
||||
<button @click="$wire.closeModal()"
|
||||
class="absolute top-4 right-4 z-20 bg-secondary text-white rounded-full p-2 hover:bg-secondary/80 transition-colors duration-200">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Scrollable Content Area -->
|
||||
<div class="h-full max-h-[90vh] overflow-y-auto">
|
||||
<!-- Image -->
|
||||
<div class="aspect-[16/10] relative overflow-hidden rounded-t-2xl">
|
||||
<img src="{{ asset('img/assets/' . $selectedProject['image']) }}"
|
||||
alt="{{ $selectedProject['title'] }}"
|
||||
class="w-full h-full object-cover">
|
||||
|
||||
<!-- Category Badge -->
|
||||
<div class="absolute top-6 left-6">
|
||||
<span class="bg-primary text-white px-4 py-2 rounded-full text-sm font-medium">
|
||||
{{ $selectedProject['category'] }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="p-8">
|
||||
<div class="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-6">
|
||||
<div class="flex-1">
|
||||
<h2 class="text-section-title mb-4">
|
||||
{{ $selectedProject['title'] }}
|
||||
</h2>
|
||||
<p class="text-muted-foreground mb-6 leading-relaxed text-base lg:text-lg">
|
||||
{{ $selectedProject['description'] }}
|
||||
</p>
|
||||
|
||||
<!-- Features -->
|
||||
<div class="mb-6">
|
||||
<h4 class="font-semibold text-foreground mb-3">Ausstattung</h4>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@foreach($selectedProject['features'] as $feature)
|
||||
<span class="bg-muted text-muted-foreground px-3 py-1 rounded-full text-sm">
|
||||
{{ $feature }}
|
||||
</span>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Details Sidebar -->
|
||||
<div class="lg:w-80 card-elevated rounded-lg p-6">
|
||||
<h4 class="font-semibold text-foreground mb-4">Projektdetails</h4>
|
||||
|
||||
<div class="space-y-4">
|
||||
@if(isset($selectedProject['location']) && $selectedProject['location'] != '')
|
||||
<div class="flex items-start gap-3">
|
||||
<svg class="w-5 h-5 text-muted-foreground mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<span class="text-sm text-muted-foreground">Standort</span>
|
||||
<div class="font-medium text-foreground">{{ $selectedProject['location'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(isset($selectedProject['price']) && $selectedProject['price'] != '')
|
||||
<div class="flex items-start gap-3">
|
||||
<svg class="w-5 h-5 text-muted-foreground mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<span class="text-sm text-muted-foreground">Preis</span>
|
||||
<div class="font-bold text-lg text-secondary">{{ $selectedProject['price'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(isset($selectedProject['size']) && $selectedProject['size'] != '')
|
||||
<div class="flex items-start gap-3">
|
||||
<svg class="w-5 h-5 text-muted-foreground mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4a1 1 0 011-1h4m0 0V4m0-1h6m0 1v3M4 8h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V8z"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<span class="text-sm text-muted-foreground">Größe</span>
|
||||
<div class="font-medium text-foreground">{{ $selectedProject['size'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- CTA Button -->
|
||||
<button class="btn-primary-accent w-full mt-6">
|
||||
Kontakt aufnehmen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
.line-clamp-2 {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Custom scrollbar for modal */
|
||||
.overflow-y-auto::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-thumb {
|
||||
background: hsl(var(--muted-foreground) / 0.3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
|
||||
background: hsl(var(--muted-foreground) / 0.5);
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<section class="section-padding bg-muted/20">
|
||||
<div class="container-padding">
|
||||
{{-- Section Title --}}
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title">{{ $content['title'] }}</h2>
|
||||
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{-- Spotlights Grid --}}
|
||||
<div class="grid md:grid-cols-3 gap-8 lg:gap-12">
|
||||
@foreach ($content['spotlights'] as $index => $spotlight)
|
||||
<div class="text-center space-y-6 group">
|
||||
<div
|
||||
class="mx-auto w-20 h-20 bg-secondary/10 rounded-2xl flex items-center justify-center group-hover:bg-secondary/20 transition-colors duration-300">
|
||||
@if ($spotlight['icon'] === 'map-pin')
|
||||
<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z">
|
||||
</path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
@elseif($spotlight['icon'] === 'star')
|
||||
<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z">
|
||||
</path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-xl font-medium">{{ $spotlight['title'] }}</h3>
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $spotlight['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<section class="section-padding bg-accent">
|
||||
<div class="container-padding">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<div>
|
||||
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
|
||||
</svg>
|
||||
{{ $content['tag'] }}
|
||||
</div>
|
||||
|
||||
<h2 class="text-section-title mb-6">
|
||||
{!! $content['title'] !!}
|
||||
</h2>
|
||||
|
||||
<p class="text-large text-muted-foreground leading-relaxed">
|
||||
{{ $content['subtitle'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach($content['benefits'] as $benefit)
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
|
||||
@if($benefit['icon'] === 'store')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'settings')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'check-circle')
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h3>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl p-8">
|
||||
<div class="space-y-8">
|
||||
<div class="text-center">
|
||||
<div class="w-20 h-20 mx-auto rounded-full bg-gradient-to-br from-secondary/20 to-secondary/5 flex items-center justify-center mb-6">
|
||||
<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-semibold text-foreground mb-4">
|
||||
{{ $content['dashboard']['title'] }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
@foreach($content['dashboard']['stats'] as $stat)
|
||||
<div class="bg-accent/30 rounded-xl p-4">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span class="text-sm font-medium text-foreground">{{ $stat['label'] }}</span>
|
||||
<span class="text-xs text-secondary">{{ $stat['value'] }}</span>
|
||||
</div>
|
||||
<div class="w-full bg-accent/50 rounded-full h-2">
|
||||
<div class="bg-secondary h-2 rounded-full" style="width: {{ $stat['value'] }}"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<section class="section-padding {{ $bg }}">
|
||||
<div class="container-padding">
|
||||
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
|
||||
{{-- Content --}}
|
||||
<div class="spacing-section">
|
||||
<div class="spacing-content">
|
||||
<h2 class="text-section-title">{{ $content['title'] }}</h2>
|
||||
<div class="spacing-small text-large text-muted-foreground leading-relaxed">
|
||||
@foreach($content['paragraphs'] as $paragraph)
|
||||
<p>{{ $paragraph }}</p>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Image --}}
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $content['image']) }}"
|
||||
alt="{{ $content['image_alt'] }}"
|
||||
class="w-full h-[500px] object-cover"
|
||||
/>
|
||||
|
||||
<div class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">{{ $content['image_caption'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<section class="min-h-screen flex items-center relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-[hsl(var(--hero-container))] rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<h1 class="text-5xl lg:text-6xl font-light text-foreground">
|
||||
Über <span class="text-secondary">B2In</span>
|
||||
</h1>
|
||||
|
||||
<blockquote class="text-xl lg:text-2xl text-muted-foreground italic leading-relaxed border-l-4 border-secondary pl-6">
|
||||
"Unsere Vision ist es, Unternehmen durch innovative Konnektivitätslösungen zu verbinden
|
||||
und nachhaltiges Wachstum in der digitalen Welt zu ermöglichen. Bei B2In schaffen wir
|
||||
nicht nur Verbindungen – wir bauen Brücken in die Zukunft."
|
||||
</blockquote>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-16 h-px bg-secondary"></div>
|
||||
<div>
|
||||
<p class="font-semibold text-foreground">Marcel Scheibe</p>
|
||||
<p class="text-sm text-muted-foreground">Gründer & CEO, B2In</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden">
|
||||
<img
|
||||
src="{{ asset('img/assets/marcel-scheibe.jpg') }}"
|
||||
alt="Marcel Scheibe, Gründer und CEO von B2In"
|
||||
class="w-full h-96 lg:h-[500px] object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div class="absolute -bottom-6 -right-6 bg-secondary text-secondary-foreground p-6 rounded-2xl">
|
||||
<div class="text-3xl font-bold">2019</div>
|
||||
<p class="text-sm opacity-90">Gründungsjahr</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
<section class="py-20 px-4 bg-background">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="relative order-2 lg:order-1">
|
||||
<div class="card-elevated rounded-3xl p-12">
|
||||
<div class="text-center mb-8">
|
||||
<div class="w-20 h-20 mx-auto rounded-full bg-gradient-to-br from-primary to-primary/60 flex items-center justify-center mb-6">
|
||||
<svg class="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-semibold text-foreground mb-4">
|
||||
Lifetime-Vergütung
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="bg-accent/30 rounded-xl p-6">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<span class="text-sm text-muted-foreground">Erstverkauf</span>
|
||||
<span class="text-lg font-semibold text-primary">3.5%</span>
|
||||
</div>
|
||||
<div class="w-full bg-accent/50 rounded-full h-2">
|
||||
<div class="bg-primary h-2 rounded-full w-[35%]"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-accent/30 rounded-xl p-6">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<span class="text-sm text-muted-foreground">Folgegeschäfte</span>
|
||||
<span class="text-lg font-semibold text-primary">1.5%</span>
|
||||
</div>
|
||||
<div class="w-full bg-accent/50 rounded-full h-2">
|
||||
<div class="bg-primary h-2 rounded-full w-[15%]"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center pt-4">
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Kontinuierliche Erträge über die gesamte Kundenbeziehung
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-8 order-1 lg:order-2">
|
||||
<div>
|
||||
<div class="inline-flex items-center gap-2 bg-primary/10 text-primary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>
|
||||
</svg>
|
||||
Für Makler
|
||||
</div>
|
||||
|
||||
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
|
||||
Lifetime <span class="text-primary">Vergütung</span> für Makler
|
||||
</h2>
|
||||
|
||||
<p class="text-xl text-muted-foreground leading-relaxed">
|
||||
Profitieren Sie von einem revolutionären Vergütungsmodell, das über
|
||||
den einmaligen Verkauf hinausgeht. Bauen Sie langfristige Kundenbeziehungen
|
||||
auf und generieren Sie kontinuierliche Erträge.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach($this->benefits as $benefit)
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center">
|
||||
@if($benefit['icon'] === 'trending-up')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'clock')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'target')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 1.657-2.657 1.657-2.657A8 8 0 0118.657 17.657zM12 12l1 1"/>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h3>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<section class="py-16 px-4 text-center">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<div class="mb-8">
|
||||
<div
|
||||
class="inline-flex items-center gap-2 bg-primary text-primary-foreground px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
★ 4.9 Rating
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="text-section-title text-foreground mb-6">
|
||||
Committed to excellence, ensuring <br />
|
||||
<span class="text-secondary">enduring comfort</span> and creating lasting <br />
|
||||
memories
|
||||
</h2>
|
||||
|
||||
<p class="text-muted-foreground text-lg">
|
||||
Robert Wilson
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<section class="section-dark py-20 px-4">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-12">
|
||||
<div class="grid grid-cols-2 gap-8">
|
||||
<div>
|
||||
<div class="text-6xl font-light text-dark-text mb-2">17+</div>
|
||||
<p class="text-dark-muted text-sm">Years of Experience</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-6xl font-light text-dark-text mb-2">2M</div>
|
||||
<p class="text-dark-muted text-sm">Happy Guests</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
<h3 class="text-3xl font-light text-dark-text">
|
||||
Economically Sound and Well-<br />
|
||||
<span class="text-secondary">Friendly Service</span> for<br />
|
||||
Families and Their<br />
|
||||
Precious Belongings
|
||||
</h3>
|
||||
|
||||
<p class="text-dark-muted leading-relaxed">
|
||||
We understand that every family is unique, which is why we offer personalized
|
||||
services tailored to meet your specific needs. From luxury amenities to
|
||||
budget-friendly options, we ensure every guest feels valued and comfortable.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 pt-8">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
|
||||
<span class="text-primary text-sm">✓</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-dark-text font-medium text-sm">Top Consultation</p>
|
||||
<p class="text-dark-muted text-xs">Expert guidance</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
|
||||
<span class="text-primary text-sm">✓</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-dark-text font-medium text-sm">Finest Meal</p>
|
||||
<p class="text-dark-muted text-xs">Gourmet dining</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
|
||||
<span class="text-primary text-sm">✓</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-dark-text font-medium text-sm">Easy Tax Reduction</p>
|
||||
<p class="text-dark-muted text-xs">Cost-effective</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated bg-dark-muted p-0 overflow-hidden rounded-3xl">
|
||||
<img src="{{ asset('img/assets/accommodation-2.jpg') }}" alt="Luxury interior design"
|
||||
class="w-full h-96 object-cover" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<section class="py-20 px-4 bg-background">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
|
||||
Digitales <span class="text-primary">Herzstück</span>
|
||||
</h2>
|
||||
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
Modernste Technologie-Infrastruktur, die alle Ecosystem-Teilnehmer
|
||||
nahtlos miteinander verbindet und außergewöhnliche Nutzererfahrungen ermöglicht.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
@foreach($this->features as $index => $feature)
|
||||
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
|
||||
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
|
||||
<div class="text-center space-y-6">
|
||||
<div class="w-16 h-16 mx-auto rounded-xl bg-primary/10 flex items-center justify-center mb-6">
|
||||
@if($feature['icon'] === 'cloud')
|
||||
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'shield')
|
||||
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'layers')
|
||||
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'database')
|
||||
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<h3 class="text-xl font-semibold text-foreground">
|
||||
{{ $feature['title'] }}
|
||||
</h3>
|
||||
|
||||
<div class="w-12 h-px bg-primary mx-auto"></div>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $feature['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-primary/20 via-primary to-primary/20 transform scale-x-0 group-hover:scale-x-100 transition-transform duration-300"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
<section class="min-h-screen flex items-center relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-[hsl(var(--hero-container))] rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<h1 class="text-5xl lg:text-7xl font-light text-foreground">
|
||||
B2In <span class="text-primary">Ecosystem</span>
|
||||
</h1>
|
||||
|
||||
<p class="text-xl lg:text-2xl text-muted-foreground leading-relaxed">
|
||||
Ein intelligentes Netzwerk, das Endkunden, Makler, Lieferanten und
|
||||
Technologie nahtlos miteinander verbindet. Jeder Teilnehmer profitiert
|
||||
vom gesamten System und schafft gemeinsam außergewöhnliche Immobilienerlebnisse.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
@foreach ($this->features as $feature)
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center">
|
||||
@if ($feature['icon'] === 'users')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z" />
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'building-2')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||
</svg>
|
||||
@elseif($feature['icon'] === 'network')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z" />
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-semibold text-foreground">{{ $feature['title'] }}</p>
|
||||
<p class="text-sm text-muted-foreground">{{ $feature['description'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl p-12 bg-background/80 backdrop-blur-sm">
|
||||
<div class="space-y-8">
|
||||
<!-- Central Hub -->
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-24 h-24 mx-auto rounded-full bg-primary flex items-center justify-center mb-4">
|
||||
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-foreground">B2In Portal</h3>
|
||||
<p class="text-sm text-muted-foreground">Zentrale Plattform</p>
|
||||
</div>
|
||||
|
||||
<!-- Connection Points -->
|
||||
<div class="grid grid-cols-2 gap-8">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">Endkunden</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">Makler</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">Lieferanten</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">B2A</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<section class="py-20 px-4 bg-background">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
|
||||
Unser <span class="text-primary">Ecosystem</span> in Zahlen
|
||||
</h2>
|
||||
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
Zahlen, die die Stärke und das Vertrauen in unser vernetztes
|
||||
Geschäftsmodell widerspiegeln.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
@foreach ($this->stats as $stat)
|
||||
<div class="card-elevated rounded-2xl p-8 text-center">
|
||||
<div class="text-4xl lg:text-5xl font-bold text-primary mb-4">
|
||||
{{ $stat['number'] }}
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold text-foreground mb-3">
|
||||
{{ $stat['label'] }}
|
||||
</h3>
|
||||
<p class="text-sm text-muted-foreground leading-relaxed">
|
||||
{{ $stat['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<section class="py-20 px-4 bg-accent/30">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<div>
|
||||
<div class="inline-flex items-center gap-2 bg-primary/10 text-primary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/>
|
||||
</svg>
|
||||
Für Endkunden
|
||||
</div>
|
||||
|
||||
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
|
||||
Exklusive <span class="text-primary">Erlebnisse</span> für Sie
|
||||
</h2>
|
||||
|
||||
<p class="text-xl text-muted-foreground leading-relaxed">
|
||||
Mit Ihrer persönlichen Login-Karte erhalten Sie Zugang zu einer
|
||||
einzigartigen Erlebniswelt, die speziell auf Ihre Wohnwünsche
|
||||
und Lebensstil abgestimmt ist. Entdecken Sie kuratierte Immobilien
|
||||
und Services, die sonst nicht verfügbar sind.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach($this->benefits as $benefit)
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center">
|
||||
@if($benefit['icon'] === 'credit-card')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'star')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'home')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h3>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden">
|
||||
<div class="bg-gradient-to-br from-primary/20 to-primary/5 p-12 h-96 flex flex-col justify-center items-center text-center">
|
||||
<div class="w-24 h-24 rounded-full bg-primary/20 backdrop-blur-sm flex items-center justify-center mb-6">
|
||||
<svg class="w-12 h-12 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-semibold text-foreground mb-4">
|
||||
Login-Karte
|
||||
</h3>
|
||||
<p class="text-muted-foreground mb-6">
|
||||
Ihr Schlüssel zu exklusiven Immobilienerlebnissen
|
||||
</p>
|
||||
<div class="bg-background/80 backdrop-blur-sm rounded-xl p-4 w-full max-w-xs">
|
||||
<div class="text-sm text-muted-foreground mb-2">Mitgliedsnummer</div>
|
||||
<div class="font-mono text-lg">B2IN-2024-VIP</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<section class="section-dark py-20 px-4 text-center">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<h2 class="text-5xl md:text-6xl font-light text-dark-text leading-tight mb-8">
|
||||
Were committed to <br />
|
||||
your <span class="text-secondary">comfort</span> and <br />
|
||||
<span class="text-secondary">satisfaction</span> for <br />
|
||||
unforgettable <br />
|
||||
experiences
|
||||
</h2>
|
||||
|
||||
<div class="flex justify-center mb-8">
|
||||
<div class="w-16 h-px bg-secondary"></div>
|
||||
</div>
|
||||
|
||||
<p class="text-dark-muted text-lg">
|
||||
Robert Wilson <br />
|
||||
<span class="text-sm">General Manager</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<section class="py-20 px-4 bg-background">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
|
||||
Das <span class="text-secondary">Führungsteam</span>
|
||||
</h2>
|
||||
<p class="text-muted-foreground text-lg max-w-2xl mx-auto">
|
||||
Unser erfahrenes Team bringt jahrzehntelange Expertise in den Bereichen
|
||||
Technologie, Operations und Geschäftsentwicklung mit.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8">
|
||||
@foreach($this->team as $member)
|
||||
<div class="group">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden hover:scale-105 transition-all duration-300">
|
||||
<div class="relative">
|
||||
<img
|
||||
src="{{ asset('img/assets/' . $member['image']) }}"
|
||||
alt="{{ $member['name'] }} - {{ $member['position'] }}"
|
||||
class="w-full h-80 object-cover"
|
||||
/>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent"></div>
|
||||
</div>
|
||||
|
||||
<div class="p-6 space-y-4">
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold text-foreground mb-1">
|
||||
{{ $member['name'] }}
|
||||
</h3>
|
||||
<p class="text-secondary font-medium text-sm">
|
||||
{{ $member['position'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="text-muted-foreground text-sm leading-relaxed">
|
||||
{{ $member['expertise'] }}
|
||||
</p>
|
||||
|
||||
<div class="flex items-center gap-2 pt-2">
|
||||
<div class="w-8 h-px bg-secondary"></div>
|
||||
<span class="text-xs text-secondary font-medium">B2IN TEAM</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<div>
|
||||
<!-- Back Navigation -->
|
||||
<div class="pt-20 pb-4">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<a href="/magazin" class="inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
|
||||
</svg>
|
||||
Zurück zum Magazin
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Article Header -->
|
||||
<article class="pb-16">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<header class="text-center mb-12">
|
||||
<h1 class="text-4xl md:text-5xl font-light text-foreground mb-6 leading-tight">
|
||||
{{ $article['title'] }}
|
||||
</h1>
|
||||
<p class="text-xl text-muted-foreground mb-8 max-w-3xl mx-auto">
|
||||
{{ $article['subtitle'] }}
|
||||
</p>
|
||||
<div class="flex items-center justify-center gap-6 text-sm text-muted-foreground">
|
||||
<div class="flex items-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
<span>{{ $article['date'] }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<span>{{ $article['readTime'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Featured Image -->
|
||||
<div class="mb-12 overflow-hidden rounded-lg">
|
||||
<img
|
||||
src="{{ asset('images/' . $article['image']) }}"
|
||||
alt="{{ $article['title'] }}"
|
||||
class="w-full h-64 md:h-96 object-cover"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-4 gap-12">
|
||||
<!-- Main Content -->
|
||||
<div class="md:col-span-3">
|
||||
<div class="prose prose-lg max-w-none">
|
||||
<p class="text-lg text-muted-foreground leading-relaxed mb-8">
|
||||
{{ $article['content']['intro'] }}
|
||||
</p>
|
||||
|
||||
@foreach($article['content']['sections'] as $index => $section)
|
||||
<section class="mb-10" id="section-{{ $index }}">
|
||||
<h2 class="text-2xl font-medium text-foreground mb-4">
|
||||
{{ $index + 1 }}. {{ $section['title'] }}
|
||||
</h2>
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $section['content'] }}
|
||||
</p>
|
||||
</section>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="md:col-span-1">
|
||||
<div class="sticky top-24">
|
||||
|
||||
<div class="card-elevated rounded-lg p-6">
|
||||
<h3 class="font-medium text-foreground mb-4">Artikel teilen</h3>
|
||||
<div class="space-y-3">
|
||||
<button class="w-full bg-[#0077B5] hover:bg-[#0095e5] text-white rounded-lg py-3 px-4 flex items-center justify-center gap-3 transition-colors duration-200">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||
</svg>
|
||||
<span class="font-medium">LinkedIn</span>
|
||||
</button>
|
||||
|
||||
<button class="w-full bg-[#3b5998] hover:bg-[#5077cc] text-white rounded-lg py-3 px-4 flex items-center justify-center gap-3 transition-colors duration-200">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
|
||||
</svg>
|
||||
<span class="font-medium text-sm">Facebook</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<!-- Bottom CTA -->
|
||||
<section class="bg-secondary text-secondary-foreground section-padding">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<h2 class="text-3xl font-light mb-6 text-[hsl(var(--dark-text))]">
|
||||
Entdecken Sie mehr über
|
||||
<span class="text-primary font-medium">Luxus</span> und
|
||||
<span class="text-primary font-medium">Komfort</span>
|
||||
für unvergessliche Erlebnisse.
|
||||
</h2>
|
||||
|
||||
<a href="/magazin" class="btn-accent px-8 py-3 rounded-lg">
|
||||
Weitere Artikel entdecken
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<section class="py-20 px-4">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
|
||||
B2In <span class="text-secondary">Magazin</span>
|
||||
</h2>
|
||||
<p class="text-muted-foreground text-lg max-w-2xl mx-auto">
|
||||
Entdecken Sie die neuesten Trends, Insights und Geschichten aus der Welt
|
||||
der Business-Konnektivität und Innovation.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-8">
|
||||
@foreach($this->posts as $post)
|
||||
<article class="group">
|
||||
<div class="card-elevated rounded-3xl overflow-hidden h-full hover:scale-[1.02] transition-all duration-300">
|
||||
<div class="flex flex-col md:flex-row">
|
||||
<div class="relative md:w-3/4 aspect-[2/1] md:aspect-[2/1]">
|
||||
<img
|
||||
src="{{ asset('images/' . $post['image']) }}"
|
||||
alt="{{ $post['title'] }}"
|
||||
class="w-full h-full object-cover"
|
||||
>
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
</div>
|
||||
|
||||
<div class="lg:w-2/3 p-6 lg:p-8 flex flex-col justify-between">
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<time>{{ $post['date'] }}</time>
|
||||
<span class="w-1 h-1 bg-muted-foreground rounded-full"></span>
|
||||
<span>{{ $post['readTime'] }}</span>
|
||||
</div>
|
||||
|
||||
<h3 class="text-xl lg:text-2xl font-semibold text-foreground leading-tight group-hover:text-secondary transition-colors duration-200">
|
||||
<a href="/magazin/{{ $post['id'] }}" class="stretched-link">
|
||||
{{ $post['title'] }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed text-base lg:text-lg">
|
||||
{{ $post['excerpt'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between mt-6">
|
||||
<div class="flex items-center text-secondary font-medium group-hover:text-secondary-dark transition-colors duration-200">
|
||||
<a href="/magazin/{{ $post['id'] }}" class="text-sm">Weiterlesen</a>
|
||||
<svg class="w-4 h-4 ml-2 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="w-10 h-10 bg-primary rounded-full flex items-center justify-center group-hover:bg-secondary transition-colors duration-200">
|
||||
<a href="/magazin/{{ $post['id'] }}">
|
||||
<svg class="w-4 h-4 text-white transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-16">
|
||||
<a href="/magazin?page=2" class="btn-primary px-8 py-4 rounded-2xl">
|
||||
Weitere Artikel laden
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<section class="section-dark section-padding">
|
||||
<div class="container-narrow text-center">
|
||||
<h2 class="text-section-title text-[hsl(var(--dark-text))] mb-12">
|
||||
Unsere <span class="text-secondary">Geschichte</span>
|
||||
</h2>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8 mb-16">
|
||||
@foreach($this->timeline as $item)
|
||||
<div class="spacing-small">
|
||||
<div class="w-12 h-12 mx-auto bg-secondary/20 rounded-full flex items-center justify-center">
|
||||
<div class="w-6 h-6 bg-secondary rounded-full"></div>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-[hsl(var(--dark-text))]">{{ $item['title'] }}</h3>
|
||||
<p class="text-dark-muted text-sm leading-relaxed">
|
||||
{{ $item['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<p class="text-large text-dark-muted leading-relaxed max-w-3xl mx-auto">
|
||||
Was als Vision begann, traditionelle Geschäftsprozesse zu revolutionieren, ist heute eine
|
||||
bewährte Plattform für digitale Innovation. B2In schließt die Lücke zwischen
|
||||
traditionellen Unternehmen und modernen, digitalen Lösungen durch maßgeschneiderte
|
||||
Konnektivitätsservices, die Effizienz steigern und nachhaltiges Wachstum fördern.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<section class="py-20 px-4">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
|
||||
Unsere <span class="text-secondary">Werte</span>
|
||||
</h2>
|
||||
<p class="text-muted-foreground text-lg max-w-2xl mx-auto">
|
||||
Diese fünf Grundpfeiler leiten unser tägliches Handeln und definieren,
|
||||
wer wir als Unternehmen sind und wofür wir stehen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
@foreach($this->values as $index => $value)
|
||||
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
|
||||
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
|
||||
<div class="text-center space-y-6">
|
||||
<div class="text-5xl mb-4">{{ $value['icon'] }}</div>
|
||||
|
||||
<h3 class="text-2xl font-semibold text-foreground">
|
||||
{{ $value['title'] }}
|
||||
</h3>
|
||||
|
||||
<div class="w-12 h-px bg-secondary mx-auto"></div>
|
||||
|
||||
<p class="text-muted-foreground leading-relaxed">
|
||||
{{ $value['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-secondary/20 via-secondary to-secondary/20 transform scale-x-0 group-hover:scale-x-100 transition-transform duration-300"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
<section class="py-16 px-4">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-section-title text-foreground mb-6">
|
||||
Warum Partner werden?
|
||||
</h2>
|
||||
<p class="text-muted-foreground text-lg max-w-3xl mx-auto">
|
||||
Entdecken Sie die Vorteile einer Partnerschaft mit B2In und
|
||||
wie Sie von unserem innovativen Ecosystem profitieren können.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid lg:grid-cols-2 gap-16">
|
||||
{{-- Für Makler --}}
|
||||
<div class="space-y-8">
|
||||
<div class="text-center lg:text-left">
|
||||
<div
|
||||
class="inline-flex items-center gap-2 bg-primary/10 text-primary px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
|
||||
</svg>
|
||||
Für Makler
|
||||
</div>
|
||||
<h3 class="text-3xl font-light text-foreground mb-6">
|
||||
Revolutionäres <span class="text-primary">Provisionsmodell</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach ($this->brokerBenefits as $index => $benefit)
|
||||
<div class="card-elevated p-6 rounded-xl">
|
||||
<div class="flex gap-4">
|
||||
<div
|
||||
class="flex-shrink-0 w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center">
|
||||
@if ($benefit['icon'] === 'trending-up')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'target')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z">
|
||||
</path>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h4>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="bg-primary/5 rounded-xl p-6">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl font-bold text-primary mb-2">3.5% - ∞</div>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Erstprovision bis Lifetime-Vergütung
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Für Lieferanten --}}
|
||||
<div class="space-y-8">
|
||||
<div class="text-center lg:text-left">
|
||||
<div
|
||||
class="inline-flex items-center gap-2 bg-accent/50 text-accent-foreground px-4 py-2 rounded-full text-sm font-medium mb-6">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
|
||||
</path>
|
||||
</svg>
|
||||
Für Lieferanten
|
||||
</div>
|
||||
<h3 class="text-3xl font-light text-foreground mb-6">
|
||||
Globale <span class="text-primary">Marktchancen</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="space-y-6">
|
||||
@foreach ($this->supplierBenefits as $index => $benefit)
|
||||
<div class="card-elevated p-6 rounded-xl">
|
||||
<div class="flex gap-4">
|
||||
<div
|
||||
class="flex-shrink-0 w-12 h-12 rounded-xl bg-accent/20 flex items-center justify-center">
|
||||
@if ($benefit['icon'] === 'globe')
|
||||
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
|
||||
</path>
|
||||
</svg>
|
||||
@elseif($benefit['icon'] === 'handshake')
|
||||
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z">
|
||||
</path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z">
|
||||
</path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="text-lg font-semibold text-foreground mb-2">
|
||||
{{ $benefit['title'] }}
|
||||
</h4>
|
||||
<p class="text-muted-foreground">
|
||||
{{ $benefit['description'] }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated p-0 overflow-hidden rounded-xl">
|
||||
<img src="{{ asset('img/assets/accommodation-1.jpg') }}" alt="Partner success visualization"
|
||||
class="w-full h-48 object-cover" />
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent flex items-end">
|
||||
<div class="p-6 text-white">
|
||||
<div class="text-2xl font-bold mb-1">500+</div>
|
||||
<p class="text-sm opacity-90">Erfolgreiche Partner</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<section class="section-dark section-padding">
|
||||
<div class="container-narrow text-center">
|
||||
<div class="spacing-section">
|
||||
<h2 class="text-5xl lg:text-6xl font-light text-[hsl(var(--dark-text))] leading-tight">
|
||||
Wachsen Sie <br />
|
||||
<span class="text-secondary">mit uns</span>
|
||||
</h2>
|
||||
|
||||
<div class="w-16 h-px bg-secondary mx-auto"></div>
|
||||
|
||||
<p class="text-large text-dark-muted leading-relaxed max-w-2xl mx-auto">
|
||||
Werden Sie Teil des B2In-Partnernetzwerks und erschließen Sie neue
|
||||
Geschäftsmöglichkeiten durch innovative Konnektivitätslösungen.
|
||||
</p>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8 py-8">
|
||||
@foreach($this->stats as $stat)
|
||||
<div class="text-center space-y-3">
|
||||
<div class="text-4xl font-light text-secondary">{{ $stat['number'] }}</div>
|
||||
<p class="text-dark-muted text-sm">{{ $stat['label'] }}</p>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="spacing-content">
|
||||
<a href="/contact" class="btn-accent px-12 py-6 rounded-2xl text-lg">
|
||||
Werden Sie B2In Partner
|
||||
</a>
|
||||
|
||||
<p class="text-dark-muted text-sm">
|
||||
Entdecken Sie die Vorteile einer strategischen Partnerschaft mit B2In
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
<section class="min-h-screen flex items-center relative overflow-hidden">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-hero-container rounded-[20px] w-[95%]">
|
||||
<div class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8">
|
||||
<h1 class="text-hero">
|
||||
Wachsen Sie mit uns.<br />
|
||||
Werden Sie <span class="text-secondary">B2In Partner</span>.
|
||||
</h1>
|
||||
|
||||
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
|
||||
Werden Sie Teil des B2In Ecosystems und profitieren Sie von innovativen
|
||||
Geschäftsmodellen, die nachhaltiges Wachstum und langfristigen Erfolg ermöglichen.
|
||||
Gemeinsam gestalten wir die Zukunft der Immobilienbranche.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
@foreach ($this->partnerTypes as $partner)
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center">
|
||||
@if ($partner['icon'] === 'trending-up')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
|
||||
</svg>
|
||||
@elseif($partner['icon'] === 'globe')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
@elseif($partner['icon'] === 'handshake')
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-semibold text-foreground">{{ $partner['title'] }}</p>
|
||||
<p class="text-sm text-muted-foreground">{{ $partner['description'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="card-elevated rounded-3xl p-12 bg-background/80 backdrop-blur-sm">
|
||||
<div class="space-y-8">
|
||||
<!-- Central Partnership Hub -->
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-24 h-24 mx-auto rounded-full bg-primary flex items-center justify-center mb-4">
|
||||
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-foreground">Partner Network</h3>
|
||||
<p class="text-sm text-muted-foreground">Werden Sie Teil unseres Ecosystems</p>
|
||||
</div>
|
||||
|
||||
<!-- Partner Types -->
|
||||
<div class="grid grid-cols-2 gap-8">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">Makler</p>
|
||||
<p class="text-xs text-muted-foreground">Lifetime-Modell</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">Lieferanten</p>
|
||||
<p class="text-xs text-muted-foreground">Global Markets</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 1.657-2.657 1.657-2.657A8 8 0 0118.657 17.657zM12 12l1 1" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">Erfolg</p>
|
||||
<p class="text-xs text-muted-foreground">Messbare Ziele</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
|
||||
<svg class="w-8 h-8 text-accent-foreground" fill="none" stroke="currentColor"
|
||||
viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="font-medium text-sm">Qualität</p>
|
||||
<p class="text-xs text-muted-foreground">Premium Standards</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue