diversen
This commit is contained in:
+4
-3
@@ -1,10 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="nl">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/images/bikeservice_logo_primary.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vue + Laravel App</title>
|
||||
<meta name="description" content="Professionele fietsreparatie en onderhoudsdiensten" />
|
||||
<title>Bike Service - Jouw fiets, onze zorg</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<svg viewBox="0 0 600 250" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Main Logo Group -->
|
||||
<g transform="translate(300, 125)">
|
||||
<!-- Bike Icon -->
|
||||
<g transform="translate(-180, -30)">
|
||||
<!-- Rear wheel -->
|
||||
<circle cx="40" cy="45" r="30" fill="none" stroke="#ffffff" stroke-width="5"/>
|
||||
<circle cx="40" cy="45" r="20" fill="none" stroke="#ffffff" stroke-width="2" opacity="0.3"/>
|
||||
<circle cx="40" cy="45" r="3" fill="#ffffff"/>
|
||||
|
||||
<!-- Front wheel -->
|
||||
<circle cx="160" cy="45" r="30" fill="none" stroke="#ffffff" stroke-width="5"/>
|
||||
<circle cx="160" cy="45" r="20" fill="none" stroke="#ffffff" stroke-width="2" opacity="0.3"/>
|
||||
<circle cx="160" cy="45" r="3" fill="#ffffff"/>
|
||||
|
||||
<!-- Frame -->
|
||||
<path d="M 40 45 L 100 45 L 130 5 M 100 45 L 160 45"
|
||||
fill="none" stroke="#ffffff" stroke-width="5"
|
||||
stroke-linejoin="round" stroke-linecap="round"/>
|
||||
|
||||
<!-- Seat post and seat -->
|
||||
<path d="M 70 45 L 90 10" fill="none" stroke="#ffffff" stroke-width="5" stroke-linecap="round"/>
|
||||
<ellipse cx="90" cy="5" rx="12" ry="5" fill="#f0d9b5"/>
|
||||
|
||||
<!-- Handlebars -->
|
||||
<path d="M 130 5 L 145 5" fill="none" stroke="#ffffff" stroke-width="5" stroke-linecap="round"/>
|
||||
<circle cx="128" cy="5" r="4" fill="#ffffff"/>
|
||||
|
||||
<!-- Pedal area -->
|
||||
<circle cx="100" cy="45" r="8" fill="#f0d9b5"/>
|
||||
<path d="M 95 50 L 105 50" fill="none" stroke="#ffffff" stroke-width="3" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Text -->
|
||||
<text x="30" y="0" font-family="Arial, Helvetica, sans-serif" font-size="52" font-weight="bold" fill="#ffffff" letter-spacing="3">BIKE</text>
|
||||
<text x="30" y="50" font-family="Arial, Helvetica, sans-serif" font-size="48" font-weight="600" fill="#f0d9b5" letter-spacing="2">SERVICE</text>
|
||||
|
||||
<!-- Accent lines -->
|
||||
<line x1="-185" y1="68" x2="250" y2="68" stroke="#ffffff" stroke-width="3"/>
|
||||
<line x1="-185" y1="72" x2="250" y2="72" stroke="#f0d9b5" stroke-width="1.5"/>
|
||||
|
||||
<!-- Tagline -->
|
||||
<text x="32" y="100" font-family="Arial, Helvetica, sans-serif" font-size="16" font-style="italic" fill="#f0f0f0" letter-spacing="0.5">Jouw fiets, onze zorg</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,48 @@
|
||||
<svg viewBox="0 0 600 250" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- White background for clean export -->
|
||||
<rect width="600" height="250" fill="white"/>
|
||||
|
||||
<!-- Main Logo Group -->
|
||||
<g transform="translate(300, 125)">
|
||||
<!-- Bike Icon -->
|
||||
<g transform="translate(-180, -30)">
|
||||
<!-- Rear wheel -->
|
||||
<circle cx="40" cy="45" r="30" fill="none" stroke="#2c5f5d" stroke-width="5"/>
|
||||
<circle cx="40" cy="45" r="20" fill="none" stroke="#2c5f5d" stroke-width="2" opacity="0.3"/>
|
||||
<circle cx="40" cy="45" r="3" fill="#2c5f5d"/>
|
||||
|
||||
<!-- Front wheel -->
|
||||
<circle cx="160" cy="45" r="30" fill="none" stroke="#2c5f5d" stroke-width="5"/>
|
||||
<circle cx="160" cy="45" r="20" fill="none" stroke="#2c5f5d" stroke-width="2" opacity="0.3"/>
|
||||
<circle cx="160" cy="45" r="3" fill="#2c5f5d"/>
|
||||
|
||||
<!-- Frame -->
|
||||
<path d="M 40 45 L 100 45 L 130 5 M 100 45 L 160 45"
|
||||
fill="none" stroke="#2c5f5d" stroke-width="5"
|
||||
stroke-linejoin="round" stroke-linecap="round"/>
|
||||
|
||||
<!-- Seat post and seat -->
|
||||
<path d="M 70 45 L 90 10" fill="none" stroke="#2c5f5d" stroke-width="5" stroke-linecap="round"/>
|
||||
<ellipse cx="90" cy="5" rx="12" ry="5" fill="#8b6f47"/>
|
||||
|
||||
<!-- Handlebars -->
|
||||
<path d="M 130 5 L 145 5" fill="none" stroke="#2c5f5d" stroke-width="5" stroke-linecap="round"/>
|
||||
<circle cx="128" cy="5" r="4" fill="#2c5f5d"/>
|
||||
|
||||
<!-- Pedal area -->
|
||||
<circle cx="100" cy="45" r="8" fill="#8b6f47"/>
|
||||
<path d="M 95 50 L 105 50" fill="none" stroke="#2c5f5d" stroke-width="3" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Text -->
|
||||
<text x="30" y="0" font-family="Arial, Helvetica, sans-serif" font-size="52" font-weight="bold" fill="#2c5f5d" letter-spacing="3">BIKE</text>
|
||||
<text x="30" y="50" font-family="Arial, Helvetica, sans-serif" font-size="48" font-weight="600" fill="#8b6f47" letter-spacing="2">SERVICE</text>
|
||||
|
||||
<!-- Accent lines -->
|
||||
<line x1="-185" y1="68" x2="250" y2="68" stroke="#2c5f5d" stroke-width="3"/>
|
||||
<line x1="-185" y1="72" x2="250" y2="72" stroke="#8b6f47" stroke-width="1.5"/>
|
||||
|
||||
<!-- Tagline -->
|
||||
<text x="32" y="100" font-family="Arial, Helvetica, sans-serif" font-size="16" font-style="italic" fill="#666666" letter-spacing="0.5">Jouw fiets, onze zorg</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
+64
-11
@@ -3,7 +3,7 @@
|
||||
<nav class="navbar">
|
||||
<div class="nav-container">
|
||||
<router-link to="/" class="nav-logo">
|
||||
🚲 Fiets Service
|
||||
<img src="/images/bikeservice_logo_navbar.svg" alt="Bike Service Logo" class="logo-image" />
|
||||
</router-link>
|
||||
<div class="nav-menu">
|
||||
<router-link to="/" class="nav-link">Home</router-link>
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<main class="main-content">
|
||||
<router-view />
|
||||
</main>
|
||||
@@ -41,6 +41,19 @@ export default {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-color: #2c5f5d;
|
||||
--primary-dark: #1f4443;
|
||||
--primary-light: #3d7a77;
|
||||
--secondary-color: #8b6f47;
|
||||
--secondary-dark: #6d5637;
|
||||
--secondary-light: #a68a5f;
|
||||
--text-dark: #2c3e50;
|
||||
--text-gray: #666;
|
||||
--bg-light: #f5f5f5;
|
||||
--bg-white: #ffffff;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@@ -49,13 +62,13 @@ export default {
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: #f5f5f5;
|
||||
background-color: var(--bg-light);
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
|
||||
padding: 1rem 0;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
|
||||
padding: 0.5rem 0;
|
||||
box-shadow: 0 2px 10px rgba(44, 95, 93, 0.2);
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
@@ -68,15 +81,26 @@ body {
|
||||
}
|
||||
|
||||
.nav-logo {
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
height: 70px;
|
||||
width: auto;
|
||||
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.logo-image:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
@@ -84,11 +108,17 @@ body {
|
||||
text-decoration: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.nav-link.router-link-active {
|
||||
background-color: var(--secondary-color);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
@@ -96,4 +126,27 @@ body {
|
||||
margin: 2rem auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-container {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
height: 75px;
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
padding: 0.4rem 0.8rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+270
-21
@@ -135,18 +135,134 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Page Content Tab -->
|
||||
<div v-if="activeTab === 'content'" class="tab-content">
|
||||
<div class="section-header">
|
||||
<h2>Pagina Teksten Beheer</h2>
|
||||
</div>
|
||||
|
||||
<div class="content-sections">
|
||||
<!-- Home Page Hero -->
|
||||
<div class="content-section">
|
||||
<h3>Openingspagina - Hero Sectie</h3>
|
||||
<div class="content-form">
|
||||
<div class="form-group">
|
||||
<label>Hoofdtekst (Header)</label>
|
||||
<input type="text" :value="getContentValue('home_hero_title')" @input="updateContentValue('home_hero_title', $event.target.value)" @blur="savePageContent('home_hero_title')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Subtekst (Subheader)</label>
|
||||
<input type="text" :value="getContentValue('home_hero_subtitle')" @input="updateContentValue('home_hero_subtitle', $event.target.value)" @blur="savePageContent('home_hero_subtitle')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Home Page Features -->
|
||||
<div class="content-section">
|
||||
<h3>Openingspagina - Panelen</h3>
|
||||
<div class="content-form">
|
||||
<div class="feature-group">
|
||||
<h4>Paneel 1</h4>
|
||||
<div class="form-group">
|
||||
<label>Koptekst</label>
|
||||
<input type="text" :value="getContentValue('home_feature_1_title')" @input="updateContentValue('home_feature_1_title', $event.target.value)" @blur="savePageContent('home_feature_1_title')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Onderschrift</label>
|
||||
<textarea :value="getContentValue('home_feature_1_text')" @input="updateContentValue('home_feature_1_text', $event.target.value)" @blur="savePageContent('home_feature_1_text')" rows="2"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-group">
|
||||
<h4>Paneel 2</h4>
|
||||
<div class="form-group">
|
||||
<label>Koptekst</label>
|
||||
<input type="text" :value="getContentValue('home_feature_2_title')" @input="updateContentValue('home_feature_2_title', $event.target.value)" @blur="savePageContent('home_feature_2_title')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Onderschrift</label>
|
||||
<textarea :value="getContentValue('home_feature_2_text')" @input="updateContentValue('home_feature_2_text', $event.target.value)" @blur="savePageContent('home_feature_2_text')" rows="2"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-group">
|
||||
<h4>Paneel 3</h4>
|
||||
<div class="form-group">
|
||||
<label>Koptekst</label>
|
||||
<input type="text" :value="getContentValue('home_feature_3_title')" @input="updateContentValue('home_feature_3_title', $event.target.value)" @blur="savePageContent('home_feature_3_title')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Onderschrift</label>
|
||||
<textarea :value="getContentValue('home_feature_3_text')" @input="updateContentValue('home_feature_3_text', $event.target.value)" @blur="savePageContent('home_feature_3_text')" rows="2"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-group">
|
||||
<h4>Paneel 4</h4>
|
||||
<div class="form-group">
|
||||
<label>Koptekst</label>
|
||||
<input type="text" :value="getContentValue('home_feature_4_title')" @input="updateContentValue('home_feature_4_title', $event.target.value)" @blur="savePageContent('home_feature_4_title')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Onderschrift</label>
|
||||
<textarea :value="getContentValue('home_feature_4_text')" @input="updateContentValue('home_feature_4_text', $event.target.value)" @blur="savePageContent('home_feature_4_text')" rows="2"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Home Page CTA -->
|
||||
<div class="content-section">
|
||||
<h3>Openingspagina - Knoppen Container</h3>
|
||||
<div class="content-form">
|
||||
<div class="form-group">
|
||||
<label>Hoofdtekst</label>
|
||||
<input type="text" :value="getContentValue('home_cta_title')" @input="updateContentValue('home_cta_title', $event.target.value)" @blur="savePageContent('home_cta_title')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Subtekst</label>
|
||||
<textarea :value="getContentValue('home_cta_subtitle')" @input="updateContentValue('home_cta_subtitle', $event.target.value)" @blur="savePageContent('home_cta_subtitle')" rows="2"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Knop 1 Tekst</label>
|
||||
<input type="text" :value="getContentValue('home_cta_button_1_text')" @input="updateContentValue('home_cta_button_1_text', $event.target.value)" @blur="savePageContent('home_cta_button_1_text')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Knop 2 Tekst</label>
|
||||
<input type="text" :value="getContentValue('home_cta_button_2_text')" @input="updateContentValue('home_cta_button_2_text', $event.target.value)" @blur="savePageContent('home_cta_button_2_text')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Booking Page -->
|
||||
<div class="content-section">
|
||||
<h3>Boekingspagina - Header</h3>
|
||||
<div class="content-form">
|
||||
<div class="form-group">
|
||||
<label>Hoofdtekst (Header)</label>
|
||||
<input type="text" :value="getContentValue('booking_header_title')" @input="updateContentValue('booking_header_title', $event.target.value)" @blur="savePageContent('booking_header_title')" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Onderschrift</label>
|
||||
<textarea :value="getContentValue('booking_header_subtitle')" @input="updateContentValue('booking_header_subtitle', $event.target.value)" @blur="savePageContent('booking_header_subtitle')" rows="2"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Settings Tab -->
|
||||
<div v-if="activeTab === 'settings'" class="tab-content">
|
||||
<div class="section-header">
|
||||
<h2>Applicatie Instellingen</h2>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="settings-form">
|
||||
<div class="setting-group">
|
||||
<label for="admin_email">Beheer Notificatie E-mail</label>
|
||||
<input
|
||||
type="email"
|
||||
id="admin_email"
|
||||
<input
|
||||
type="email"
|
||||
id="admin_email"
|
||||
v-model="settings.admin_notification_email"
|
||||
placeholder="admin@voorbeeld.com"
|
||||
/>
|
||||
@@ -154,12 +270,12 @@
|
||||
💾
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="setting-group">
|
||||
<label for="business_name">Bedrijfsnaam</label>
|
||||
<input
|
||||
type="text"
|
||||
id="business_name"
|
||||
<input
|
||||
type="text"
|
||||
id="business_name"
|
||||
v-model="settings.business_name"
|
||||
placeholder="Fiets Service Centrum"
|
||||
/>
|
||||
@@ -381,6 +497,7 @@ export default {
|
||||
const blockedDates = ref([])
|
||||
const settings = ref({})
|
||||
const pricelist = ref([])
|
||||
const pageContent = ref([])
|
||||
|
||||
// Modal states
|
||||
const showRequestModal = ref(false)
|
||||
@@ -410,6 +527,7 @@ export default {
|
||||
{ id: 'requests', label: 'Service Aanvragen' },
|
||||
{ id: 'blocked', label: 'Geblokkeerde Data' },
|
||||
{ id: 'pricelist', label: 'Prijslijst' },
|
||||
{ id: 'content', label: 'Pagina Teksten' },
|
||||
{ id: 'settings', label: 'Instellingen' }
|
||||
]
|
||||
|
||||
@@ -516,6 +634,19 @@ export default {
|
||||
console.error('Failed to fetch pricelist:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const fetchPageContent = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/page-content', {
|
||||
headers: authStore.getAuthHeaders()
|
||||
})
|
||||
if (response.ok) {
|
||||
pageContent.value = await response.json()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch page content:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const refreshRequests = async () => {
|
||||
loading.value = true
|
||||
@@ -814,9 +945,9 @@ export default {
|
||||
|
||||
const deletePricelistItem = async (id) => {
|
||||
if (!confirm('Weet je zeker dat je dit prijslijst item wilt verwijderen?')) return
|
||||
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/pricelist/${id}`, {
|
||||
const response = await fetch(`/api/pricelist/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: authStore.getAuthHeaders()
|
||||
})
|
||||
@@ -827,6 +958,41 @@ export default {
|
||||
console.error('Failed to delete pricelist item:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Page content functions
|
||||
const getContentValue = (key) => {
|
||||
const content = pageContent.value.find(c => c.key === key)
|
||||
return content ? content.value : ''
|
||||
}
|
||||
|
||||
const updateContentValue = (key, value) => {
|
||||
const content = pageContent.value.find(c => c.key === key)
|
||||
if (content) {
|
||||
content.value = value
|
||||
}
|
||||
}
|
||||
|
||||
const savePageContent = async (key) => {
|
||||
const content = pageContent.value.find(c => c.key === key)
|
||||
if (!content) return
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/page-content/key/${key}`, {
|
||||
method: 'PUT',
|
||||
headers: authStore.getAuthHeaders(),
|
||||
body: JSON.stringify({
|
||||
value: content.value,
|
||||
description: content.description
|
||||
})
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
console.log(`Content ${key} updated successfully`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to update page content:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
const formatDateTime = (date, time) => {
|
||||
@@ -843,10 +1009,11 @@ export default {
|
||||
onMounted(() => {
|
||||
// Check authentication
|
||||
authStore.checkAuth()
|
||||
|
||||
|
||||
fetchRequests()
|
||||
fetchBlockedDates()
|
||||
fetchPricelist()
|
||||
fetchPageContent()
|
||||
fetchSettings()
|
||||
})
|
||||
|
||||
@@ -858,6 +1025,7 @@ export default {
|
||||
blockedDates,
|
||||
settings,
|
||||
pricelist,
|
||||
pageContent,
|
||||
user: computed(() => authStore.user),
|
||||
showRequestModal,
|
||||
showAddBlockedDate,
|
||||
@@ -905,6 +1073,9 @@ export default {
|
||||
updateRequestStatus,
|
||||
updateRequestDate,
|
||||
updateRequestTime,
|
||||
getContentValue,
|
||||
updateContentValue,
|
||||
savePageContent,
|
||||
formatDateTime,
|
||||
formatDate
|
||||
}
|
||||
@@ -924,13 +1095,13 @@ export default {
|
||||
}
|
||||
|
||||
.admin-header h1 {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.admin-header p {
|
||||
color: #666;
|
||||
color: var(--text-gray);
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -984,8 +1155,8 @@ export default {
|
||||
}
|
||||
|
||||
.tab-button.active {
|
||||
border-bottom-color: #3498db;
|
||||
color: #3498db;
|
||||
border-bottom-color: var(--primary-color);
|
||||
color: var(--primary-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -1008,12 +1179,12 @@ export default {
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.refresh-btn, .add-btn {
|
||||
background: #3498db;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
width: 40px;
|
||||
@@ -1029,9 +1200,9 @@ export default {
|
||||
}
|
||||
|
||||
.refresh-btn:hover:not(:disabled), .add-btn:hover {
|
||||
background: #2980b9;
|
||||
background: var(--primary-dark);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||
box-shadow: 0 4px 8px rgba(44, 95, 93, 0.3);
|
||||
}
|
||||
|
||||
.refresh-btn:disabled {
|
||||
@@ -1612,12 +1783,13 @@ export default {
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #3498db;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: #2980b9;
|
||||
background: var(--primary-dark);
|
||||
box-shadow: 0 4px 10px rgba(44, 95, 93, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@@ -1800,4 +1972,81 @@ export default {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Page Content Styles */
|
||||
.content-sections {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.content-section {
|
||||
background: #f8f9fa;
|
||||
padding: 1.5rem;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #e1e8ed;
|
||||
}
|
||||
|
||||
.content-section h3 {
|
||||
color: #2c3e50;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.content-section h4 {
|
||||
color: #2c3e50;
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.content-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.feature-group {
|
||||
background: white;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e1e8ed;
|
||||
}
|
||||
|
||||
.feature-group:not(:last-child) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.content-form .form-group {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.content-form .form-group label {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
margin-bottom: 0.5rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.content-form .form-group input,
|
||||
.content-form .form-group textarea {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 2px solid #e1e8ed;
|
||||
border-radius: 8px;
|
||||
font-size: 1rem;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.content-form .form-group input:focus,
|
||||
.content-form .form-group textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
background: #f8f9fa;
|
||||
box-shadow: 0 0 0 3px rgba(44, 95, 93, 0.1);
|
||||
}
|
||||
|
||||
.content-form .form-group textarea {
|
||||
resize: vertical;
|
||||
font-family: inherit;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="booking">
|
||||
<div class="booking-header">
|
||||
<h1>🚲 Boek Je Fiets Service</h1>
|
||||
<p>Vul het onderstaande formulier in om je fietsreparatie of onderhoud in te plannen</p>
|
||||
<h1>{{ content.booking_header_title || '🚲 Boek Je Fiets Service' }}</h1>
|
||||
<p>{{ content.booking_header_subtitle || 'Vul het onderstaande formulier in om je fietsreparatie of onderhoud in te plannen' }}</p>
|
||||
</div>
|
||||
|
||||
<div class="booking-form-container">
|
||||
@@ -181,7 +181,8 @@ export default {
|
||||
const formError = ref('')
|
||||
const showSuccessModal = ref(false)
|
||||
const submittedRequest = ref(null)
|
||||
|
||||
const content = ref({})
|
||||
|
||||
// Date picker state
|
||||
const currentDate = ref(new Date())
|
||||
const blockedDates = ref([])
|
||||
@@ -275,6 +276,17 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
const fetchContent = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/public/page-content')
|
||||
if (response.ok) {
|
||||
content.value = await response.json()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch page content:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const previousMonth = () => {
|
||||
currentDate.value = new Date(currentDate.value.getFullYear(), currentDate.value.getMonth() - 1, 1)
|
||||
}
|
||||
@@ -343,6 +355,7 @@ export default {
|
||||
tomorrow.setDate(tomorrow.getDate() + 1)
|
||||
form.value.requested_date = tomorrow.toISOString().split('T')[0]
|
||||
fetchBlockedDates() // Fetch blocked dates on mount
|
||||
fetchContent() // Fetch page content on mount
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -351,6 +364,7 @@ export default {
|
||||
formError,
|
||||
showSuccessModal,
|
||||
submittedRequest,
|
||||
content,
|
||||
minDate,
|
||||
submitForm,
|
||||
closeSuccessModal,
|
||||
@@ -379,13 +393,13 @@ export default {
|
||||
}
|
||||
|
||||
.booking-header h1 {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.booking-header p {
|
||||
color: #666;
|
||||
color: var(--text-gray);
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
@@ -419,7 +433,7 @@ export default {
|
||||
|
||||
.form-group label {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
@@ -435,7 +449,8 @@ export default {
|
||||
.form-group input:focus,
|
||||
.form-group textarea:focus {
|
||||
outline: none;
|
||||
border-color: #3498db;
|
||||
border-color: var(--primary-color);
|
||||
box-shadow: 0 0 0 3px rgba(44, 95, 93, 0.1);
|
||||
}
|
||||
|
||||
.form-group textarea {
|
||||
@@ -476,7 +491,7 @@ export default {
|
||||
|
||||
.current-month {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
@@ -492,7 +507,7 @@ export default {
|
||||
padding: 0.75rem;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
@@ -537,14 +552,15 @@ export default {
|
||||
}
|
||||
|
||||
.calendar-date.selected {
|
||||
background: #3498db;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.calendar-date.today {
|
||||
font-weight: bold;
|
||||
color: #3498db;
|
||||
color: var(--primary-color);
|
||||
border: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.calendar-date.today.selected {
|
||||
@@ -566,7 +582,7 @@ export default {
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
background: #3498db;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 1rem 2rem;
|
||||
@@ -574,11 +590,14 @@ export default {
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 10px rgba(44, 95, 93, 0.3);
|
||||
}
|
||||
|
||||
.submit-btn:hover:not(:disabled) {
|
||||
background: #2980b9;
|
||||
background: var(--primary-dark);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(44, 95, 93, 0.4);
|
||||
}
|
||||
|
||||
.submit-btn:disabled {
|
||||
@@ -615,7 +634,7 @@ export default {
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
@@ -634,18 +653,21 @@ export default {
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #3498db;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
transition: background-color 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 6px rgba(44, 95, 93, 0.3);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: #2980b9;
|
||||
background: var(--primary-dark);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 10px rgba(44, 95, 93, 0.4);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
+63
-32
@@ -1,46 +1,70 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<div class="hero">
|
||||
<h1>🚲 Welkom bij Fiets Service Centrum</h1>
|
||||
<p>Professionele fietsreparatie en onderhoudsdiensten</p>
|
||||
<h1>{{ content.home_hero_title || 'Welkom bij Fiets Service Centrum' }}</h1>
|
||||
<p>{{ content.home_hero_subtitle || 'Professionele fietsreparatie en onderhoudsdiensten' }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="features">
|
||||
<div class="feature-card">
|
||||
<h3>🔧 Deskundige Reparaties</h3>
|
||||
<p>Professionele fietsmonteurs met jarenlange ervaring</p>
|
||||
<h3>{{ content.home_feature_1_title || '🔧 Deskundige Reparaties' }}</h3>
|
||||
<p>{{ content.home_feature_1_text || 'Professionele fietsmonteurs met jarenlange ervaring' }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="feature-card">
|
||||
<h3>⚡ Snelle Service</h3>
|
||||
<p>Snelle doorlooptijden voor de meeste reparaties</p>
|
||||
<h3>{{ content.home_feature_2_title || '⚡ Snelle Service' }}</h3>
|
||||
<p>{{ content.home_feature_2_text || 'Snelle doorlooptijden voor de meeste reparaties' }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="feature-card">
|
||||
<h3>💰 Eerlijke Prijzen</h3>
|
||||
<p>Concurrerende tarieven zonder verborgen kosten</p>
|
||||
<h3>{{ content.home_feature_3_title || '💰 Eerlijke Prijzen' }}</h3>
|
||||
<p>{{ content.home_feature_3_text || 'Concurrerende tarieven zonder verborgen kosten' }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="feature-card">
|
||||
<h3>📅 Eenvoudig Boeken</h3>
|
||||
<p>Eenvoudig online boekingssysteem</p>
|
||||
<h3>{{ content.home_feature_4_title || '📅 Eenvoudig Boeken' }}</h3>
|
||||
<p>{{ content.home_feature_4_text || 'Eenvoudig online boekingssysteem' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="cta">
|
||||
<h2>Klaar om je fiets te laten repareren?</h2>
|
||||
<p>Boek je afspraak online en krijg je fiets weer in topconditie.</p>
|
||||
<h2>{{ content.home_cta_title || 'Klaar om je fiets te laten repareren?' }}</h2>
|
||||
<p>{{ content.home_cta_subtitle || 'Boek je afspraak online en krijg je fiets weer in topconditie.' }}</p>
|
||||
<div class="cta-buttons">
|
||||
<router-link to="/booking" class="cta-button">Nu Service Boeken</router-link>
|
||||
<router-link to="/pricelist" class="cta-button secondary">💰 Prijslijst Bekijken</router-link>
|
||||
<router-link to="/booking" class="cta-button">{{ content.home_cta_button_1_text || 'Nu Service Boeken' }}</router-link>
|
||||
<router-link to="/pricelist" class="cta-button secondary">{{ content.home_cta_button_2_text || '💰 Prijslijst Bekijken' }}</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'Home'
|
||||
name: 'Home',
|
||||
setup() {
|
||||
const content = ref({})
|
||||
|
||||
const fetchContent = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/public/page-content')
|
||||
if (response.ok) {
|
||||
content.value = await response.json()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch page content:', error)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchContent()
|
||||
})
|
||||
|
||||
return {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -50,11 +74,12 @@ export default {
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
|
||||
color: white;
|
||||
padding: 4rem 2rem;
|
||||
border-radius: 15px;
|
||||
margin-bottom: 3rem;
|
||||
box-shadow: 0 4px 20px rgba(44, 95, 93, 0.3);
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
@@ -87,30 +112,31 @@ export default {
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.feature-card p {
|
||||
color: #666;
|
||||
color: var(--text-gray);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.cta {
|
||||
background: #f8f9fa;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
||||
padding: 3rem 2rem;
|
||||
border-radius: 15px;
|
||||
border: 2px dashed #3498db;
|
||||
border: 3px solid var(--primary-color);
|
||||
box-shadow: 0 4px 20px rgba(44, 95, 93, 0.15);
|
||||
}
|
||||
|
||||
.cta h2 {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.cta p {
|
||||
color: #666;
|
||||
color: var(--text-gray);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
@@ -123,25 +149,30 @@ export default {
|
||||
|
||||
.cta-button {
|
||||
display: inline-block;
|
||||
background: #3498db;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
padding: 1rem 2rem;
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
transition: background-color 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 10px rgba(44, 95, 93, 0.3);
|
||||
}
|
||||
|
||||
.cta-button:hover {
|
||||
background: #2980b9;
|
||||
background: var(--primary-dark);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(44, 95, 93, 0.4);
|
||||
}
|
||||
|
||||
.cta-button.secondary {
|
||||
background: #e74c3c;
|
||||
background: var(--secondary-color);
|
||||
box-shadow: 0 4px 10px rgba(139, 111, 71, 0.3);
|
||||
}
|
||||
|
||||
.cta-button.secondary:hover {
|
||||
background: #c0392b;
|
||||
background: var(--secondary-dark);
|
||||
box-shadow: 0 6px 15px rgba(139, 111, 71, 0.4);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -114,7 +114,7 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
@@ -133,13 +133,13 @@ export default {
|
||||
}
|
||||
|
||||
.login-header h1 {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.login-header p {
|
||||
color: #666;
|
||||
color: var(--text-gray);
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ export default {
|
||||
|
||||
.form-group label {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,8 @@ export default {
|
||||
|
||||
.form-group input:focus {
|
||||
outline: none;
|
||||
border-color: #3498db;
|
||||
border-color: var(--primary-color);
|
||||
box-shadow: 0 0 0 3px rgba(44, 95, 93, 0.1);
|
||||
}
|
||||
|
||||
.form-group input:disabled {
|
||||
@@ -190,7 +191,7 @@ export default {
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
background: #3498db;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 1rem;
|
||||
@@ -198,11 +199,14 @@ export default {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 10px rgba(44, 95, 93, 0.3);
|
||||
}
|
||||
|
||||
.login-btn:hover:not(:disabled) {
|
||||
background: #2980b9;
|
||||
background: var(--primary-dark);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 15px rgba(44, 95, 93, 0.4);
|
||||
}
|
||||
|
||||
.login-btn:disabled {
|
||||
@@ -225,7 +229,7 @@ export default {
|
||||
}
|
||||
|
||||
.login-info strong {
|
||||
color: #2c3e50;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
|
||||
Reference in New Issue
Block a user