Chore/marco changes #3
+9
-12
@@ -170,20 +170,17 @@
|
||||
<form class="admin-form" id="vehicleForm">
|
||||
<input type="hidden" name="vid" />
|
||||
|
||||
<div class="admin-photo-preview" id="photoPreview"></div>
|
||||
<label>
|
||||
<span data-i18n="adminPhotoUpload">Hauptfoto hochladen (JPG/PNG/WebP, max 50 MB)</span>
|
||||
<input type="file" id="photoInput" accept="image/*" />
|
||||
</label>
|
||||
<div class="admin-photo-upload-zone" id="photoUploadZone">
|
||||
<div class="admin-photo-upload-content">
|
||||
<span class="admin-photo-upload-icon">📷</span>
|
||||
<span>Fotos hochladen (JPG/PNG/WebP, max 50 MB)</span>
|
||||
<span class="muted" style="font-size:0.85rem;">Klicken oder Dateien hierher ziehen · Mehrfachauswahl möglich</span>
|
||||
</div>
|
||||
<input type="file" id="photoInput" accept="image/*" multiple />
|
||||
</div>
|
||||
<input type="hidden" name="photo_url" />
|
||||
|
||||
<div style="margin-top:1.2rem;">
|
||||
<label>
|
||||
<span>Weitere Fotos hinzufügen</span>
|
||||
<input type="file" id="extraPhotoInput" accept="image/*" multiple />
|
||||
</label>
|
||||
<div id="extraPhotoGallery" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:0.5rem;margin-top:0.5rem;"></div>
|
||||
</div>
|
||||
<div class="admin-photo-gallery" id="extraPhotoGallery"></div>
|
||||
|
||||
<div class="row2">
|
||||
<label><span data-i18n="adminBrand">Marke</span><input name="brand" required /></label>
|
||||
|
||||
+169
-58
@@ -52,8 +52,7 @@ const formTitle = document.querySelector("#formTitle");
|
||||
const saveBtn = document.querySelector("#saveBtn");
|
||||
const resetBtn = document.querySelector("#resetBtn");
|
||||
const photoInput = document.querySelector("#photoInput");
|
||||
const photoPreview = document.querySelector("#photoPreview");
|
||||
const extraPhotoInput = document.querySelector("#extraPhotoInput");
|
||||
const photoUploadZone = document.querySelector("#photoUploadZone");
|
||||
const extraPhotoGallery = document.querySelector("#extraPhotoGallery");
|
||||
const tableBody = document.querySelector("#adminTable tbody");
|
||||
|
||||
@@ -324,7 +323,6 @@ function loadForEdit(id) {
|
||||
vehicleForm.photo_url.value = v.photo_url;
|
||||
vehicleForm.is_active.checked = v.is_active;
|
||||
state.currentPhotoPath = v.photo_path || null;
|
||||
updatePreview(v.photo_url);
|
||||
loadVehiclePhotos(v.id);
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}
|
||||
@@ -342,7 +340,6 @@ resetBtn.addEventListener("click", () => {
|
||||
vehicleForm.price_per_km_eur.value = 1.50;
|
||||
state.currentPhotoPath = null;
|
||||
state.vehiclePhotos = [];
|
||||
updatePreview("");
|
||||
formTitle.textContent = "Neues Fahrzeug";
|
||||
formFeedback.textContent = "";
|
||||
});
|
||||
@@ -408,36 +405,8 @@ async function deleteVehicle(id) {
|
||||
renderVehicles();
|
||||
}
|
||||
|
||||
// Photo upload
|
||||
photoInput.addEventListener("change", async () => {
|
||||
const file = photoInput.files?.[0];
|
||||
if (!file) return;
|
||||
formFeedback.className = "form-feedback";
|
||||
formFeedback.textContent = "Uploading photo...";
|
||||
try {
|
||||
// Delete old photo if exists
|
||||
if (state.currentPhotoPath) {
|
||||
await supabase.storage.from("vehicle-photos").remove([state.currentPhotoPath]);
|
||||
}
|
||||
const ext = (file.name.split(".").pop() || "jpg").toLowerCase();
|
||||
const path = `${crypto.randomUUID()}.${ext}`;
|
||||
const { error: upErr } = await supabase.storage
|
||||
.from("vehicle-photos")
|
||||
.upload(path, file, { contentType: file.type, upsert: true });
|
||||
if (upErr) throw upErr;
|
||||
const { data: pub } = supabase.storage.from("vehicle-photos").getPublicUrl(path);
|
||||
state.currentPhotoPath = path;
|
||||
vehicleForm.photo_url.value = pub.publicUrl;
|
||||
updatePreview(pub.publicUrl);
|
||||
formFeedback.textContent = "Upload ok.";
|
||||
} catch (err) {
|
||||
formFeedback.className = "form-feedback error";
|
||||
formFeedback.textContent = err.message || String(err);
|
||||
}
|
||||
});
|
||||
function updatePreview(url) { photoPreview.style.backgroundImage = url ? `url('${url}')` : ""; }
|
||||
// ----- Unified Photo Upload + Gallery -----
|
||||
|
||||
// ----- Vehicle Photo Gallery -----
|
||||
async function loadVehiclePhotos(vehicleId) {
|
||||
if (!vehicleId) {
|
||||
state.vehiclePhotos = [];
|
||||
@@ -457,33 +426,136 @@ async function loadVehiclePhotos(vehicleId) {
|
||||
function renderExtraPhotoGallery() {
|
||||
if (!extraPhotoGallery) return;
|
||||
extraPhotoGallery.innerHTML = "";
|
||||
for (const ph of state.vehiclePhotos) {
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.style.cssText = "position:relative;border-radius:8px;overflow:hidden;aspect-ratio:16/10;background:#1a1a1a;";
|
||||
wrapper.innerHTML = `
|
||||
<img src="${attr(ph.photo_url)}" style="width:100%;height:100%;object-fit:cover;" />
|
||||
<div style="position:absolute;top:2px;right:2px;display:flex;gap:2px;">
|
||||
${!ph.is_primary ? `<button type="button" style="cursor:pointer;background:#f59e0b;color:#000;border:none;border-radius:4px;padding:1px 4px;font-size:10px;font-weight:700;" data-set-primary="${ph.id}">★</button>` : ''}
|
||||
<button type="button" style="cursor:pointer;background:#ef4444;color:#fff;border:none;border-radius:4px;padding:1px 4px;font-size:10px;font-weight:700;" data-delete-photo="${ph.id}">×</button>
|
||||
const photos = state.vehiclePhotos;
|
||||
if (!photos.length) return;
|
||||
|
||||
for (let i = 0; i < photos.length; i++) {
|
||||
const ph = photos[i];
|
||||
const card = document.createElement("div");
|
||||
card.className = "admin-photo-card";
|
||||
card.draggable = true;
|
||||
card.dataset.photoId = ph.id;
|
||||
card.dataset.photoIdx = i;
|
||||
card.innerHTML = `
|
||||
<img src="${attr(ph.photo_url)}" alt="Foto ${i + 1}" />
|
||||
<div class="admin-photo-card-arrows">
|
||||
<button type="button" class="admin-photo-arrow" data-move-dir="-1" ${i === 0 ? 'disabled style="opacity:0.3;pointer-events:none;"' : ''} aria-label="Nach links verschieben">‹</button>
|
||||
<button type="button" class="admin-photo-arrow" data-move-dir="1" ${i === photos.length - 1 ? 'disabled style="opacity:0.3;pointer-events:none;"' : ''} aria-label="Nach rechts verschieben">›</button>
|
||||
</div>
|
||||
${ph.is_primary ? '<span style="position:absolute;bottom:2px;left:2px;background:#22c55e;color:#fff;border-radius:4px;padding:1px 4px;font-size:9px;font-weight:700;">Hauptfoto</span>' : ''}
|
||||
<div class="admin-photo-card-actions">
|
||||
${!ph.is_primary ? `<button type="button" class="admin-photo-set-primary" data-photo-id="${ph.id}" aria-label="Als Hauptfoto setzen">★</button>` : ''}
|
||||
<button type="button" class="admin-photo-delete" data-photo-id="${ph.id}" aria-label="Foto löschen">×</button>
|
||||
</div>
|
||||
${ph.is_primary ? '<span class="admin-photo-badge">Hauptfoto</span>' : ''}
|
||||
<span class="admin-photo-drag-handle" aria-hidden="true">⠿</span>
|
||||
`;
|
||||
extraPhotoGallery.appendChild(wrapper);
|
||||
extraPhotoGallery.appendChild(card);
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
extraPhotoGallery.querySelectorAll("[data-delete-photo]").forEach(btn => {
|
||||
// Action buttons
|
||||
extraPhotoGallery.querySelectorAll(".admin-photo-delete").forEach(btn => {
|
||||
btn.addEventListener("click", async () => {
|
||||
const phId = btn.dataset.deletePhoto;
|
||||
await deleteVehiclePhoto(phId);
|
||||
await deleteVehiclePhoto(btn.dataset.photoId);
|
||||
});
|
||||
});
|
||||
extraPhotoGallery.querySelectorAll("[data-set-primary]").forEach(btn => {
|
||||
extraPhotoGallery.querySelectorAll(".admin-photo-set-primary").forEach(btn => {
|
||||
btn.addEventListener("click", async () => {
|
||||
const phId = btn.dataset.setPrimary;
|
||||
await setPrimaryPhoto(phId);
|
||||
await setPrimaryPhoto(btn.dataset.photoId);
|
||||
});
|
||||
});
|
||||
extraPhotoGallery.querySelectorAll(".admin-photo-arrow").forEach(btn => {
|
||||
btn.addEventListener("click", async () => {
|
||||
const card = btn.closest(".admin-photo-card");
|
||||
const idx = +card.dataset.photoIdx;
|
||||
const dir = +btn.dataset.moveDir;
|
||||
await reorderPhoto(idx, dir);
|
||||
});
|
||||
});
|
||||
|
||||
// Drag and drop
|
||||
extraPhotoGallery.querySelectorAll(".admin-photo-card").forEach(card => {
|
||||
card.addEventListener("dragstart", handleDragStart);
|
||||
card.addEventListener("dragover", handleDragOver);
|
||||
card.addEventListener("dragenter", handleDragEnter);
|
||||
card.addEventListener("dragleave", handleDragLeave);
|
||||
card.addEventListener("drop", handleDrop);
|
||||
card.addEventListener("dragend", handleDragEnd);
|
||||
});
|
||||
}
|
||||
|
||||
let draggedPhotoIdx = null;
|
||||
|
||||
function handleDragStart(e) {
|
||||
draggedPhotoIdx = +this.dataset.photoIdx;
|
||||
e.dataTransfer.effectAllowed = "move";
|
||||
e.dataTransfer.setData("text/plain", this.dataset.photoId);
|
||||
this.style.opacity = "0.4";
|
||||
}
|
||||
|
||||
function handleDragOver(e) {
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = "move";
|
||||
}
|
||||
|
||||
function handleDragEnter(e) {
|
||||
e.preventDefault();
|
||||
if (+this.dataset.photoIdx !== draggedPhotoIdx) {
|
||||
this.classList.add("admin-photo-card-drag-over");
|
||||
}
|
||||
}
|
||||
|
||||
function handleDragLeave() {
|
||||
this.classList.remove("admin-photo-card-drag-over");
|
||||
}
|
||||
|
||||
function handleDrop(e) {
|
||||
e.preventDefault();
|
||||
this.classList.remove("admin-photo-card-drag-over");
|
||||
const targetIdx = +this.dataset.photoIdx;
|
||||
if (draggedPhotoIdx !== null && draggedPhotoIdx !== targetIdx) {
|
||||
const dir = targetIdx > draggedPhotoIdx ? 1 : -1;
|
||||
reorderPhoto(draggedPhotoIdx, dir, targetIdx);
|
||||
}
|
||||
}
|
||||
|
||||
function handleDragEnd() {
|
||||
this.style.opacity = "1";
|
||||
draggedPhotoIdx = null;
|
||||
extraPhotoGallery?.querySelectorAll(".admin-photo-card").forEach(c => c.classList.remove("admin-photo-card-drag-over"));
|
||||
}
|
||||
|
||||
async function reorderPhoto(fromIdx, dir, targetIdx) {
|
||||
const photos = state.vehiclePhotos;
|
||||
if (photos.length < 2) return;
|
||||
|
||||
let toIdx;
|
||||
if (targetIdx !== undefined) {
|
||||
toIdx = targetIdx;
|
||||
} else {
|
||||
toIdx = fromIdx + dir;
|
||||
if (toIdx < 0 || toIdx >= photos.length) return;
|
||||
}
|
||||
|
||||
// Swap in local array
|
||||
[photos[fromIdx], photos[toIdx]] = [photos[toIdx], photos[fromIdx]];
|
||||
|
||||
// Build order payload
|
||||
const orderPayload = photos.map((p, i) => ({ id: p.id, order: i }));
|
||||
|
||||
const vid = vehicleForm.vid?.value;
|
||||
if (vid) {
|
||||
try {
|
||||
await supabase.rpc("reorder_vehicle_photos", {
|
||||
p_vehicle_id: vid,
|
||||
p_photo_orders: orderPayload,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Reorder failed:", err);
|
||||
[photos[fromIdx], photos[toIdx]] = [photos[fromIdx], photos[toIdx]];
|
||||
return;
|
||||
}
|
||||
}
|
||||
renderExtraPhotoGallery();
|
||||
}
|
||||
|
||||
async function deleteVehiclePhoto(photoId) {
|
||||
@@ -496,6 +568,16 @@ async function deleteVehiclePhoto(photoId) {
|
||||
const { error } = await supabase.from("vehicle_photos").delete().eq("id", photoId);
|
||||
if (error) throw error;
|
||||
state.vehiclePhotos = state.vehiclePhotos.filter(p => p.id !== photoId);
|
||||
|
||||
// If deleted was primary, promote next photo
|
||||
if (ph.is_primary && state.vehiclePhotos.length) {
|
||||
const newPrimary = state.vehiclePhotos[0];
|
||||
const vid = vehicleForm.vid?.value;
|
||||
if (vid) {
|
||||
await supabase.rpc("set_primary_vehicle_photo", { p_vehicle_id: vid, p_photo_id: newPrimary.id });
|
||||
vehicleForm.photo_url.value = newPrimary.photo_url;
|
||||
}
|
||||
}
|
||||
renderExtraPhotoGallery();
|
||||
} catch (err) {
|
||||
console.error("Failed to delete photo:", err);
|
||||
@@ -506,25 +588,28 @@ async function setPrimaryPhoto(photoId) {
|
||||
const vid = vehicleForm.vid?.value;
|
||||
if (!vid) return;
|
||||
try {
|
||||
const ph = state.vehiclePhotos.find(p => p.id === photoId);
|
||||
await supabase.rpc("set_primary_vehicle_photo", { p_vehicle_id: vid, p_photo_id: photoId });
|
||||
vehicleForm.photo_url.value = ph?.photo_url || "";
|
||||
await loadVehiclePhotos(vid);
|
||||
} catch (err) {
|
||||
console.error("Failed to set primary photo:", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Extra photos upload
|
||||
extraPhotoInput?.addEventListener("change", async () => {
|
||||
const files = extraPhotoInput.files;
|
||||
// Unified photo upload handler
|
||||
photoInput.addEventListener("change", async () => {
|
||||
const files = photoInput.files;
|
||||
if (!files.length) return;
|
||||
const vid = vehicleForm.vid?.value;
|
||||
if (!vid) {
|
||||
formFeedback.className = "form-feedback error";
|
||||
formFeedback.textContent = "Bitte zuerst Fahrzeug speichern, dann Fotos hinzufügen.";
|
||||
formFeedback.textContent = "Bitte zuerst das Fahrzeug speichern, dann Fotos hinzufügen.";
|
||||
return;
|
||||
}
|
||||
formFeedback.className = "form-feedback";
|
||||
formFeedback.textContent = "Uploading photos...";
|
||||
formFeedback.textContent = `Uploading ${files.length} photo(s)...`;
|
||||
let uploaded = 0;
|
||||
for (const file of files) {
|
||||
try {
|
||||
const ext = (file.name.split(".").pop() || "jpg").toLowerCase();
|
||||
@@ -534,23 +619,49 @@ extraPhotoInput?.addEventListener("change", async () => {
|
||||
.upload(path, file, { contentType: file.type, upsert: true });
|
||||
if (upErr) throw upErr;
|
||||
const { data: pub } = supabase.storage.from("vehicle-photos").getPublicUrl(path);
|
||||
const isFirst = state.vehiclePhotos.length === 0;
|
||||
const maxOrder = state.vehiclePhotos.reduce((m, p) => Math.max(m, p.display_order), -1);
|
||||
await supabase.from("vehicle_photos").insert({
|
||||
vehicle_id: vid,
|
||||
photo_url: pub.publicUrl,
|
||||
photo_path: path,
|
||||
display_order: maxOrder + 1,
|
||||
is_primary: state.vehiclePhotos.length === 0,
|
||||
is_primary: isFirst,
|
||||
});
|
||||
if (isFirst) {
|
||||
vehicleForm.photo_url.value = pub.publicUrl;
|
||||
}
|
||||
uploaded++;
|
||||
} catch (err) {
|
||||
console.error("Upload failed:", err);
|
||||
}
|
||||
}
|
||||
await loadVehiclePhotos(vid);
|
||||
formFeedback.textContent = `${files.length} Foto(s) hochgeladen.`;
|
||||
extraPhotoInput.value = "";
|
||||
formFeedback.textContent = `${uploaded} Foto(s) hochgeladen.`;
|
||||
photoInput.value = "";
|
||||
});
|
||||
|
||||
// Drag-and-drop on upload zone
|
||||
if (photoUploadZone) {
|
||||
photoUploadZone.addEventListener("dragover", e => {
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = "copy";
|
||||
photoUploadZone.classList.add("drag-active");
|
||||
});
|
||||
photoUploadZone.addEventListener("dragleave", () => {
|
||||
photoUploadZone.classList.remove("drag-active");
|
||||
});
|
||||
photoUploadZone.addEventListener("drop", e => {
|
||||
e.preventDefault();
|
||||
photoUploadZone.classList.remove("drag-active");
|
||||
const files = e.dataTransfer.files;
|
||||
if (files.length) {
|
||||
photoInput.files = files;
|
||||
photoInput.dispatchEvent(new Event("change"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// LEADS
|
||||
// =========================================================================
|
||||
|
||||
@@ -1135,6 +1135,172 @@ table.admin-table td:last-child { white-space: nowrap; }
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
/* ---- Unified Photo Upload Zone ---- */
|
||||
.admin-photo-upload-zone {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
border: 2px dashed var(--line);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s ease, background 0.2s ease;
|
||||
background: var(--bg-elev);
|
||||
margin-bottom: 0.5rem;
|
||||
position: relative;
|
||||
}
|
||||
.admin-photo-upload-zone:hover {
|
||||
border-color: var(--accent-strong);
|
||||
}
|
||||
.admin-photo-upload-zone.drag-active {
|
||||
border-color: var(--accent-strong);
|
||||
background: rgba(245, 158, 11, 0.08);
|
||||
}
|
||||
.admin-photo-upload-zone input[type="file"] {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.admin-photo-upload-content {
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
.admin-photo-upload-icon {
|
||||
font-size: 2rem;
|
||||
display: block;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
/* ---- Photo Gallery ---- */
|
||||
.admin-photo-gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 0.8rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.admin-photo-card {
|
||||
position: relative;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
aspect-ratio: 16/10;
|
||||
background: #1a1a1a;
|
||||
border: 2px solid transparent;
|
||||
transition: border-color 0.2s ease, transform 0.2s ease, opacity 0.2s ease;
|
||||
cursor: grab;
|
||||
}
|
||||
.admin-photo-card:hover {
|
||||
border-color: var(--accent-strong);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
.admin-photo-card:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
.admin-photo-card-drag-over {
|
||||
border-color: #f59e0b !important;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
.admin-photo-card img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
}
|
||||
.admin-photo-card-arrows {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 6px;
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
z-index: 2;
|
||||
}
|
||||
.admin-photo-arrow {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
.admin-photo-arrow:hover {
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
.admin-photo-card-actions {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
z-index: 2;
|
||||
}
|
||||
.admin-photo-set-primary {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
background: rgba(245, 158, 11, 0.85);
|
||||
color: #000;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
.admin-photo-set-primary:hover {
|
||||
background: #f59e0b;
|
||||
}
|
||||
.admin-photo-delete {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
background: rgba(239, 68, 68, 0.85);
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
.admin-photo-delete:hover {
|
||||
background: #ef4444;
|
||||
}
|
||||
.admin-photo-badge {
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
left: 6px;
|
||||
background: #22c55e;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
padding: 2px 8px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.05em;
|
||||
z-index: 2;
|
||||
}
|
||||
.admin-photo-drag-handle {
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
right: 6px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
font-size: 1.1rem;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ---------------- Forms / Toggle Switch ---------------- */
|
||||
.toggle-switch {
|
||||
position: relative;
|
||||
|
||||
Reference in New Issue
Block a user