Trying to work on new theme
This commit is contained in:
@@ -3,10 +3,47 @@
|
||||
/* Import Tailwind using PostCSS */
|
||||
@import "tailwindcss";
|
||||
|
||||
/* Import flash message styles */
|
||||
@import "components/flash";
|
||||
/* Import our custom theme */
|
||||
@import "theme";
|
||||
|
||||
/** Default text color */
|
||||
/* Import components */
|
||||
@import "components/hero";
|
||||
@import "components/flash";
|
||||
@import "components/footer";
|
||||
@import "components/party-finder";
|
||||
|
||||
/* Base styles */
|
||||
body {
|
||||
color: #555555;
|
||||
font-family: var(--font-sans);
|
||||
line-height: 1.6;
|
||||
color: var(--color-neutral-900);
|
||||
background: var(--color-neutral-50);
|
||||
}
|
||||
|
||||
/* App wrapper */
|
||||
.app-wrapper {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Main content */
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
background: var(--color-neutral-800);
|
||||
color: var(--color-neutral-300);
|
||||
}
|
||||
|
||||
/* Flash messages */
|
||||
.flash {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Yield content */
|
||||
.yield {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
82
app/assets/stylesheets/components/footer.css
Normal file
82
app/assets/stylesheets/components/footer.css
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
.footer {
|
||||
background: var(--color-neutral-800);
|
||||
color: var(--color-neutral-300);
|
||||
padding: var(--space-8) 0 var(--space-4);
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
display: grid;
|
||||
gap: var(--space-6);
|
||||
margin-bottom: var(--space-6);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.footer-content {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.footer-content {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.footer-section h3 {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 700;
|
||||
margin-bottom: var(--space-3);
|
||||
color: white;
|
||||
font-size: var(--text-lg);
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.footer-links li {
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.footer-links a {
|
||||
color: var(--color-neutral-400);
|
||||
text-decoration: none;
|
||||
transition: color var(--duration-normal);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: var(--color-accent-400);
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
border-top: 1px solid var(--color-neutral-700);
|
||||
padding-top: var(--space-4);
|
||||
text-align: center;
|
||||
color: var(--color-neutral-400);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero {
|
||||
padding: var(--space-8) 0 var(--space-6);
|
||||
}
|
||||
|
||||
.cta-group {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hero-stats {
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
238
app/assets/stylesheets/components/hero.css
Normal file
238
app/assets/stylesheets/components/hero.css
Normal file
@@ -0,0 +1,238 @@
|
||||
.hero {
|
||||
background: linear-gradient(135deg,
|
||||
rgba(168, 85, 247, 0.08) 0%,
|
||||
rgba(236, 72, 153, 0.08) 50%,
|
||||
rgba(168, 85, 247, 0.08) 100%);
|
||||
padding: var(--space-12) 0 var(--space-8);
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background:
|
||||
radial-gradient(circle at 20% 80%, rgba(168, 85, 247, 0.1) 0%, transparent 50%),
|
||||
radial-gradient(circle at 80% 20%, rgba(236, 72, 153, 0.1) 0%, transparent 50%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(2rem, 5vw, 3.5rem);
|
||||
font-weight: 900;
|
||||
margin-bottom: var(--space-4);
|
||||
background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-accent-500) 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.hero .subtitle {
|
||||
font-size: var(--text-lg);
|
||||
color: var(--color-neutral-600);
|
||||
margin-bottom: var(--space-6);
|
||||
max-width: 700px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cta-group {
|
||||
display: flex;
|
||||
gap: var(--space-4);
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: var(--space-8);
|
||||
}
|
||||
|
||||
.hero-stats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: var(--space-6);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.hero-stat {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-stat-number {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-xl);
|
||||
font-weight: 800;
|
||||
color: var(--color-primary-600);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hero-stat-label {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--color-neutral-500);
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: var(--space-12) 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
text-align: center;
|
||||
margin-bottom: var(--space-8);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(1.5rem, 3vw, 2.5rem);
|
||||
font-weight: 800;
|
||||
margin-bottom: var(--space-3);
|
||||
color: var(--color-neutral-900);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.section-description {
|
||||
font-size: var(--text-lg);
|
||||
color: var(--color-neutral-600);
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.features-section {
|
||||
background: linear-gradient(135deg, var(--color-primary-50) 0%, var(--color-accent-50) 100%);
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
gap: var(--space-6);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.features-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.features-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background: white;
|
||||
padding: var(--space-6);
|
||||
border-radius: var(--radius-xl);
|
||||
text-align: center;
|
||||
box-shadow: var(--shadow-sm);
|
||||
border: 1px solid var(--color-neutral-200);
|
||||
transition: all var(--duration-normal) var(--ease-out);
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
background: linear-gradient(135deg, var(--color-primary-500) 0%, var(--color-accent-400) 100%);
|
||||
color: white;
|
||||
border-radius: var(--radius-xl);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto var(--space-3);
|
||||
box-shadow: var(--shadow-purple-sm);
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 700;
|
||||
margin-bottom: var(--space-2);
|
||||
color: var(--color-neutral-900);
|
||||
}
|
||||
|
||||
.feature-description {
|
||||
color: var(--color-neutral-600);
|
||||
line-height: 1.6;
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.stats-section {
|
||||
background: var(--color-neutral-900);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
gap: var(--space-6);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
padding: var(--space-4);
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(1.5rem, 4vw, 2.5rem);
|
||||
font-weight: 900;
|
||||
color: var(--color-accent-400);
|
||||
display: block;
|
||||
margin-bottom: var(--space-1);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: var(--color-neutral-300);
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-accent-500) 100%);
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: var(--space-12) 0;
|
||||
}
|
||||
|
||||
.cta-content h2 {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(1.5rem, 3vw, 2rem);
|
||||
font-weight: 800;
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.cta-content p {
|
||||
font-size: var(--text-lg);
|
||||
margin-bottom: var(--space-6);
|
||||
opacity: 0.9;
|
||||
}
|
||||
210
app/assets/stylesheets/components/party-finder.css
Normal file
210
app/assets/stylesheets/components/party-finder.css
Normal file
@@ -0,0 +1,210 @@
|
||||
.party-finder {
|
||||
background: white;
|
||||
border-radius: var(--radius-2xl);
|
||||
box-shadow: var(--shadow-2xl);
|
||||
padding: var(--space-8);
|
||||
margin: var(--space-12) auto;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
border: 1px solid var(--color-neutral-200);
|
||||
backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
.finder-header {
|
||||
text-align: center;
|
||||
margin-bottom: var(--space-8);
|
||||
}
|
||||
|
||||
.finder-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-2xl);
|
||||
font-weight: 800;
|
||||
margin-bottom: var(--space-2);
|
||||
color: var(--color-neutral-900);
|
||||
}
|
||||
|
||||
.finder-subtitle {
|
||||
color: var(--color-neutral-600);
|
||||
font-size: var(--text-lg);
|
||||
}
|
||||
|
||||
.finder-form {
|
||||
display: grid;
|
||||
gap: var(--space-6);
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.finder-form {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.finder-form {
|
||||
grid-template-columns: repeat(4, 1fr) auto;
|
||||
align-items: end;
|
||||
}
|
||||
}
|
||||
|
||||
.finder-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.finder-label {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 700;
|
||||
color: var(--color-neutral-700);
|
||||
margin-bottom: var(--space-2);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.finder-input,
|
||||
.finder-select {
|
||||
background: var(--color-neutral-50);
|
||||
border: 2px solid var(--color-neutral-200);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--space-4);
|
||||
font-size: var(--text-base);
|
||||
font-weight: 500;
|
||||
color: var(--color-neutral-900);
|
||||
transition: all var(--duration-normal) var(--ease-out);
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.finder-input:focus,
|
||||
.finder-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary-500);
|
||||
background: white;
|
||||
box-shadow: 0 0 0 4px rgb(168 85 247 / 0.1);
|
||||
}
|
||||
|
||||
.finder-input::placeholder {
|
||||
color: var(--color-neutral-500);
|
||||
}
|
||||
|
||||
.finder-select {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right 12px center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
padding-right: var(--space-12);
|
||||
}
|
||||
|
||||
.price-range {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.price-range-label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.price-value {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 800;
|
||||
color: var(--color-primary-600);
|
||||
}
|
||||
|
||||
.price-slider {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--color-neutral-200);
|
||||
outline: none;
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.price-slider::-webkit-slider-thumb {
|
||||
appearance: none;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: var(--radius-full);
|
||||
background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-accent-500) 100%);
|
||||
cursor: pointer;
|
||||
border: 3px solid white;
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.price-slider::-moz-range-thumb {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: var(--radius-full);
|
||||
background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-accent-500) 100%);
|
||||
cursor: pointer;
|
||||
border: 3px solid white;
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.finder-search-btn {
|
||||
background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-accent-500) 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--space-5) var(--space-8);
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 800;
|
||||
cursor: pointer;
|
||||
transition: all var(--duration-normal) var(--ease-out);
|
||||
box-shadow: var(--shadow-purple-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.finder-search-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-purple-lg);
|
||||
}
|
||||
|
||||
.finder-search-btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.party-finder {
|
||||
margin: var(--space-8) auto;
|
||||
padding: var(--space-6);
|
||||
}
|
||||
|
||||
.finder-form {
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.finder-search-btn {
|
||||
justify-content: center;
|
||||
padding: var(--space-4) var(--space-6);
|
||||
font-size: var(--text-base);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enhanced animations */
|
||||
.animate-fadeInUp {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transition: all 0.6s var(--ease-out);
|
||||
}
|
||||
|
||||
.animate-fadeInUp.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Loading spinner animation */
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
@@ -1,161 +1,795 @@
|
||||
/* Theme Rules from docs/theme-rules.md - Light Theme Only */
|
||||
|
||||
/* Custom properties for the design system */
|
||||
:root {
|
||||
/* Primary - Purple gradient system */
|
||||
--color-primary-50: #faf5ff;
|
||||
--color-primary-100: #f3e8ff;
|
||||
--color-primary-200: #e9d5ff;
|
||||
--color-primary-300: #d8b4fe;
|
||||
--color-primary-400: #c084fc;
|
||||
--color-primary-500: #a855f7;
|
||||
--color-primary-600: #9333ea;
|
||||
--color-primary-700: #7e22ce;
|
||||
--color-primary-800: #6b21a8;
|
||||
--color-primary-900: #581c87;
|
||||
/* Colors */
|
||||
--color-primary-50: #f5f3ff;
|
||||
--color-primary-100: #ede9fe;
|
||||
--color-primary-200: #ddd6fe;
|
||||
--color-primary-300: #c4b5fd;
|
||||
--color-primary-400: #a78bfa;
|
||||
--color-primary-500: #8b5cf6;
|
||||
--color-primary-600: #7c3aed;
|
||||
--color-primary-700: #6d28d9;
|
||||
--color-primary-800: #5b21b6;
|
||||
--color-primary-900: #4c1d95;
|
||||
|
||||
/* Accent - Pink gradient */
|
||||
--color-accent-400: #f472b6;
|
||||
--color-accent-500: #ec4899;
|
||||
--color-accent-600: #db2777;
|
||||
--color-accent-50: #fdf2f8;
|
||||
--color-accent-100: #fce7f3;
|
||||
--color-accent-200: #fbcfe8;
|
||||
--color-accent-300: #f9a8d4;
|
||||
--color-accent-400: #f472b6;
|
||||
--color-accent-500: #ec4899;
|
||||
--color-accent-600: #db2777;
|
||||
--color-accent-700: #be185d;
|
||||
--color-accent-800: #9d174d;
|
||||
--color-accent-900: #831843;
|
||||
|
||||
/* Neutral - Slate system */
|
||||
--color-neutral-50: #f8fafc;
|
||||
--color-neutral-100: #f1f5f9;
|
||||
--color-neutral-200: #e2e8f0;
|
||||
--color-neutral-300: #cbd5e1;
|
||||
--color-neutral-400: #94a3b8;
|
||||
--color-neutral-500: #64748b;
|
||||
--color-neutral-600: #475569;
|
||||
--color-neutral-700: #334155;
|
||||
--color-neutral-800: #1e293b;
|
||||
--color-neutral-900: #0f172a;
|
||||
--color-neutral-50: #fafafa;
|
||||
--color-neutral-100: #f5f5f5;
|
||||
--color-neutral-200: #e5e5e5;
|
||||
--color-neutral-300: #d4d4d4;
|
||||
--color-neutral-400: #a3a3a3;
|
||||
--color-neutral-500: #737373;
|
||||
--color-neutral-600: #525252;
|
||||
--color-neutral-700: #404040;
|
||||
--color-neutral-800: #262626;
|
||||
--color-neutral-900: #171717;
|
||||
|
||||
/* Font families */
|
||||
--font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--color-success: #10b981;
|
||||
--color-success-light: #d1fae5;
|
||||
--color-success-dark: #047857;
|
||||
|
||||
/* Spacing scale */
|
||||
--space-1: 0.25rem; /* 4px */
|
||||
--space-2: 0.5rem; /* 8px */
|
||||
--space-3: 0.75rem; /* 12px */
|
||||
--space-4: 1rem; /* 16px */
|
||||
--space-5: 1.25rem; /* 20px */
|
||||
--space-6: 1.5rem; /* 24px */
|
||||
--space-8: 2rem; /* 32px */
|
||||
--space-10: 2.5rem; /* 40px */
|
||||
--space-12: 3rem; /* 48px */
|
||||
--color-warning: #f59e0b;
|
||||
--color-warning-light: #fef3c7;
|
||||
--color-warning-dark: #b45309;
|
||||
|
||||
--color-danger: #ef4444;
|
||||
--color-danger-light: #fee2e2;
|
||||
--color-danger-dark: #b91c1c;
|
||||
|
||||
/* Typography */
|
||||
--font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
--font-display: 'Outfit', var(--font-sans);
|
||||
|
||||
--text-xs: 0.75rem; /* 12px */
|
||||
--text-sm: 0.875rem; /* 14px */
|
||||
--text-base: 1rem; /* 16px */
|
||||
--text-lg: 1.125rem; /* 18px */
|
||||
--text-xl: 1.25rem; /* 20px */
|
||||
--text-2xl: 1.5rem; /* 24px */
|
||||
--text-3xl: 1.875rem; /* 30px */
|
||||
--text-4xl: 2.25rem; /* 36px */
|
||||
--text-5xl: 3rem; /* 48px */
|
||||
|
||||
/* Spacing */
|
||||
--space-1: 0.25rem; /* 4px */
|
||||
--space-2: 0.5rem; /* 8px */
|
||||
--space-3: 0.75rem; /* 12px */
|
||||
--space-4: 1rem; /* 16px */
|
||||
--space-5: 1.25rem; /* 20px */
|
||||
--space-6: 1.5rem; /* 24px */
|
||||
--space-8: 2rem; /* 32px */
|
||||
--space-10: 2.5rem; /* 40px */
|
||||
--space-12: 3rem; /* 48px */
|
||||
--space-16: 4rem; /* 64px */
|
||||
--space-20: 5rem; /* 80px */
|
||||
|
||||
/* Radius */
|
||||
--radius: 0.25rem; /* 4px */
|
||||
--radius-md: 0.5rem; /* 8px */
|
||||
--radius-lg: 0.75rem; /* 12px */
|
||||
--radius-xl: 1rem; /* 16px */
|
||||
--radius-2xl: 1.5rem; /* 24px */
|
||||
--radius-full: 9999px;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||
|
||||
--shadow-purple-sm: 0 1px 3px 0 rgba(168, 85, 247, 0.1), 0 1px 2px 0 rgba(168, 85, 247, 0.06);
|
||||
--shadow-purple-md: 0 4px 6px -1px rgba(168, 85, 247, 0.1), 0 2px 4px -1px rgba(168, 85, 247, 0.06);
|
||||
--shadow-purple-lg: 0 10px 15px -3px rgba(168, 85, 247, 0.1), 0 4px 6px -2px rgba(168, 85, 247, 0.05);
|
||||
|
||||
/* Transitions */
|
||||
--duration-fast: 150ms;
|
||||
--duration-normal: 300ms;
|
||||
--duration-slow: 500ms;
|
||||
|
||||
--ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
|
||||
/* Base styles */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
line-height: 1.6;
|
||||
color: var(--color-neutral-900);
|
||||
background: var(--color-neutral-50);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--space-4);
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--text-4xl);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: var(--text-3xl);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: var(--text-2xl);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: var(--text-xl);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-2);
|
||||
font-family: var(--font-display);
|
||||
font-weight: 700;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
border-radius: var(--radius-lg);
|
||||
transition: all var(--duration-normal) var(--ease-out);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: var(--space-2) var(--space-4);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.btn-md {
|
||||
padding: var(--space-3) var(--space-6);
|
||||
font-size: var(--text-base);
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
padding: var(--space-4) var(--space-8);
|
||||
font-size: var(--text-lg);
|
||||
}
|
||||
|
||||
/* Button components */
|
||||
.btn-primary {
|
||||
@apply bg-gradient-to-r from-purple-600 to-pink-600 text-white font-medium py-2 px-4 rounded-lg shadow-sm hover:shadow-md transition-all duration-200;
|
||||
background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-accent-500) 100%);
|
||||
color: white;
|
||||
box-shadow: var(--shadow-purple-md);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-purple-lg);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply bg-white text-purple-600 border border-purple-200 font-medium py-2 px-4 rounded-lg hover:bg-purple-50 transition-colors duration-200;
|
||||
background: var(--color-neutral-800);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-destructive {
|
||||
@apply bg-red-600 text-white font-medium py-2 px-4 rounded-lg shadow-sm hover:bg-red-700 transition-colors duration-200;
|
||||
.btn-secondary:hover {
|
||||
background: var(--color-neutral-900);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Card components */
|
||||
.card {
|
||||
@apply bg-white rounded-lg shadow-sm border border-neutral-200 p-6 hover:shadow-md transition-shadow duration-200;
|
||||
.btn-outline {
|
||||
background: transparent;
|
||||
border: 2px solid var(--color-primary-600);
|
||||
color: var(--color-primary-600);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
@apply pb-4 border-b border-neutral-200 mb-4;
|
||||
.btn-outline:hover {
|
||||
background: var(--color-primary-50);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.card-body {
|
||||
@apply space-y-4;
|
||||
.btn-ghost {
|
||||
background: transparent;
|
||||
color: var(--color-neutral-700);
|
||||
}
|
||||
|
||||
/* Form components */
|
||||
.form-input {
|
||||
@apply block w-full rounded-md border-neutral-300 shadow-sm focus:border-purple-500 focus:ring-purple-500 sm:text-sm;
|
||||
.btn-ghost:hover {
|
||||
background: var(--color-neutral-100);
|
||||
}
|
||||
|
||||
/* Form elements */
|
||||
.form-group {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.form-label {
|
||||
@apply block text-sm font-medium text-neutral-700 mb-1;
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 700;
|
||||
color: var(--color-neutral-700);
|
||||
margin-bottom: var(--space-2);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
background: var(--color-neutral-50);
|
||||
border: 2px solid var(--color-neutral-200);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--space-4);
|
||||
font-size: var(--text-base);
|
||||
font-weight: 500;
|
||||
color: var(--color-neutral-900);
|
||||
transition: all var(--duration-normal) var(--ease-out);
|
||||
font-family: var(--font-sans);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-select:focus,
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary-500);
|
||||
background: white;
|
||||
box-shadow: 0 0 0 4px rgba(168, 85, 247, 0.1);
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: var(--color-neutral-500);
|
||||
}
|
||||
|
||||
.form-select {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right 12px center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
padding-right: var(--space-12);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
min-height: 100px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
@apply text-sm text-red-600 mt-1;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
.nav-link {
|
||||
@apply text-neutral-600 hover:text-purple-600 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200;
|
||||
}
|
||||
|
||||
.nav-link-active {
|
||||
@apply text-purple-600 bg-purple-50;
|
||||
}
|
||||
|
||||
/* Layout utilities */
|
||||
.container {
|
||||
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
|
||||
}
|
||||
|
||||
.grid-responsive {
|
||||
@apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6;
|
||||
}
|
||||
|
||||
.grid-cards {
|
||||
@apply grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6;
|
||||
}
|
||||
|
||||
/* Animation utilities */
|
||||
.hover-lift {
|
||||
@apply transition-transform duration-200 hover:-translate-y-1;
|
||||
}
|
||||
|
||||
.hover-glow {
|
||||
@apply transition-all duration-200 hover:shadow-lg hover:shadow-purple-500/25;
|
||||
color: var(--color-danger);
|
||||
font-size: var(--text-sm);
|
||||
margin-top: var(--space-1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.focus-ring {
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2;
|
||||
transition: all var(--duration-normal) var(--ease-out);
|
||||
}
|
||||
|
||||
.transition-fast {
|
||||
@apply transition-all duration-150 ease-in-out;
|
||||
.focus-ring:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary-500);
|
||||
background: white;
|
||||
box-shadow: 0 0 0 4px rgba(168, 85, 247, 0.1);
|
||||
}
|
||||
|
||||
.transition-normal {
|
||||
@apply transition-all duration-200 ease-in-out;
|
||||
/* Badges */
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: var(--space-1) var(--space-3);
|
||||
border-radius: var(--radius-full);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.transition-slow {
|
||||
@apply transition-all duration-300 ease-in-out;
|
||||
.badge-available {
|
||||
background: var(--color-success-light);
|
||||
color: var(--color-success-dark);
|
||||
border: 1px solid var(--color-success);
|
||||
}
|
||||
|
||||
/* State utilities */
|
||||
.disabled {
|
||||
@apply opacity-50 cursor-not-allowed;
|
||||
.badge-limited {
|
||||
background: var(--color-warning-light);
|
||||
color: var(--color-warning-dark);
|
||||
border: 1px solid var(--color-warning);
|
||||
}
|
||||
|
||||
.animate-pulse-subtle {
|
||||
@apply animate-pulse;
|
||||
animation-duration: 3s;
|
||||
.badge-sold-out {
|
||||
background: var(--color-danger-light);
|
||||
color: var(--color-danger-dark);
|
||||
border: 1px solid var(--color-danger);
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
@apply animate-in fade-in-0 duration-500;
|
||||
.badge-featured {
|
||||
background: var(--color-accent-100);
|
||||
color: var(--color-accent-700);
|
||||
border: 1px solid var(--color-accent-300);
|
||||
}
|
||||
|
||||
/* Accessibility utilities */
|
||||
.focus-visible {
|
||||
@apply focus:outline-none focus-visible:ring-2 focus-visible:ring-purple-500 focus-visible:ring-offset-2;
|
||||
.badge-vip {
|
||||
background: var(--color-primary-100);
|
||||
color: var(--color-primary-800);
|
||||
border: 1px solid var(--color-primary-300);
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
@apply text-neutral-900;
|
||||
/* Cards */
|
||||
.card {
|
||||
background: white;
|
||||
border-radius: var(--radius-xl);
|
||||
padding: var(--space-6);
|
||||
border: 1px solid var(--color-neutral-200);
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: all var(--duration-slow) var(--ease-out);
|
||||
}
|
||||
|
||||
.card.hover-lift:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: var(--shadow-2xl);
|
||||
border-color: var(--color-primary-200);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.card-body {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.event-card {
|
||||
background: white;
|
||||
border-radius: var(--radius-xl);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-md);
|
||||
transition: all var(--duration-slow) var(--ease-out);
|
||||
border: 1px solid var(--color-neutral-200);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.event-card.hover-glow:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: var(--shadow-2xl);
|
||||
border-color: var(--color-primary-200);
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
.nav {
|
||||
background: white;
|
||||
box-shadow: var(--shadow-sm);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: var(--color-neutral-700);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
padding: var(--space-3) var(--space-2);
|
||||
border-radius: var(--radius);
|
||||
transition: all var(--duration-normal);
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
color: var(--color-primary-600);
|
||||
background: var(--color-primary-50);
|
||||
}
|
||||
|
||||
/* Search box */
|
||||
.search-box {
|
||||
position: relative;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
padding-left: var(--space-12);
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
position: absolute;
|
||||
left: var(--space-4);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--color-neutral-400);
|
||||
}
|
||||
|
||||
/* Price tags */
|
||||
.price-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
font-family: var(--font-display);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.price-tag-sm {
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.price-tag-md {
|
||||
font-size: var(--text-lg);
|
||||
}
|
||||
|
||||
.price-tag-lg {
|
||||
font-size: var(--text-2xl);
|
||||
}
|
||||
|
||||
/* Avatars */
|
||||
.avatar-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--color-primary-100);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
color: var(--color-primary-600);
|
||||
border: 2px solid white;
|
||||
box-shadow: var(--shadow-sm);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
|
||||
.avatar-status {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: var(--radius-full);
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.status-online { background: var(--color-success); }
|
||||
.status-offline { background: var(--color-neutral-400); }
|
||||
.status-busy { background: var(--color-danger); }
|
||||
|
||||
/* Progress bars */
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background: var(--color-neutral-200);
|
||||
border-radius: var(--radius-full);
|
||||
overflow: hidden;
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, var(--color-primary-500) 0%, var(--color-accent-400) 100%);
|
||||
border-radius: var(--radius-full);
|
||||
transition: width var(--duration-slow) var(--ease-out);
|
||||
}
|
||||
|
||||
/* Rating stars */
|
||||
.rating {
|
||||
display: flex;
|
||||
gap: var(--space-1);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rating-star {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.rating-star.filled {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.rating-star.empty {
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
/* Notifications */
|
||||
.notification {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-3);
|
||||
padding: var(--space-4);
|
||||
border-radius: var(--radius-lg);
|
||||
margin-bottom: var(--space-3);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.notification-success {
|
||||
background: var(--color-success-light);
|
||||
color: var(--color-success-dark);
|
||||
border: 1px solid var(--color-success);
|
||||
}
|
||||
|
||||
.notification-warning {
|
||||
background: var(--color-warning-light);
|
||||
color: var(--color-warning-dark);
|
||||
border: 1px solid var(--color-warning);
|
||||
}
|
||||
|
||||
.notification-error {
|
||||
background: var(--color-danger-light);
|
||||
color: var(--color-danger-dark);
|
||||
border: 1px solid var(--color-danger);
|
||||
}
|
||||
|
||||
.notification-info {
|
||||
background: var(--color-primary-50);
|
||||
color: var(--color-primary-800);
|
||||
border: 1px solid var(--color-primary-200);
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
.tabs {
|
||||
border-bottom: 1px solid var(--color-neutral-200);
|
||||
margin-bottom: var(--space-6);
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
display: flex;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: var(--space-3) var(--space-4);
|
||||
font-weight: 500;
|
||||
color: var(--color-neutral-600);
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: all var(--duration-normal);
|
||||
font-family: var(--font-display);
|
||||
}
|
||||
|
||||
.tab-button:hover {
|
||||
color: var(--color-primary-600);
|
||||
background: var(--color-primary-50);
|
||||
border-radius: var(--radius-md) var(--radius-md) 0 0;
|
||||
}
|
||||
|
||||
.tab-button.active {
|
||||
color: var(--color-primary-600);
|
||||
border-bottom-color: var(--color-primary-600);
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
padding: var(--space-4) 0;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Tooltips */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip-content {
|
||||
position: absolute;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--color-neutral-900);
|
||||
color: white;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
border-radius: var(--radius);
|
||||
font-size: var(--text-sm);
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all var(--duration-normal);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.tooltip-content::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border: 5px solid transparent;
|
||||
border-top-color: var(--color-neutral-900);
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltip-content {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Loading states */
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid var(--color-neutral-200);
|
||||
border-top-color: var(--color-primary-600);
|
||||
border-radius: var(--radius-full);
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
.loading-dots {
|
||||
display: flex;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.loading-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: var(--color-primary-600);
|
||||
border-radius: var(--radius-full);
|
||||
animation: bounce 1.4s infinite both;
|
||||
}
|
||||
|
||||
.loading-dot:nth-child(2) { animation-delay: 0.2s; }
|
||||
.loading-dot:nth-child(3) { animation-delay: 0.4s; }
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%, 80%, 100% { transform: scale(0); }
|
||||
40% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* Breadcrumbs */
|
||||
.breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.breadcrumb-item {
|
||||
color: var(--color-neutral-600);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.breadcrumb-item:hover {
|
||||
color: var(--color-primary-600);
|
||||
}
|
||||
|
||||
.breadcrumb-item.current {
|
||||
color: var(--color-neutral-900);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.breadcrumb-separator {
|
||||
color: var(--color-neutral-400);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 0 var(--space-3);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--text-3xl);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: var(--text-2xl);
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
padding: var(--space-3) var(--space-6);
|
||||
font-size: var(--text-base);
|
||||
}
|
||||
|
||||
.btn-md {
|
||||
padding: var(--space-2) var(--space-4);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
padding: var(--space-3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional styles for enhanced Aperonight design */
|
||||
.event-card.hover-glow:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: var(--shadow-2xl);
|
||||
border-color: var(--color-primary-200);
|
||||
}
|
||||
|
||||
.price-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
font-family: var(--font-display);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.price-tag-sm {
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.price-tag-md {
|
||||
font-size: var(--text-lg);
|
||||
}
|
||||
|
||||
.price-tag-lg {
|
||||
font-size: var(--text-2xl);
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
padding-left: var(--space-12);
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
position: absolute;
|
||||
left: var(--space-4);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--color-neutral-400);
|
||||
}
|
||||
|
||||
.text-secondary {
|
||||
@apply text-neutral-600;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ class PagesController < ApplicationController
|
||||
# Homepage showing featured parties
|
||||
def home
|
||||
# @parties = Party.published.featured.limit(3)
|
||||
@parties = Party.where(state: :published).order(created_at: :desc)
|
||||
# @parties = Party.where(state: :published).order(created_at: :desc)
|
||||
|
||||
if user_signed_in?
|
||||
return redirect_to(dashboard_path)
|
||||
|
||||
@@ -1,83 +1,41 @@
|
||||
<footer class="py-10 bg-neutral-100 text-neutral-600 border-t border-neutral-200">
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<!-- Column 1: About -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-lg font-semibold text-purple-500">À propos</h3>
|
||||
<p class="text-sm text-neutral-600 leading-relaxed">
|
||||
Aperonight est la plateforme qui connecte les amateurs de soirées aux meilleurs événements de leur ville.
|
||||
</p>
|
||||
<div class="flex space-x-4">
|
||||
<a href="#" class="text-neutral-500 hover:text-purple-500 transition-colors">
|
||||
<span class="sr-only">Facebook</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 20.128 22 15.991 22 12z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="#" class="text-neutral-500 hover:text-purple-500 transition-colors">
|
||||
<span class="sr-only">Instagram</span>
|
||||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.024.06 1.378.06 3.808s-.012 2.784-.06 3.808c-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.024.048-1.378.06-3.808.06s-2.784-.012-3.808-.06c-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.048-1.024-.06-1.378-.06-3.808s.012-2.784.06-3.808c.049-1.064.218-1.791.465-2.427A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Column 2: Quick Links -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-lg font-semibold text-purple-500">Liens rapides</h3>
|
||||
<ul class="space-y-2 text-sm">
|
||||
<li><%= link_to "Accueil", "/", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
<li><%= link_to "Événements", "/events", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
<li><%= link_to "Organisateurs", "/organizers", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
<li><%= link_to "Support", "/support", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Column 3: Legal -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-lg font-semibold text-purple-500">Légal</h3>
|
||||
<ul class="space-y-2 text-sm">
|
||||
<li><%= link_to "Conditions d'utilisation", "/terms", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
<li><%= link_to "Politique de confidentialité", "/privacy", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
<li><%= link_to "CGV", "/cgv", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
<li><%= link_to "Mentions légales", "/legal", class: "text-neutral-600 hover:text-purple-500 transition-colors" %></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Column 4: Contact -->
|
||||
<div class="space-y-4">
|
||||
<h3 class="text-lg font-semibold text-purple-500">Contact</h3>
|
||||
<address class="not-italic text-sm text-neutral-600 space-y-2">
|
||||
<p>
|
||||
<span class="block font-medium">Email:</span>
|
||||
<a href="mailto:hello@aperonight.com" class="text-purple-500 hover:text-purple-400 transition-colors">
|
||||
hello@aperonight.com
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<span class="block font-medium">Support:</span>
|
||||
<a href="mailto:support@aperonight.com" class="text-purple-500 hover:text-purple-400 transition-colors">
|
||||
support@aperonight.com
|
||||
</a>
|
||||
</p>
|
||||
</address>
|
||||
<p class="text-xs text-neutral-500">
|
||||
Réponse sous 24h en semaine
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Bar -->
|
||||
<div class="mt-12 pt-8 border-t border-neutral-200">
|
||||
<div class="flex flex-col md:flex-row justify-between items-center">
|
||||
<p class="text-sm text-neutral-500">
|
||||
© <%= Time.current.year %> Aperonight. Tous droits réservés.
|
||||
</p>
|
||||
<p class="text-xs text-neutral-400 mt-2 md:mt-0">
|
||||
Fait avec 💜 pour la communauté
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h3>Events</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">Find Events</a></li>
|
||||
<li><a href="#">Host an Event</a></li>
|
||||
<li><a href="#">Event Categories</a></li>
|
||||
<li><a href="#">Premium Events</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
<div class="footer-section">
|
||||
<h3>Community</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">Join Us</a></li>
|
||||
<li><a href="#">Member Benefits</a></li>
|
||||
<li><a href="#">Success Stories</a></li>
|
||||
<li><a href="#">Ambassador Program</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h3>Support</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">Help Center</a></li>
|
||||
<li><a href="#">Contact Us</a></li>
|
||||
<li><a href="#">Safety Guidelines</a></li>
|
||||
<li><a href="#">Cancellation Policy</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h3>Company</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">About Aperonight</a></li>
|
||||
<li><a href="#">Careers</a></li>
|
||||
<li><a href="#">Press & Media</a></li>
|
||||
<li><a href="#">Partner With Us</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2024 Aperonight. All rights reserved. • <a href="#" style="color: var(--color-accent-400);">Privacy Policy</a> • <a href="#" style="color: var(--color-accent-400);">Terms of Service</a></p>
|
||||
</div>
|
||||
@@ -1,140 +1,17 @@
|
||||
<header class="shadow-sm border-b border-neutral-700">
|
||||
<div class="bg-neutral-900">
|
||||
<nav x-data="{ open: false }" class="bg-neutral-800 border-b border-neutral-700">
|
||||
<!-- Primary Navigation Menu -->
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between h-16">
|
||||
<div class="flex">
|
||||
<!-- Logo -->
|
||||
<div class="shrink-0 flex items-center">
|
||||
<%= link_to Rails.application.config.app_name, current_user ? "/dashboard" : "/", class: "text-xl font-bold text-white" %>
|
||||
</div>
|
||||
<!-- Navigation Links -->
|
||||
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex items-center">
|
||||
<%= link_to t('header.parties'), parties_path,
|
||||
class: "text-neutral-100 hover:text-primary-200 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200"
|
||||
%>
|
||||
<%= link_to t('header.concerts'), "#" ,
|
||||
class: "text-neutral-100 hover:text-primary-200 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200"
|
||||
%>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Authentication Links -->
|
||||
<% if user_signed_in? %>
|
||||
<!-- Settings Dropdown -->
|
||||
<div class="hidden sm:flex sm:items-center sm:ms-6">
|
||||
<div class="relative" x-data="{ open: false }" @click.outside="open = false" @close.stop="open = false">
|
||||
<div @click="open = ! open">
|
||||
<button
|
||||
class="bg-primary-700 text-white border border-primary-800 font-medium py-2 px-4 rounded-lg hover:bg-primary-800 transition-colors duration-200 focus-ring">
|
||||
<div>
|
||||
<%= current_user.email.length> 20 ? current_user.email[0,20] + "..." : current_user.email %>
|
||||
</div>
|
||||
<div class="ms-1">
|
||||
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div x-show="open" x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-75" x-transition:leave-start="opacity-100 scale-100"
|
||||
x-transition:leave-end="opacity-0 scale-95"
|
||||
class="absolute z-50 mt-2 w-48 rounded-md shadow-lg origin-top-right right-0" style="display: none;"
|
||||
@click="open = false">
|
||||
<div class="rounded-md ring-1 ring-primary-700 py-1 bg-primary-600">
|
||||
<%= link_to t('header.profile') , edit_user_registration_path,
|
||||
class: "block w-full px-4 py-2 text-start text-sm leading-5 text-neutral-100 hover:bg-primary-700" %>
|
||||
<%= link_to t('header.reservations') , "#" ,
|
||||
class: "block w-full px-4 py-2 text-start text-sm leading-5 text-neutral-100 hover:bg-primary-700" %>
|
||||
<%= link_to t('header.logout') , destroy_user_session_path, data: { controller: "logout" ,
|
||||
action: "click->logout#signOut" , logout_url_value: destroy_user_session_path, login_url_value:
|
||||
new_user_session_path, turbo: false },
|
||||
class: "block w-full px-4 py-2 text-start text-sm leading-5 text-neutral-100 hover:bg-primary-700" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<!-- Login/Register Links -->
|
||||
<div class="hidden sm:flex sm:items-center sm:ms-6 space-x-4 items-center">
|
||||
<%= link_to t('header.login') , new_user_session_path,
|
||||
class: "text-neutral-100 hover:text-primary-200 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200"
|
||||
%>
|
||||
<%= link_to t('header.register') , new_user_registration_path,
|
||||
class: "bg-primary-50 text-primary-600 font-medium py-2 px-4 rounded-lg shadow-sm hover:bg-primary-100 transition-all duration-200"
|
||||
%>
|
||||
</div>
|
||||
<% end %>
|
||||
<!-- Hamburger -->
|
||||
<div class="-me-2 flex items-center sm:hidden">
|
||||
<button @click="open = ! open"
|
||||
class="p-2 rounded-md text-neutral-300 hover:text-white hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
|
||||
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path :class="{ 'hidden': open, 'inline-flex': !open }" class="inline-flex" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
<path :class="{ 'hidden': !open, 'inline-flex': open }" class="hidden" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="nav">
|
||||
<div class="container">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; padding: var(--space-4) 0;">
|
||||
<div style="display: flex; align-items: center; gap: var(--space-3);">
|
||||
<div style="width: 40px; height: 40px; background: linear-gradient(135deg, var(--color-primary-600) 0%, var(--color-accent-500) 100%); border-radius: var(--radius-lg); display: flex; align-items: center; justify-content: center; color: white; font-weight: 800; font-family: var(--font-display); box-shadow: var(--shadow-purple-sm);">A</div>
|
||||
<%= link_to "Aperonight", root_path, class: "nav-link", style: "font-size: var(--text-xl); font-weight: 800; color: var(--color-neutral-900); font-family: var(--font-display);" %>
|
||||
</div>
|
||||
<!-- Responsive Navigation Menu -->
|
||||
<div :class="{ 'block': open, 'hidden': !open }" class="hidden sm:hidden">
|
||||
<div class="pt-2 pb-3 space-y-1 bg-primary-600">
|
||||
<%= link_to t('header.parties') , "#" ,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-neutral-100 hover:text-primary-200 hover:bg-primary-700"
|
||||
%>
|
||||
<%= link_to t('header.concerts') , "#" ,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-neutral-100 hover:text-primary-200 hover:bg-primary-700"
|
||||
%>
|
||||
</div>
|
||||
<!-- Responsive Settings Options -->
|
||||
<div class="pt-4 pb-1 border-t border-primary-700 bg-primary-600">
|
||||
<% if user_signed_in? %>
|
||||
<div class="px-4">
|
||||
<% if current_user.first_name %>
|
||||
<div class="font-medium text-base text-white">
|
||||
<%= current_user.first_name %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="font-medium text-base text-white">
|
||||
<%= current_user.email.length> 20 ? current_user.email[0,20] + "..." : current_user.email %>
|
||||
</div>
|
||||
<%# <div class="font-medium text-sm text-purple-200">
|
||||
<%= current_user.email.length> 20 ? current_user.email[0,20] + "..." : current_user.email %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="mt-3 space-y-1">
|
||||
<%= link_to t('header.profile') , edit_user_registration_path,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-neutral-100 hover:text-primary-200 hover:bg-primary-700"
|
||||
%>
|
||||
<%= link_to t('header.reservations') , "#" ,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-neutral-100 hover:text-primary-200 hover:bg-primary-700"
|
||||
%>
|
||||
|
||||
<%= link_to t('header.logout') , destroy_user_session_path, data: { controller: "logout" , action: "click->logout#signOut",
|
||||
logout_url_value: destroy_user_session_path, login_url_value: new_user_session_path, turbo: false },
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-neutral-100 hover:text-primary-200 hover:bg-primary-700"
|
||||
%>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="mt-3 space-y-1">
|
||||
<%= link_to t('header.register') , new_user_registration_path,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-neutral-100 hover:text-primary-200 hover:bg-primary-700"
|
||||
%>
|
||||
<%= link_to t('header.login') , new_user_session_path,
|
||||
class: "block px-3 py-2 rounded-md text-base font-medium text-neutral-100 hover:text-primary-200 hover:bg-primary-700"
|
||||
%>
|
||||
</div>
|
||||
<% end %>
|
||||
<div style="display: flex; gap: var(--space-2); align-items: center;">
|
||||
<a href="#events" class="nav-link">Events</a>
|
||||
<a href="#features" class="nav-link">About</a>
|
||||
<a href="#contact" class="nav-link">Contact</a>
|
||||
<button class="btn btn-md btn-outline" style="margin-left: var(--space-2);">Sign In</button>
|
||||
<button class="btn btn-md btn-primary">Get Started</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
</nav>
|
||||
157
app/views/components/_party_finder.html.erb
Normal file
157
app/views/components/_party_finder.html.erb
Normal file
@@ -0,0 +1,157 @@
|
||||
<!-- Party Finder Section -->
|
||||
<section style="padding: 0;">
|
||||
<div class="container">
|
||||
<div class="party-finder animate-fadeInUp">
|
||||
<div class="finder-header">
|
||||
<h2 class="finder-title">Find Your Perfect Event</h2>
|
||||
<p class="finder-subtitle">Discover afterwork parties tailored to your preferences</p>
|
||||
</div>
|
||||
|
||||
<form class="finder-form">
|
||||
<div class="finder-field">
|
||||
<label class="finder-label">
|
||||
<i data-lucide="calendar"></i>
|
||||
Date
|
||||
</label>
|
||||
<input type="date" class="finder-input focus-ring" id="event-date">
|
||||
</div>
|
||||
|
||||
<div class="finder-field">
|
||||
<label class="finder-label">
|
||||
<i data-lucide="map-pin"></i>
|
||||
City
|
||||
</label>
|
||||
<select class="finder-select focus-ring" id="event-city">
|
||||
<option value="">Choose a city</option>
|
||||
<option value="paris">Paris</option>
|
||||
<option value="london">London</option>
|
||||
<option value="berlin">Berlin</option>
|
||||
<option value="madrid">Madrid</option>
|
||||
<option value="barcelona">Barcelona</option>
|
||||
<option value="amsterdam">Amsterdam</option>
|
||||
<option value="rome">Rome</option>
|
||||
<option value="zurich">Zurich</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="finder-field">
|
||||
<label class="finder-label">
|
||||
<i data-lucide="users"></i>
|
||||
Event Type
|
||||
</label>
|
||||
<select class="finder-select focus-ring" id="event-type">
|
||||
<option value="">All types</option>
|
||||
<option value="networking">Networking</option>
|
||||
<option value="tech">Tech & Innovation</option>
|
||||
<option value="creative">Creative & Design</option>
|
||||
<option value="business">Business</option>
|
||||
<option value="startup">Startup</option>
|
||||
<option value="wine">Wine & Tasting</option>
|
||||
<option value="art">Art & Culture</option>
|
||||
<option value="music">Music & Entertainment</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="finder-field price-range">
|
||||
<label class="finder-label">
|
||||
<div class="price-range-label">
|
||||
<span>
|
||||
<i data-lucide="euro"></i>
|
||||
Price Range
|
||||
</span>
|
||||
<span class="price-value" id="price-display">€0 - €100</span>
|
||||
</div>
|
||||
</label>
|
||||
<div style="display: flex; gap: var(--space-3); align-items: center;">
|
||||
<input type="range" class="price-slider" id="price-min" min="0" max="100" value="0" style="flex: 1;">
|
||||
<span style="color: var(--color-neutral-500); font-weight: 600;">to</span>
|
||||
<input type="range" class="price-slider" id="price-max" min="0" max="100" value="100" style="flex: 1;">
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<button type="submit" class="finder-search-btn">
|
||||
<i data-lucide="search"></i>
|
||||
Find Events
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
// Party Finder Functionality
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const priceMin = document.getElementById('price-min');
|
||||
const priceMax = document.getElementById('price-max');
|
||||
const priceDisplay = document.getElementById('price-display');
|
||||
|
||||
if (priceMin && priceMax && priceDisplay) {
|
||||
function updatePriceDisplay() {
|
||||
const minVal = parseInt(priceMin.value);
|
||||
const maxVal = parseInt(priceMax.value);
|
||||
|
||||
// Ensure min doesn't exceed max
|
||||
if (minVal > maxVal) {
|
||||
priceMin.value = maxVal;
|
||||
}
|
||||
|
||||
// Ensure max doesn't go below min
|
||||
if (maxVal < minVal) {
|
||||
priceMax.value = minVal;
|
||||
}
|
||||
|
||||
const finalMin = Math.min(parseInt(priceMin.value), parseInt(priceMax.value));
|
||||
const finalMax = Math.max(parseInt(priceMin.value), parseInt(priceMax.value));
|
||||
|
||||
priceDisplay.textContent = `€${finalMin} - €${finalMax}`;
|
||||
}
|
||||
|
||||
priceMin.addEventListener('input', updatePriceDisplay);
|
||||
priceMax.addEventListener('input', updatePriceDisplay);
|
||||
|
||||
// Set default date to tomorrow
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
const dateInput = document.getElementById('event-date');
|
||||
if (dateInput) {
|
||||
dateInput.value = tomorrow.toISOString().split('T')[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Form submission
|
||||
const finderForm = document.querySelector('.finder-form');
|
||||
if (finderForm) {
|
||||
finderForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = {
|
||||
date: document.getElementById('event-date').value,
|
||||
city: document.getElementById('event-city').value,
|
||||
type: document.getElementById('event-type').value,
|
||||
priceMin: priceMin ? priceMin.value : '',
|
||||
priceMax: priceMax ? priceMax.value : ''
|
||||
};
|
||||
|
||||
console.log('Search filters:', formData);
|
||||
|
||||
// Add loading state to button
|
||||
const searchBtn = document.querySelector('.finder-search-btn');
|
||||
if (searchBtn) {
|
||||
const originalText = searchBtn.innerHTML;
|
||||
searchBtn.innerHTML = '<div style="width: 20px; height: 20px; border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%; animation: spin 1s linear infinite;"></div> Searching...';
|
||||
|
||||
// Simulate search
|
||||
setTimeout(() => {
|
||||
searchBtn.innerHTML = originalText;
|
||||
alert('Search completed! Results would be displayed here.');
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="h-full bg-neutral-50">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%= content_for(:title) || "Aperonight" %></title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
@@ -8,24 +8,33 @@
|
||||
<%= csrf_meta_tags %>
|
||||
<%= csp_meta_tag %>
|
||||
<%= yield :head %>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Outfit:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Lucide Icons -->
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
|
||||
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
|
||||
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
|
||||
<link rel="icon" href="/icon.png" type="image/png">
|
||||
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/icon.png">
|
||||
|
||||
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
||||
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
||||
<%= stylesheet_link_tag "theme", "data-turbo-track": "reload" %>
|
||||
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
|
||||
</head>
|
||||
<body class="h-full font-sans text-neutral-900 antialiased">
|
||||
|
||||
<div class="">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-wrapper">
|
||||
<%= render "components/header" %>
|
||||
|
||||
<main class="container mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<main>
|
||||
<% if flash.any? %>
|
||||
<div class="flash mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<div class="flash py-6">
|
||||
<%= render "shared/flash_messages" %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -35,12 +44,108 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="bg-neutral-100 text-neutral-600">
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
<!-- Features Section -->
|
||||
<section class="section features-section">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Why Choose Aperonight?</h2>
|
||||
<p class="section-description">We curate premium experiences that connect professionals and create lasting relationships.</p>
|
||||
</div>
|
||||
|
||||
<div class="features-grid">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i data-lucide="crown"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Premium Curation</h3>
|
||||
<p class="feature-description">Every event is carefully selected and designed to provide exceptional value and networking opportunities.</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i data-lucide="shield-check"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Secure & Trusted</h3>
|
||||
<p class="feature-description">Safe payments, verified venues, and trusted community with comprehensive insurance coverage.</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i data-lucide="users-2"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Quality Networking</h3>
|
||||
<p class="feature-description">Connect with verified professionals, entrepreneurs, and industry leaders in intimate settings.</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">
|
||||
<i data-lucide="zap"></i>
|
||||
</div>
|
||||
<h3 class="feature-title">Instant Booking</h3>
|
||||
<p class="feature-description">Seamless reservation process with instant confirmation and easy event management.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Stats Section -->
|
||||
<section class="section stats-section">
|
||||
<div class="container">
|
||||
<div class="stats-grid">
|
||||
<div class="stat-item">
|
||||
<span class="stat-number">150+</span>
|
||||
<div class="stat-label">Monthly Events</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-number">5.2K</span>
|
||||
<div class="stat-label">Active Members</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-number">200+</span>
|
||||
<div class="stat-label">Partner Venues</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-number">98%</span>
|
||||
<div class="stat-label">Satisfaction Rate</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="cta-section">
|
||||
<div class="container">
|
||||
<div class="cta-content">
|
||||
<h2>Ready to Join the Community?</h2>
|
||||
<p>Start discovering amazing events and connect with like-minded professionals in your city.</p>
|
||||
<div style="display: flex; gap: var(--space-4); justify-content: center; flex-wrap: wrap;">
|
||||
<button class="btn btn-lg" style="background: white; color: var(--color-primary-600); border: 2px solid white;">
|
||||
<i data-lucide="user-plus"></i>
|
||||
Join Now - Free
|
||||
</button>
|
||||
<button class="btn btn-lg btn-ghost" style="border: 2px solid rgba(255,255,255,0.5); color: white;">
|
||||
<i data-lucide="calendar"></i>
|
||||
Browse Events
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<%= render "components/footer" %>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize Lucide icons
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
if (typeof lucide !== 'undefined') {
|
||||
lucide.createIcons();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
247
app/views/pages/components.html.erb
Normal file
247
app/views/pages/components.html.erb
Normal file
@@ -0,0 +1,247 @@
|
||||
<div class="py-12">
|
||||
<div class="text-center mb-16">
|
||||
<h1 class="mb-4">Aperonight Design System</h1>
|
||||
<p class="text-xl text-neutral-600 max-w-3xl mx-auto">
|
||||
A comprehensive collection of reusable components for premium event booking experiences.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Buttons Section -->
|
||||
<section class="mb-16">
|
||||
<h2 class="mb-8 text-2xl font-bold">Buttons</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Primary Buttons</h3>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<button class="btn btn-sm btn-primary">Small</button>
|
||||
<button class="btn btn-md btn-primary">Medium</button>
|
||||
<button class="btn btn-lg btn-primary">Large</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Secondary Buttons</h3>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<button class="btn btn-sm btn-secondary">Small</button>
|
||||
<button class="btn btn-md btn-secondary">Medium</button>
|
||||
<button class="btn btn-lg btn-secondary">Large</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Outline Buttons</h3>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<button class="btn btn-sm btn-outline">Small</button>
|
||||
<button class="btn btn-md btn-outline">Medium</button>
|
||||
<button class="btn btn-lg btn-outline">Large</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Ghost Buttons</h3>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<button class="btn btn-sm btn-ghost">Small</button>
|
||||
<button class="btn btn-md btn-ghost">Medium</button>
|
||||
<button class="btn btn-lg btn-ghost">Large</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Form Elements -->
|
||||
<section class="mb-16">
|
||||
<h2 class="mb-8 text-2xl font-bold">Form Elements</h2>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Input Fields</h3>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Event Name</label>
|
||||
<input type="text" class="form-input focus-ring" placeholder="Enter event name">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Description</label>
|
||||
<textarea class="form-textarea focus-ring" rows="3" placeholder="Describe your event"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Category</label>
|
||||
<select class="form-select focus-ring">
|
||||
<option>Select category</option>
|
||||
<option>Networking</option>
|
||||
<option>Tech</option>
|
||||
<option>Creative</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="search-box">
|
||||
<input type="search" class="form-input search-input focus-ring" placeholder="Search events...">
|
||||
<i class="search-icon">
|
||||
<!-- Search icon would be inserted by Lucide JS -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-3 mt-6">
|
||||
<button type="submit" class="btn btn-md btn-primary">Submit</button>
|
||||
<button type="reset" class="btn btn-md btn-outline">Reset</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Validation States</h3>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Email (Valid)</label>
|
||||
<input type="email" class="form-input" value="user@example.com" style="border-color: var(--color-success); background: var(--color-success-light);">
|
||||
<div class="form-error mt-1" style="color: var(--color-success); display: flex; align-items: center; gap: 0.25rem;">
|
||||
<!-- Check icon -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
||||
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
||||
</svg>
|
||||
Email is valid
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Password (Error)</label>
|
||||
<input type="password" class="form-input" value="123" style="border-color: var(--color-danger); background: var(--color-danger-light);">
|
||||
<div class="form-error">
|
||||
<!-- Alert icon -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="8" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
||||
</svg>
|
||||
Password must be at least 8 characters
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Phone (Warning)</label>
|
||||
<input type="tel" class="form-input" value="+33 1 23 45" style="border-color: var(--color-warning); background: var(--color-warning-light);">
|
||||
<div class="form-error mt-1" style="color: var(--color-warning-dark); display: flex; align-items: center; gap: 0.25rem;">
|
||||
<!-- Warning icon -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
||||
<line x1="12" y1="9" x2="12" y2="13"></line>
|
||||
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
||||
</svg>
|
||||
Please complete phone number
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Badges and Tags -->
|
||||
<section class="mb-16">
|
||||
<h2 class="mb-8 text-2xl font-bold">Badges & Tags</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Event Status Badges</h3>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<span class="badge badge-available">Available</span>
|
||||
<span class="badge badge-limited">Limited</span>
|
||||
<span class="badge badge-sold-out">Sold Out</span>
|
||||
<span class="badge badge-featured">★ Featured</span>
|
||||
<span class="badge badge-vip">VIP</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">Price Tags</h3>
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
<div class="price-tag price-tag-sm" style="color: var(--color-neutral-600);">€15</div>
|
||||
<div class="price-tag price-tag-md" style="color: var(--color-primary-600);">€35</div>
|
||||
<div class="price-tag price-tag-lg" style="color: var(--color-accent-600);">€55</div>
|
||||
<div class="price-tag price-tag-md" style="color: var(--color-neutral-600);">
|
||||
<span style="text-decoration: line-through; opacity: 0.7;">€60</span>
|
||||
<span style="color: var(--color-success); margin-left: 0.5rem;">€45</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Cards -->
|
||||
<section class="mb-16">
|
||||
<h2 class="mb-8 text-2xl font-bold">Cards</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<div class="card hover-lift">
|
||||
<div class="card-header">
|
||||
<h3 class="font-bold mb-2">Basic Card</h3>
|
||||
<p class="text-neutral-600 m-0">Simple card with header and content</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>This is a basic card component that can be used for various content types. It includes proper spacing and hover effects.</p>
|
||||
<button class="btn btn-md btn-primary mt-4">Learn More</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="event-card hover-glow">
|
||||
<div style="height: 200px; background: linear-gradient(135deg, var(--color-primary-500), var(--color-accent-500)); display: flex; align-items: center; justify-content: center; color: white; font-size: var(--text-xl); font-weight: bold;">
|
||||
Event Image
|
||||
</div>
|
||||
<div style="padding: var(--space-6);">
|
||||
<div class="flex gap-2 mb-4">
|
||||
<span class="badge badge-featured">★ Featured</span>
|
||||
<span class="badge badge-available">Available</span>
|
||||
</div>
|
||||
<h3 class="font-bold mb-2 text-neutral-900">Networking Event</h3>
|
||||
<p class="text-neutral-600 mb-6 text-sm">Join professionals for an evening of networking and insights.</p>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="price-tag price-tag-md" style="color: var(--color-primary-600);">€35</span>
|
||||
<button class="btn btn-sm btn-primary">Book Now</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3 class="demo-title mb-4">User Profile</h3>
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div class="avatar avatar-lg">
|
||||
<div class="avatar-image" style="background: linear-gradient(135deg, var(--color-primary-200), var(--color-accent-200));"></div>
|
||||
<div class="avatar-status status-online"></div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="font-bold mb-1">Alex Johnson</h4>
|
||||
<p class="text-neutral-600 text-sm m-0">Senior Developer</p>
|
||||
<div class="rating mt-1">
|
||||
<!-- Stars would be inserted by Lucide JS -->
|
||||
<div class="flex">
|
||||
<svg class="rating-star filled" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||
</svg>
|
||||
<svg class="rating-star filled" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||
</svg>
|
||||
<svg class="rating-star filled" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||
</svg>
|
||||
<svg class="rating-star filled" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||
</svg>
|
||||
<svg class="rating-star empty" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-sm text-neutral-600 ml-2">4.2</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button class="btn btn-sm btn-primary flex-1">Connect</button>
|
||||
<button class="btn btn-sm btn-outline">Message</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1,46 +1,217 @@
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<h1 class="text-3xl font-bold mb-8">Upcoming Events</h1>
|
||||
|
||||
<% if @parties.any? %>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<% @parties.each do |party| %>
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
||||
<% if party.image.present? %>
|
||||
<img src="<%= party.image %>" alt="<%= party.name %>" class="w-full h-48 object-cover">
|
||||
<% else %>
|
||||
<div class="bg-gray-200 border-2 border-dashed rounded-xl w-full h-48 flex items-center justify-center">
|
||||
<span class="text-gray-500">No Image</span>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="p-6">
|
||||
<h2 class="text-xl font-semibold mb-2"><%= party.name %></h2>
|
||||
<p class="text-gray-600 mb-4"><%= party.description.truncate(100) %></p>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<p class="text-sm text-gray-500"><%= party.venue_name %></p>
|
||||
<p class="text-sm text-gray-500"><%= party.venue_address %></p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-blue-100 text-blue-800">
|
||||
<%= party.state.humanize %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% content_for :title, "All Events - Aperonight" %>
|
||||
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h1 class="section-title">All Events</h1>
|
||||
<p class="section-description">Discover all our upcoming afterwork events tailored to your interests.</p>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="mt-8 flex justify-center">
|
||||
<%= paginate @parties %>
|
||||
<div class="events-filter-bar" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-8); flex-wrap: wrap; gap: var(--space-4);">
|
||||
<div class="search-box" style="flex: 1; max-width: 400px;">
|
||||
<input type="text" class="form-input search-input" placeholder="Search events...">
|
||||
<i data-lucide="search" class="search-icon"></i>
|
||||
</div>
|
||||
<div style="display: flex; gap: var(--space-3);">
|
||||
<select class="form-select" style="min-width: 150px;">
|
||||
<option>All Categories</option>
|
||||
<option>Networking</option>
|
||||
<option>Tech & Innovation</option>
|
||||
<option>Creative & Design</option>
|
||||
<option>Business</option>
|
||||
<option>Wine & Tasting</option>
|
||||
</select>
|
||||
<select class="form-select" style="min-width: 120px;">
|
||||
<option>Any Price</option>
|
||||
<option>Free</option>
|
||||
<option>Under €30</option>
|
||||
<option>€30 - €60</option>
|
||||
<option>Over €60</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-center py-12">
|
||||
<h2 class="text-xl font-medium text-gray-900 mb-4">No events found</h2>
|
||||
<p class="text-gray-500">Check back later for upcoming events.</p>
|
||||
|
||||
<div class="events-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--space-6);">
|
||||
<!-- Event 1 -->
|
||||
<div class="event-card hover-glow">
|
||||
<img src="https://images.unsplash.com/photo-1540039155733-5bb30b53aa14?w=400&h=200&fit=crop" alt="Tech Networking Night" style="width: 100%; height: 200px; object-fit: cover;">
|
||||
<div style="padding: var(--space-5);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-3);">
|
||||
<h3 style="font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; margin: 0;">Tech & Innovation Networking Night</h3>
|
||||
<span class="badge badge-featured">★ Featured</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="calendar" style="width: 16px; height: 16px;"></i>
|
||||
<span>Thu, Mar 15 • 18:30</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-4); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="map-pin" style="width: 16px; height: 16px;"></i>
|
||||
<span>Le Perchoir Marais, Paris</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span class="price-tag price-tag-md">€35</span>
|
||||
<button class="btn btn-sm btn-primary">Reserve Spot</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 2 -->
|
||||
<div class="event-card hover-glow">
|
||||
<img src="https://images.unsplash.com/photo-1574391884720-bbc3740c59d1?w=400&h=200&fit=crop" alt="Creative Afterwork" style="width: 100%; height: 200px; object-fit: cover;">
|
||||
<div style="padding: var(--space-5);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-3);">
|
||||
<h3 style="font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; margin: 0;">Creative Directors Exclusive Meetup</h3>
|
||||
<span class="badge badge-vip">VIP</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="calendar" style="width: 16px; height: 16px;"></i>
|
||||
<span>Fri, Mar 16 • 19:00</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-4); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="map-pin" style="width: 16px; height: 16px;"></i>
|
||||
<span>Atelier Des Lumières, Paris</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span class="price-tag price-tag-md">€65</span>
|
||||
<button class="btn btn-sm btn-primary">Join VIP</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 3 -->
|
||||
<div class="event-card hover-glow">
|
||||
<img src="https://images.unsplash.com/photo-1569949381669-ecf31ae8e613?w=400&h=200&fit=crop" alt="Wine Tasting" style="width: 100%; height: 200px; object-fit: cover;">
|
||||
<div style="padding: var(--space-5);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-3);">
|
||||
<h3 style="font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; margin: 0;">Wine & Business Premium Tasting</h3>
|
||||
<span class="badge badge-available">Available</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="calendar" style="width: 16px; height: 16px;"></i>
|
||||
<span>Sat, Mar 18 • 17:00</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-4); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="map-pin" style="width: 16px; height: 16px;"></i>
|
||||
<span>Cave Legrand, Paris</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span class="price-tag price-tag-md">€55</span>
|
||||
<button class="btn btn-sm btn-secondary">Book Now</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 4 -->
|
||||
<div class="event-card hover-glow">
|
||||
<img src="https://images.unsplash.com/photo-1511795409834-ef04bbd61622?w=400&h=200&fit=crop" alt="Startup Pitch Night" style="width: 100%; height: 200px; object-fit: cover;">
|
||||
<div style="padding: var(--space-5);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-3);">
|
||||
<h3 style="font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; margin: 0;">Startup Pitch Night</h3>
|
||||
<span class="badge badge-limited">Limited</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="calendar" style="width: 16px; height: 16px;"></i>
|
||||
<span>Mon, Mar 20 • 18:00</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-4); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="map-pin" style="width: 16px; height: 16px;"></i>
|
||||
<span>Station F, Paris</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span class="price-tag price-tag-md">€25</span>
|
||||
<button class="btn btn-sm btn-primary">Reserve Spot</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 5 -->
|
||||
<div class="event-card hover-glow">
|
||||
<img src="https://images.unsplash.com/photo-1470225620780-dba8ba36b745?w=400&h=200&fit=crop" alt="Jazz & Cocktails" style="width: 100%; height: 200px; object-fit: cover;">
|
||||
<div style="padding: var(--space-5);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-3);">
|
||||
<h3 style="font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; margin: 0;">Jazz & Cocktails Evening</h3>
|
||||
<span class="badge badge-available">Available</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="calendar" style="width: 16px; height: 16px;"></i>
|
||||
<span>Wed, Mar 22 • 20:00</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-4); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="map-pin" style="width: 16px; height: 16px;"></i>
|
||||
<span>Blue Note, Paris</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span class="price-tag price-tag-md">€40</span>
|
||||
<button class="btn btn-sm btn-secondary">Book Now</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 6 -->
|
||||
<div class="event-card hover-glow">
|
||||
<img src="https://images.unsplash.com/photo-1511795409834-ef04bbd61622?w=400&h=200&fit=crop" alt="Art & Wine" style="width: 100%; height: 200px; object-fit: cover;">
|
||||
<div style="padding: var(--space-5);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-3);">
|
||||
<h3 style="font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700; margin: 0;">Art & Wine Gallery Night</h3>
|
||||
<span class="badge badge-featured">★ Featured</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="calendar" style="width: 16px; height: 16px;"></i>
|
||||
<span>Fri, Mar 24 • 19:30</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-4); color: var(--color-neutral-600); font-size: var(--text-sm);">
|
||||
<i data-lucide="map-pin" style="width: 16px; height: 16px;"></i>
|
||||
<span>Gallery Lafayette, Paris</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span class="price-tag price-tag-md">€30</span>
|
||||
<button class="btn btn-sm btn-primary">Reserve Spot</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: center; margin-top: var(--space-8);">
|
||||
<nav style="display: flex; gap: var(--space-2);">
|
||||
<a href="#" class="btn btn-outline" style="padding: var(--space-2) var(--space-4);">Previous</a>
|
||||
<a href="#" class="btn btn-primary" style="padding: var(--space-2) var(--space-4);">1</a>
|
||||
<a href="#" class="btn btn-outline" style="padding: var(--space-2) var(--space-4);">2</a>
|
||||
<a href="#" class="btn btn-outline" style="padding: var(--space-2) var(--space-4);">3</a>
|
||||
<a href="#" class="btn btn-outline" style="padding: var(--space-2) var(--space-4);">Next</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.events-filter-bar .search-input {
|
||||
padding-left: var(--space-12);
|
||||
}
|
||||
|
||||
.events-filter-bar .search-icon {
|
||||
position: absolute;
|
||||
left: var(--space-4);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--color-neutral-400);
|
||||
}
|
||||
|
||||
.events-filter-bar {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.events-filter-bar {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.events-filter-bar .search-box {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.events-filter-bar > div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,250 +1,320 @@
|
||||
<% content_for :title, "Aperonight - Discover Premium Afterwork Events" %>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative bg-neutral-50 min-h-[70vh] flex items-center">
|
||||
<div class="absolute inset-0 bg-white bg-opacity-60"></div>
|
||||
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h1 class="text-5xl md:text-7xl font-bold text-neutral-900 mb-6 leading-tight">
|
||||
Découvrez les afterworks et soirée
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-purple-600 to-pink-600">
|
||||
à Paris
|
||||
</span>
|
||||
</h1>
|
||||
<p class="text-xl md:text-2xl text-neutral-700 mb-8 max-w-3xl mx-auto leading-relaxed">
|
||||
Les meilleures soirées, concerts et afterworks de Paris en un clic. Réservez vos places et vivez des expériences uniques.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<%= link_to "Explorer les soirées", parties_path, class: "bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white font-semibold py-4 px-8 rounded-full transition-all duration-300 transform hover:scale-105 shadow-lg" %>
|
||||
<%= link_to "Voir les concerts", "#", class: "bg-white border border-neutral-300 hover:border-purple-300 text-neutral-700 font-semibold py-4 px-8 rounded-full transition-all duration-300" %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<div class="hero-content">
|
||||
<h1>Discover Premium Afterwork Events</h1>
|
||||
<p class="subtitle">Connect with professionals, explore unique venues, and create memorable experiences at carefully curated afterwork events in your city.</p>
|
||||
|
||||
<!-- Metrics -->
|
||||
<section class="bg-neutral-50 py-20">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl md:text-5xl font-bold text-neutral-900 mb-4">
|
||||
Des chiffres qui parlent
|
||||
</h2>
|
||||
<p class="text-xl text-neutral-600 max-w-2xl mx-auto">
|
||||
La plateforme préférée des Parisiens pour vivre la nuit
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8 md:gap-12">
|
||||
<!-- Total Events -->
|
||||
<div class="group relative">
|
||||
<div class="relative overflow-hidden rounded-2xl bg-white border border-neutral-200 hover:border-purple-300 transition-all duration-300 p-8">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-100 to-indigo-100 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="relative">
|
||||
<div class="text-5xl md:text-6xl font-light bg-gradient-to-r from-purple-600 via-indigo-600 to-pink-600 bg-clip-text text-transparent mb-3">
|
||||
<span class="counter" data-controller="counter" data-counter-target-value="127">0</span>
|
||||
</div>
|
||||
<p class="text-neutral-700 font-mono uppercase tracking-widest text-sm font-medium">
|
||||
Événements organisés
|
||||
</p>
|
||||
<div class="mt-4 h-1 bg-gradient-to-r from-purple-500 via-indigo-500 to-pink-500 rounded-full w-0 group-hover:w-full transition-all duration-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Total Users -->
|
||||
<div class="group relative">
|
||||
<div class="relative overflow-hidden rounded-2xl bg-white border border-neutral-200 hover:border-purple-300 transition-all duration-300 p-8">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-100 to-indigo-100 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="relative">
|
||||
<div class="text-5xl md:text-6xl font-light bg-gradient-to-r from-purple-600 via-indigo-600 to-pink-600 bg-clip-text text-transparent mb-3">
|
||||
<span class="counter" data-controller="counter" data-counter-target-value="1433">0</span>+
|
||||
</div>
|
||||
<p class="text-neutral-700 font-mono uppercase tracking-widest text-sm font-medium">
|
||||
Membres actifs
|
||||
</p>
|
||||
<div class="mt-4 h-1 bg-gradient-to-r from-purple-500 via-indigo-500 to-pink-500 rounded-full w-0 group-hover:w-full transition-all duration-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Average Rating -->
|
||||
<div class="group relative">
|
||||
<div class="relative overflow-hidden rounded-2xl bg-white border border-neutral-200 hover:border-purple-300 transition-all duration-300 p-8">
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-purple-100 to-indigo-100 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
<div class="relative">
|
||||
<div class="text-5xl md:text-6xl font-light bg-gradient-to-r from-purple-600 via-indigo-600 to-pink-600 bg-clip-text text-transparent mb-3">
|
||||
<span class="counter" data-controller="counter" data-counter-target-value="4.4" data-counter-decimal-value="true">0</span>/5
|
||||
</div>
|
||||
<p class="text-neutral-700 font-mono uppercase tracking-widest text-sm font-medium">
|
||||
Note moyenne des soirées
|
||||
</p>
|
||||
<div class="mt-4 h-1 bg-gradient-to-r from-purple-500 via-indigo-500 to-pink-500 rounded-full w-0 group-hover:w-full transition-all duration-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Additional Stats Row -->
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-6 mt-12">
|
||||
<div class="text-center">
|
||||
<div class="text-3xl font-bold text-purple-600">
|
||||
<span class="counter" data-controller="counter" data-counter-target-value="79">0</span>%
|
||||
</div>
|
||||
<p class="text-neutral-600 text-sm font-mono uppercase tracking-wide font-medium">Taux de remplissage</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div class="text-3xl font-bold text-purple-600">
|
||||
<span class="counter" data-controller="counter" data-counter-target-value="12">0</span>
|
||||
</div>
|
||||
<p class="text-neutral-600 text-sm font-mono uppercase tracking-wide font-medium">Arrondissements</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div class="text-3xl font-bold text-purple-600">
|
||||
<span class="counter" data-controller="counter" data-counter-target-value="156">0</span>
|
||||
</div>
|
||||
<p class="text-neutral-600 text-sm font-mono uppercase tracking-wide font-medium">Établissements partenaires</p>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<div class="text-3xl font-bold text-purple-600">
|
||||
<span class="counter" data-controller="counter" data-counter-target-value="98">0</span>%
|
||||
</div>
|
||||
<p class="text-neutral-600 text-sm font-mono uppercase tracking-wide font-medium">Satisfaction client</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Quick Search Section -->
|
||||
<section id="search" class="bg-white py-16">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="bg-gradient-to-br from-neutral-50 to-white border border-neutral-200 rounded-2xl p-8 shadow-lg">
|
||||
<h2 class="text-3xl font-bold text-neutral-900 text-center mb-8">Trouvez votre prochaine soirée</h2>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 items-end">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-neutral-700 mb-2">Quand ?</label>
|
||||
<input type="date" class="w-full bg-white border border-neutral-300 text-neutral-900 rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" placeholder="Choisir une date">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-neutral-700 mb-2">Type d'événement</label>
|
||||
<select class="w-full bg-white border border-neutral-300 text-neutral-900 rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all">
|
||||
<option value="">Tous les types</option>
|
||||
<option value="club">Soirées club</option>
|
||||
<option value="afterwork">Afterworks</option>
|
||||
<option value="concert">Concerts</option>
|
||||
<option value="vip">Événements VIP</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-neutral-700 mb-2">Genre musical</label>
|
||||
<select class="w-full bg-white border border-neutral-300 text-neutral-900 rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all">
|
||||
<option value="">Tous les genres</option>
|
||||
<option value="house">House/Techno</option>
|
||||
<option value="hiphop">Hip-Hop</option>
|
||||
<option value="pop">Pop</option>
|
||||
<option value="rock">Rock</option>
|
||||
<option value="electro">Électro</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button class="w-full bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white font-semibold py-3 px-6 rounded-lg transition-all duration-300 transform hover:scale-105">
|
||||
Rechercher
|
||||
<div class="cta-group">
|
||||
<button class="btn btn-lg btn-primary">
|
||||
<i data-lucide="search"></i>
|
||||
Explore Events
|
||||
</button>
|
||||
<button class="btn btn-lg btn-secondary">
|
||||
<i data-lucide="plus"></i>
|
||||
Host an Event
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="hero-stats">
|
||||
<div class="hero-stat">
|
||||
<span class="hero-stat-number">150+</span>
|
||||
<span class="hero-stat-label">Events Monthly</span>
|
||||
</div>
|
||||
<div class="hero-stat">
|
||||
<span class="hero-stat-number">5.2K</span>
|
||||
<span class="hero-stat-label">Active Members</span>
|
||||
</div>
|
||||
<div class="hero-stat">
|
||||
<span class="hero-stat-number">200+</span>
|
||||
<span class="hero-stat-label">Partner Venues</span>
|
||||
</div>
|
||||
<div class="hero-stat">
|
||||
<span class="hero-stat-number">98%</span>
|
||||
<span class="hero-stat-label">Satisfaction</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Featured Events -->
|
||||
<section id="events" class="bg-neutral-50 py-20">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-12">
|
||||
<h2 class="text-4xl font-bold text-neutral-900 mb-4">Événements du moment</h2>
|
||||
<p class="text-xl text-neutral-600">Les soirées et concerts les plus populaires cette semaine</p>
|
||||
<%= render "components/party_finder" %>
|
||||
|
||||
<!-- Featured Events Section -->
|
||||
<section class="section featured-events" id="events">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Featured This Week</h2>
|
||||
<p class="section-description">Handpicked premium events that bring together the best professionals and creators in the city.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<% @parties.each do |party| %>
|
||||
<div class="bg-white border border-neutral-200 rounded-2xl overflow-hidden hover:transform hover:scale-105 transition-all duration-300 shadow-lg">
|
||||
<div class="h-56 bg-gradient-to-br from-purple-500 via-pink-500 to-red-500 relative"
|
||||
style="background-image: url('<%= party.image || "https://images.unsplash.com/photo-1506157786151-b84b9d3d78d8?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" %>');
|
||||
background-size: cover;
|
||||
background-position: center;">
|
||||
<div class="absolute top-4 right-4 bg-white bg-opacity-90 text-neutral-900 px-3 py-1 rounded-full text-sm font-medium">
|
||||
<%= party.venue_name.split(' ').first %>
|
||||
<div class="featured-events-grid animate-fadeInUp">
|
||||
<!-- Featured Event 1 -->
|
||||
<div class="featured-event-card animate-slideInLeft">
|
||||
<img src="https://images.unsplash.com/photo-1540039155733-5bb30b53aa14?w=600&h=300&fit=crop" alt="Tech Networking Night" class="featured-event-image">
|
||||
<div class="featured-event-content">
|
||||
<div class="featured-event-badges">
|
||||
<span class="badge badge-featured">★ Featured</span>
|
||||
<span class="badge badge-available">Available</span>
|
||||
</div>
|
||||
<h3 class="featured-event-title">Tech & Innovation Networking Night</h3>
|
||||
<div class="featured-event-meta">
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="calendar"></i>
|
||||
Thu, Mar 15 • 18:30 - 22:00
|
||||
</div>
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="map-pin"></i>
|
||||
Le Perchoir Marais, Paris
|
||||
</div>
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="users"></i>
|
||||
85 attendees • 15 spots left
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="flex justify-between items-start mb-3">
|
||||
<h3 class="text-2xl font-bold text-neutral-900"><%= party.name.upcase %></h3>
|
||||
<% if party.ticket_types.any? %>
|
||||
<span class="text-purple-600 font-semibold"><%= number_to_currency(party.ticket_types.first.price_cents / 100.0, unit: "€", separator: ",", delimiter: " ") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<p class="text-neutral-600 mb-2"><%= party.venue_name %>, <%= party.venue_address.split(',').first %></p>
|
||||
<p class="text-neutral-700 mb-4"><%= I18n.l(party.start_time, format: "%A %Hh") if party.start_time %> • <%= party.description.split('.').first %></p>
|
||||
<%= link_to "Voir les détails", party_path(party.slug, party), class: "w-full bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white font-semibold py-3 rounded-lg transition-all duration-300 text-center block" %>
|
||||
<p class="featured-event-description">Join 100+ tech professionals for an exclusive evening of networking, drinks, and insights into the latest innovation trends. Connect with startups, investors, and industry leaders.</p>
|
||||
<div class="featured-event-footer">
|
||||
<span class="featured-event-price">€35</span>
|
||||
<button class="btn btn-sm btn-primary">Reserve Spot</button>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Featured Event 2 -->
|
||||
<div class="featured-event-card animate-fadeInUp">
|
||||
<img src="https://images.unsplash.com/photo-1574391884720-bbc3740c59d1?w=400&h=240&fit=crop" alt="Creative Afterwork" class="featured-event-image">
|
||||
<div class="featured-event-content">
|
||||
<div class="featured-event-badges">
|
||||
<span class="badge badge-vip">VIP</span>
|
||||
<span class="badge badge-limited">Limited</span>
|
||||
</div>
|
||||
<h3 class="featured-event-title">Creative Directors Exclusive Meetup</h3>
|
||||
<div class="featured-event-meta">
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="calendar"></i>
|
||||
Fri, Mar 16 • 19:00 - 23:00
|
||||
</div>
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="map-pin"></i>
|
||||
Atelier Des Lumières, Paris
|
||||
</div>
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="users"></i>
|
||||
30 creatives • 8 spots left
|
||||
</div>
|
||||
</div>
|
||||
<p class="featured-event-description">An intimate gathering of creative directors, designers, and visual artists. Experience immersive art installations while networking with industry pioneers.</p>
|
||||
<div class="featured-event-footer">
|
||||
<span class="featured-event-price">€65</span>
|
||||
<button class="btn btn-sm btn-primary">Join VIP</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Featured Event 3 -->
|
||||
<div class="featured-event-card animate-slideInRight">
|
||||
<img src="https://images.unsplash.com/photo-1569949381669-ecf31ae8e613?w=400&h=240&fit=crop" alt="Wine Tasting" class="featured-event-image">
|
||||
<div class="featured-event-content">
|
||||
<div class="featured-event-badges">
|
||||
<span class="badge badge-available">Available</span>
|
||||
</div>
|
||||
<h3 class="featured-event-title">Wine & Business Premium Tasting</h3>
|
||||
<div class="featured-event-meta">
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="calendar"></i>
|
||||
Sat, Mar 18 • 17:00 - 21:00
|
||||
</div>
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="map-pin"></i>
|
||||
Cave Legrand, Paris
|
||||
</div>
|
||||
<div class="featured-event-meta-item">
|
||||
<i data-lucide="users"></i>
|
||||
45 professionals • 12 spots left
|
||||
</div>
|
||||
</div>
|
||||
<p class="featured-event-description">Discover exceptional French wines while connecting with business professionals. Expert sommelier guidance and premium tastings in a historic wine cellar.</p>
|
||||
<div class="featured-event-footer">
|
||||
<span class="featured-event-price">€55</span>
|
||||
<button class="btn btn-sm btn-secondary">Book Now</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12">
|
||||
<%= link_to "Voir tous les événements →", parties_path, class: "text-purple-600 hover:text-purple-700 text-lg font-medium transition-all duration-300 border-b-2 border-purple-600 hover:border-purple-700" %>
|
||||
<div style="text-align: center; margin-top: var(--space-12);">
|
||||
<%= link_to "View All Events", parties_path, class: "btn btn-lg btn-outline" %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Features -->
|
||||
<section class="bg-white py-20">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-4xl font-bold text-neutral-900 mb-4">Pourquoi choisir <%= Rails.application.config.app_name %> ?</h2>
|
||||
<p class="text-xl text-neutral-600 max-w-2xl mx-auto">La plateforme préférée des Parisiens pour sortir</p>
|
||||
</div>
|
||||
<style>
|
||||
/* Updated Featured Events Grid - 3 Cards Side by Side */
|
||||
.featured-events-grid {
|
||||
display: grid;
|
||||
gap: var(--space-8);
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div class="text-center p-8">
|
||||
<div class="bg-gradient-to-r from-purple-600 to-pink-600 rounded-full w-20 h-20 flex items-center justify-center mx-auto 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="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-neutral-900 mb-3">Découverte facile</h3>
|
||||
<p class="text-neutral-600 leading-relaxed">Trouvez les meilleures soirées et concerts de Paris en quelques clics grâce à notre algorithme personnalisé</p>
|
||||
</div>
|
||||
@media (min-width: 768px) {
|
||||
.featured-events-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
<div class="text-center p-8">
|
||||
<div class="bg-gradient-to-r from-purple-600 to-pink-600 rounded-full w-20 h-20 flex items-center justify-center mx-auto 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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-neutral-900 mb-3">Réservation sécurisée</h3>
|
||||
<p class="text-neutral-600 leading-relaxed">Paiement 100% sécurisé et billets électroniques avec QR code sur votre mobile</p>
|
||||
</div>
|
||||
@media (min-width: 1024px) {
|
||||
.featured-events-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
<div class="text-center p-8">
|
||||
<div class="bg-gradient-to-r from-purple-600 to-pink-600 rounded-full w-20 h-20 flex items-center justify-center mx-auto 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 10V3L4 14h7v7l9-11h-7z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-neutral-900 mb-3">Accès rapide</h3>
|
||||
<p class="text-neutral-600 leading-relaxed">Entrée express avec validation mobile de vos billets. Plus besoin d'imprimer !</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
.featured-event-card {
|
||||
background: white;
|
||||
border-radius: var(--radius-xl);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-md);
|
||||
transition: all var(--duration-slow) var(--ease-out);
|
||||
border: 1px solid var(--color-neutral-200);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="bg-gradient-to-r from-purple-100 via-pink-50 to-indigo-100 py-20">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<h2 class="text-4xl font-bold text-neutral-900 mb-6">Prêt à vivre la nuit parisienne ?</h2>
|
||||
<p class="text-xl text-neutral-700 mb-8">Rejoignez des milliers de party-goers qui utilisent Aperonight chaque semaine</p>
|
||||
<%= link_to new_user_registration_path, class: "bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white font-semibold py-4 px-8 rounded-full text-lg transition-all duration-300 transform hover:scale-105 shadow-xl" do %>
|
||||
S'inscrire gratuitement
|
||||
<% end %>
|
||||
</div>
|
||||
</section>
|
||||
.featured-event-card:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: var(--shadow-2xl);
|
||||
border-color: var(--color-primary-200);
|
||||
}
|
||||
|
||||
.featured-event-image {
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
object-fit: cover;
|
||||
transition: transform var(--duration-slow) var(--ease-out);
|
||||
}
|
||||
|
||||
.featured-event-card:hover .featured-event-image {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.featured-event-content {
|
||||
padding: var(--space-6);
|
||||
}
|
||||
|
||||
.featured-event-badges {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
margin-bottom: var(--space-4);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.featured-event-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-xl);
|
||||
font-weight: 700;
|
||||
margin-bottom: var(--space-3);
|
||||
color: var(--color-neutral-900);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.featured-event-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.featured-event-meta-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
color: var(--color-neutral-600);
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.featured-event-description {
|
||||
color: var(--color-neutral-700);
|
||||
margin-bottom: var(--space-6);
|
||||
line-height: 1.6;
|
||||
font-size: var(--text-sm);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.featured-event-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.featured-event-price {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-xl);
|
||||
font-weight: 800;
|
||||
color: var(--color-primary-600);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.featured-event-image {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.featured-event-content {
|
||||
padding: var(--space-4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enhanced animations */
|
||||
.animate-slideInLeft {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
transition: all 0.5s var(--ease-out);
|
||||
}
|
||||
|
||||
.animate-slideInLeft.visible {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.animate-slideInRight {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
transition: all 0.5s var(--ease-out);
|
||||
}
|
||||
|
||||
.animate-slideInRight.visible {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Add animation classes when elements are in view
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
}
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
// Observe animated elements
|
||||
document.querySelectorAll('.animate-fadeInUp, .animate-slideInLeft, .animate-slideInRight').forEach(el => {
|
||||
observer.observe(el);
|
||||
});
|
||||
|
||||
// Add staggered animation delays
|
||||
document.querySelectorAll('.featured-event-card').forEach((card, index) => {
|
||||
card.style.transitionDelay = `${index * 0.2}s`;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
0
bin/brakeman
Executable file → Normal file
0
bin/brakeman
Executable file → Normal file
0
bin/docker-entrypoint
Executable file → Normal file
0
bin/docker-entrypoint
Executable file → Normal file
0
bin/rubocop
Executable file → Normal file
0
bin/rubocop
Executable file → Normal file
0
bin/thrust
Executable file → Normal file
0
bin/thrust
Executable file → Normal file
Reference in New Issue
Block a user