Initial commit

This commit is contained in:
2026-08-20 16:48:16 +02:00
commit a5e5f7f9a9
54 changed files with 351 additions and 0 deletions
+256
View File
@@ -0,0 +1,256 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1973 Jaguar E-Type Roadster</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<!-- ================= Schema.org Vehicle Markup ================= -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Vehicle",
"name": "1973 Jaguar E-Type Series III Roadster",
"brand": {
"@type": "Brand",
"name": "Jaguar"
},
"model": "E-Type Series III",
"vehicleModelDate": "1973",
"vehicleConfiguration": "Roadster",
"bodyType": "Convertible",
"vehicleEngine": {
"@type": "EngineSpecification",
"engineType": "V12",
"engineDisplacement": {
"@type": "QuantitativeValue",
"value": 5.3,
"unitCode": "LTR"
}
},
"vehicleTransmission": "Automatic",
"fuelType": "Petrol",
"color": "Red",
"itemCondition": "https://schema.org/UsedCondition",
"offers": {
"@type": "Offer",
"price": "65000",
"priceCurrency": "CHF",
"availability": "https://schema.org/InStock",
"seller": {
"@type": "Person",
"name": "Private Seller"
}
},
"additionalProperty": [
{ "@type": "PropertyValue", "name": "Condition", "value": "Very Good" },
{ "@type": "PropertyValue", "name": "Import History", "value": "US import 1980" },
{ "@type": "PropertyValue", "name": "Heritage", "value": "Jaguar Heritage Certificate" },
{ "@type": "PropertyValue", "name": "Hardtop", "value": "Removable Hardtop" },
{ "@type": "PropertyValue", "name": "Technical Inspection", "value": "Swiss Technical Control" }
]
}
</script>
<!-- ============================================================ -->
<style>
body { margin:0; font-family:"Segoe UI",Arial,sans-serif; background:#f5f6f8; color:#333; }
header { background:#c62828; color:white; padding:40px 20px; position:relative; text-align:center; }
.lang-switch { position:absolute; top:15px; right:20px; display:flex; gap:12px; }
.lang-btn { cursor:pointer; opacity:.6; text-align:center; }
.lang-btn.active { opacity:1; }
.lang-btn img { width:32px; height:22px; }
.lang-indicator { height:3px; background:white; margin-top:4px; opacity:0; }
.lang-btn.active .lang-indicator { opacity:1; }
section { max-width:1100px; margin:40px auto; padding:0 20px; }
.card { background:white; border-radius:6px; padding:30px; margin-bottom:35px; box-shadow:0 6px 16px rgba(0,0,0,.08); }
.price { font-size:34px; color:#c62828; }
.badge { background:#e0e0e0; padding:6px 12px; border-radius:20px; font-size:13px; }
.specs { display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:15px; }
.spec { background:#f1f1f1; padding:15px; text-align:center; border-radius:5px; }
.carousel { position:relative; height:260px; overflow:hidden; }
.carousel img { position:absolute; inset:0; margin:auto; max-width:100%; max-height:100%; opacity:0; transition:.8s; cursor:pointer; }
.carousel img.active { opacity:1; position:relative; }
.dots { display:flex; justify-content:center; gap:8px; margin-top:12px; }
.dot { width:10px; height:10px; border-radius:50%; background:#ccc; cursor:pointer; }
.dot.active { background:#c62828; }
.fullscreen { position:fixed; inset:0; background:rgba(0,0,0,.95); display:flex; align-items:center; justify-content:center; z-index:9999; }
.fullscreen img { max-width:95%; max-height:95%; }
.close-btn,.arrow { position:absolute; color:white; font-size:2rem; cursor:pointer; }
.close-btn { top:20px; right:25px; }
.arrow-left { left:20px; }
.arrow-right { right:20px; }
.links a { display:block; padding:14px; background:#f1f1f1; margin-bottom:8px; text-decoration:none; color:#333; border-radius:5px; }
.whatsapp-form input,.whatsapp-form textarea { width:100%; padding:12px; margin-bottom:10px; }
.whatsapp-form button { background:#25d366; border:none; color:white; padding:14px; font-size:16px; cursor:pointer; width:100%; }
.call-box { text-align:center; font-size:18px; }
.call-box a { display:inline-block; margin-top:10px; font-size:22px; color:#c62828; text-decoration:none; }
footer { background:#222; color:#aaa; text-align:center; padding:25px; }
</style>
</head>
<body>
<div id="app">
<header>
<div class="lang-switch">
<div class="lang-btn" :class="{active:lang==='en'}" @click="setLang('en')">
<img src="https://flagcdn.com/w40/gb.png"><div class="lang-indicator"></div>
</div>
<div class="lang-btn" :class="{active:lang==='fr'}" @click="setLang('fr')">
<img src="https://flagcdn.com/w40/fr.png"><div class="lang-indicator"></div>
</div>
</div>
<h1>{{ t.title }}</h1>
<p>{{ t.subtitle }}</p>
</header>
<section>
<div class="card">
<h2>{{ t.overview }}</h2>
<span class="badge">{{ t.privateSeller }}</span>
<p>{{ t.description }}</p>
<div class="price">CHF 65'000</div>
</div>
<div class="card">
<h2>{{ t.specs }}</h2>
<div class="specs">
<div class="spec" v-for="s in specifications" :key="s">{{ s }}</div>
</div>
</div>
</section>
<section v-if="photos.length">
<div class="card">
<h2>{{ t.photos }}</h2>
<div class="carousel">
<img v-for="(img,i) in photos"
:key="img"
:src="'photos/'+img"
:class="{active:i===activeIndex}"
loading="lazy"
@click="openFullscreen(i)">
</div>
<div class="dots">
<div v-for="(img,i) in photos"
:key="i"
class="dot"
:class="{active:i===activeIndex}"
@click="activeIndex=i"></div>
</div>
</div>
</section>
<section>
<div class="card">
<h2>{{ t.links }}</h2>
<div class="links">
<a v-for="l in links" :key="l.url" :href="l.url" target="_blank">{{ l.label }}</a>
</div>
</div>
</section>
<section>
<div class="card call-box">
<h2>{{ t.callTitle }}</h2>
<p>{{ t.callText }}</p>
<a href="tel:+41793758510">📞 +41 79 375 8510</a>
</div>
</section>
<section>
<div class="card">
<h2>{{ t.contactTitle }}</h2>
<form class="whatsapp-form" @submit.prevent="openWhatsApp">
<input v-model="form.name" :placeholder="t.name" required>
<input v-model="form.phone" :placeholder="t.phone" required>
<textarea v-model="form.message" rows="4"></textarea>
<button type="submit">{{ t.whatsapp }}</button>
</form>
</div>
</section>
<footer>© 2025 Private Classic Car Sale</footer>
<div v-if="fullscreen" class="fullscreen">
<span class="close-btn" @click="fullscreen=false">×</span>
<span class="arrow arrow-left" @click="prev">‹</span>
<img :src="'photos/'+photos[activeIndex]">
<span class="arrow arrow-right" @click="next">›</span>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
lang:'en',
photos:[],
specifications:[],
links:[],
activeIndex:0,
fullscreen:false,
form:{name:'',phone:'',message:''},
translations:{
en:{ title:"1973 Jaguar E-Type Roadster", subtitle:"Iconic British Classic • V12 • Roadster",
overview:"Overview", privateSeller:"Private Seller", specs:"Specifications",
photos:"Photos", links:"Related Links & References",
callTitle:"Call the Owner", callText:"For direct inquiries, please call the owner:",
contactTitle:"Contact via WhatsApp", name:"Your name", phone:"Your phone number",
whatsapp:"Contact via WhatsApp",
description:"Privately owned 1973 Jaguar E-Type Roadster in red, featuring the legendary V12 engine."},
fr:{ title:"Jaguar E-Type Roadster 1973", subtitle:"Icône britannique • V12 • Roadster",
overview:"Présentation", privateSeller:"Vente privée", specs:"Caractéristiques",
photos:"Photos", links:"Liens et références",
callTitle:"Appeler le propriétaire", callText:"Pour toute demande directe, veuillez appeler le propriétaire :",
contactTitle:"Contact via WhatsApp", name:"Votre nom", phone:"Votre numéro de téléphone",
whatsapp:"Contacter via WhatsApp",
description:"Jaguar E-Type Roadster de 1973, propriété privée, en rouge, équipée du légendaire moteur V12."}
}
};
},
computed:{ t(){ return this.translations[this.lang]; }},
methods:{
loadData(){
fetch(`specifications_${this.lang}.json`).then(r=>r.json()).then(j=>this.specifications=j);
fetch(`links_${this.lang}.json`).then(r=>r.json()).then(j=>this.links=j);
},
setLang(l){ this.lang=l; this.loadData(); },
openFullscreen(i){ this.activeIndex=i; this.fullscreen=true; },
next(){ this.activeIndex=(this.activeIndex+1)%this.photos.length; },
prev(){ this.activeIndex=(this.activeIndex-1+this.photos.length)%this.photos.length; },
openWhatsApp(){
const t=`${this.form.name} (${this.form.phone}): ${this.form.message}`;
window.open(`https://wa.me/41793758510?text=${encodeURIComponent(t)}`);
}
},
mounted(){
fetch("photos.json").then(r=>r.json()).then(j=>this.photos=j);
this.loadData();
}
}).mount("#app");
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-WKE9H4BLN3"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-WKE9H4BLN3');
</script>
</body>
</html>
Executable
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env sh
PHOTOS_DIR="photos"
OUTPUT_FILE="photos.json"
# Check photos directory exists
if [ ! -d "$PHOTOS_DIR" ]; then
echo "Error: '$PHOTOS_DIR' directory not found."
exit 1
fi
# Start JSON array
printf "[\n" > "$OUTPUT_FILE"
# Collect JPG files (case-insensitive), sorted
# Works on macOS + Linux
FILES=$(ls -1 "$PHOTOS_DIR" 2>/dev/null | grep -i '\.jpg$' | sort)
COUNT=0
TOTAL=$(printf "%s\n" "$FILES" | grep -c .)
printf "%s\n" "$FILES" | while IFS= read -r FILE; do
COUNT=$((COUNT + 1))
if [ "$COUNT" -lt "$TOTAL" ]; then
printf " \"%s\",\n" "$FILE" >> "$OUTPUT_FILE"
else
printf " \"%s\"\n" "$FILE" >> "$OUTPUT_FILE"
fi
done
# End JSON array
printf "]\n" >> "$OUTPUT_FILE"
echo "Generated $OUTPUT_FILE with $TOTAL image(s)."
+6
View File
@@ -0,0 +1,6 @@
[
{ "label": "Bring a Trailer – Jaguar E-Type Series III", "url": "https://bringatrailer.com/jaguar/xke-series-iii/" },
{ "label": "Jaguar E-Type Documentary (YouTube)", "url": "https://www.youtube.com/watch?v=iihVaoxD_aY" },
{ "label": "Jaguar E-Type Review (YouTube)", "url": "https://www.youtube.com/watch?v=YqaZR8DmFFc" }
]
+6
View File
@@ -0,0 +1,6 @@
[
{ "label": "Bring a Trailer – Jaguar E-Type Série III", "url": "https://bringatrailer.com/jaguar/xke-series-iii/" },
{ "label": "Documentaire Jaguar E-Type (YouTube)", "url": "https://www.youtube.com/watch?v=iihVaoxD_aY" },
{ "label": "Essai Jaguar E-Type (YouTube)", "url": "https://www.youtube.com/watch?v=YqaZR8DmFFc" }
]
+18
View File
@@ -0,0 +1,18 @@
[
"IMG_0000.jpg",
"IMG_8742.jpg",
"IMG_8744.jpg",
"IMG_8745.jpg",
"IMG_8749.jpg",
"IMG_8998 2.jpg",
"IMG_8998.jpg",
"IMG_9290.jpg",
"IMG_9294.jpg",
"IMG_9296.jpg",
"IMG_9301.jpg",
"IMG_9341.jpg",
"IMG_9602.jpg",
"IMG_9603.jpg",
"IMG_9604.jpg",
"JAG1.jpg"
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

+13
View File
@@ -0,0 +1,13 @@
[
"Year: 1973",
"Engine: 5.3L V12",
"Transmission: Automatic",
"Exterior: Red",
"Body Style: Roadster",
"Condition: Very Good",
"Removable Hardtop",
"Jaguar Heritage Certificate",
"US import 1980",
"Swiss Technical Control"
]
+13
View File
@@ -0,0 +1,13 @@
[
"Année : 1973",
"Moteur : V12 5.3L",
"Transmission : Automatique",
"Couleur extérieure : Rouge",
"Type de carrosserie : Roadster",
"État : Très bon",
"Hardtop amovible",
"Certificat Jaguar Heritage",
"Importation américaine 1980",
"Expertisé"
]