Set up modern PHP MVC project structure for GetYourBand platform
- Implemented clean MVC architecture with Router, Controller, and Model base classes - Created database migrations for users, bands, bookings, reviews, and availability - Set up Tailwind CSS with yellow color scheme and modern design - Added Alpine.js for reactive JavaScript components - Configured Vite for asset building and hot module replacement - Created authentication and role-based middleware - Implemented helper functions and configuration system - Added comprehensive README with setup instructions - Configured Apache with proper rewrite rules and security headers - Set up Composer and npm package management with modern dependencies
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
@apply scroll-smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-gray-50 text-gray-900 antialiased;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-4 py-2 rounded-lg font-medium transition-all duration-200 inline-flex items-center justify-center;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply bg-primary-500 text-white hover:bg-primary-600 active:bg-primary-700;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply bg-gray-200 text-gray-800 hover:bg-gray-300 active:bg-gray-400;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply bg-white rounded-xl shadow-md p-6 transition-shadow hover:shadow-lg;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
@apply w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent;
|
||||
}
|
||||
|
||||
.badge {
|
||||
@apply inline-flex items-center px-3 py-1 rounded-full text-sm font-medium;
|
||||
}
|
||||
|
||||
.badge-yellow {
|
||||
@apply bg-accent-100 text-accent-800;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-balance {
|
||||
text-wrap: balance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import Alpine from 'alpinejs';
|
||||
|
||||
// Make Alpine available globally
|
||||
window.Alpine = Alpine;
|
||||
|
||||
// Alpine Components
|
||||
Alpine.data('searchBands', () => ({
|
||||
query: '',
|
||||
filters: {
|
||||
genre: '',
|
||||
location: '',
|
||||
priceMin: '',
|
||||
priceMax: '',
|
||||
},
|
||||
results: [],
|
||||
loading: false,
|
||||
|
||||
init() {
|
||||
console.log('Search component initialized');
|
||||
},
|
||||
|
||||
async search() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
q: this.query,
|
||||
...this.filters
|
||||
});
|
||||
const response = await fetch(`/api/bands/search?${params}`);
|
||||
this.results = await response.json();
|
||||
} catch (error) {
|
||||
console.error('Search error:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
Alpine.data('bookingForm', () => ({
|
||||
formData: {
|
||||
bandId: '',
|
||||
eventDate: '',
|
||||
location: '',
|
||||
budget: '',
|
||||
eventType: '',
|
||||
message: ''
|
||||
},
|
||||
submitting: false,
|
||||
|
||||
async submit() {
|
||||
this.submitting = true;
|
||||
try {
|
||||
const response = await fetch('/api/bookings', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(this.formData)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('Buchungsanfrage erfolgreich gesendet!');
|
||||
this.reset();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Booking error:', error);
|
||||
alert('Es gab einen Fehler. Bitte versuchen Sie es erneut.');
|
||||
} finally {
|
||||
this.submitting = false;
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.formData = {
|
||||
bandId: '',
|
||||
eventDate: '',
|
||||
location: '',
|
||||
budget: '',
|
||||
eventType: '',
|
||||
message: ''
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
// Initialize Alpine
|
||||
Alpine.start();
|
||||
|
||||
// Smooth scroll for anchor links
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(this.getAttribute('href'));
|
||||
if (target) {
|
||||
target.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user