feat: Latest production version with interior scene and glass

Includes room interior with floor, walls, glass you can see through,
and all uncommitted production changes that were running live.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ubuntu
2026-03-01 14:50:31 +00:00
parent 748a5814e7
commit 3d788740cb
110 changed files with 162553 additions and 13070 deletions

16
bron/App.js Normal file
View File

@@ -0,0 +1,16 @@
import { BrowserRouter as Router, Route, Routes, Link } from "react-router-dom";
import Endpoint from "./components/endpoint";
import RequestConfirmation from "./pages/RequestConfirmation";
import BubblesManager from "./pages/BubblesManager";
export default function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Endpoint />} />
<Route path="/request-confirmation" element={<RequestConfirmation />} />
<Route path="/manage-bubble" element={<BubblesManager />} />
</Routes>
</Router>
);
}

16
bron/Appp.js Normal file
View File

@@ -0,0 +1,16 @@
import { BrowserRouter as Router, Route, Routes, Link } from "react-router-dom";
import Endpoint from "./components/endpoint";
import RequestConfirmation from "./pages/RequestConfirmation";
import BubblesManager from "./pages/BubblesManager";
export default function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Endpoint />} />
<Route path="/request-confirmation" element={<RequestConfirmation />} />
<Route path="/manage-bubble" element={<BubblesManager />} />
</Routes>
</Router>
);
}

161
bron/BubblesManager.js Normal file
View File

@@ -0,0 +1,161 @@
// src/BubblesManager.js
import React, { useEffect, useState } from "react";
import axios from "axios";
const BubblesManager = () => {
const [bubbles, setBubbles] = useState([]);
const [bubbleName, setBubbleName] = useState("");
const [bubbleText, setBubbleText] = useState("");
const [isEditing, setIsEditing] = useState(false);
const [currentBubbleIndex, setCurrentBubbleIndex] = useState(null);
useEffect(() => {
fetchBubbles();
}, []);
const fetchBubbles = async () => {
try {
const response = await axios.get(
"https://api.config-fencing.com/api/get-bubbles"
);
setBubbles(response.data.bubbles);
} catch (error) {
console.error("Error fetching bubbles:", error);
}
};
const addBubble = async () => {
if (bubbleName.trim() !== "" && bubbleText.trim() !== "") {
const response = await axios.post(
"https://api.config-fencing.com/api/create-bubble",
{
name: bubbleName,
text: bubbleText,
}
);
setBubbles([
...bubbles,
{ id: response.data.bubble.id, name: bubbleName, text: bubbleText },
]);
setBubbleName("");
setBubbleText("");
}
};
const editBubble = (index) => {
setBubbleName(bubbles[index].name);
setBubbleText(bubbles[index].text);
setIsEditing(true);
setCurrentBubbleIndex(index);
};
const updateBubble = async () => {
const response = await axios.post(
`https://api.config-fencing.com/api/update-bubble/${bubbles[currentBubbleIndex].id}`,
{
name: bubbleName,
text: bubbleText,
}
);
const updatedBubbles = bubbles.map((bubble, index) =>
index === currentBubbleIndex
? { id: bubble.id, name: bubbleName, text: bubbleText }
: bubble
);
setBubbles(updatedBubbles);
setBubbleName("");
setBubbleText("");
setIsEditing(false);
setCurrentBubbleIndex(null);
};
const removeBubble = (index) => {
const newBubbles = bubbles.filter((_, i) => i !== index);
setBubbles(newBubbles);
};
return (
<div className="container mx-auto p-6 max-w-md">
<h1 className="text-3xl font-bold mb-6 text-center">Bubble Manager</h1>
{/* <div className="mb-6">
<input
type="text"
value={bubbleName}
onChange={(e) => setBubbleName(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble name"
/>
<input
type="text"
value={bubbleText}
onChange={(e) => setBubbleText(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble text"
/>
{isEditing ? (
<button
onClick={updateBubble}
className="bg-yellow-500 text-white rounded p-2 w-full hover:bg-yellow-600"
>
Update Bubble
</button>
) : (
<button
onClick={addBubble}
className="bg-blue-500 text-white rounded p-2 w-full hover:bg-blue-600"
>
Add Bubble
</button>
)}
</div> */}
{isEditing && (
<div className="mb-6">
<input
type="text"
value={bubbleName}
onChange={(e) => setBubbleName(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble name"
/>
<input
type="text"
value={bubbleText}
onChange={(e) => setBubbleText(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble text"
/>
<button
onClick={updateBubble}
className="bg-yellow-500 text-white rounded p-2 w-full hover:bg-yellow-600"
>
Update Bubble
</button>
</div>
)}
<ul className="list-none p-0">
{bubbles.map((bubble, index) => (
<li
key={index}
className="flex justify-between items-center mb-2 bg-gray-100 p-2 rounded shadow"
>
<div className="flex-1">
<h2 className="font-bold">{bubble.name}</h2>
<p>{bubble.text}</p>
</div>
<div>
<button
onClick={() => editBubble(index)}
className="bg-yellow-500 text-white rounded p-1 mr-2 hover:bg-yellow-600"
>
Edit
</button>
</div>
</li>
))}
</ul>
</div>
);
};
export default BubblesManager;

161
bron/BubblesManagerr.js Normal file
View File

@@ -0,0 +1,161 @@
// src/BubblesManager.js
import React, { useEffect, useState } from "react";
import axios from "axios";
const BubblesManager = () => {
const [bubbles, setBubbles] = useState([]);
const [bubbleName, setBubbleName] = useState("");
const [bubbleText, setBubbleText] = useState("");
const [isEditing, setIsEditing] = useState(false);
const [currentBubbleIndex, setCurrentBubbleIndex] = useState(null);
useEffect(() => {
fetchBubbles();
}, []);
const fetchBubbles = async () => {
try {
const response = await axios.get(
"https://api.config-fencing.com/api/get-bubbles"
);
setBubbles(response.data.bubbles);
} catch (error) {
console.error("Error fetching bubbles:", error);
}
};
const addBubble = async () => {
if (bubbleName.trim() !== "" && bubbleText.trim() !== "") {
const response = await axios.post(
"https://api.config-fencing.com/api/create-bubble",
{
name: bubbleName,
text: bubbleText,
}
);
setBubbles([
...bubbles,
{ id: response.data.bubble.id, name: bubbleName, text: bubbleText },
]);
setBubbleName("");
setBubbleText("");
}
};
const editBubble = (index) => {
setBubbleName(bubbles[index].name);
setBubbleText(bubbles[index].text);
setIsEditing(true);
setCurrentBubbleIndex(index);
};
const updateBubble = async () => {
const response = await axios.post(
`https://api.config-fencing.com/api/update-bubble/${bubbles[currentBubbleIndex].id}`,
{
name: bubbleName,
text: bubbleText,
}
);
const updatedBubbles = bubbles.map((bubble, index) =>
index === currentBubbleIndex
? { id: bubble.id, name: bubbleName, text: bubbleText }
: bubble
);
setBubbles(updatedBubbles);
setBubbleName("");
setBubbleText("");
setIsEditing(false);
setCurrentBubbleIndex(null);
};
const removeBubble = (index) => {
const newBubbles = bubbles.filter((_, i) => i !== index);
setBubbles(newBubbles);
};
return (
<div className="container mx-auto p-6 max-w-md">
<h1 className="text-3xl font-bold mb-6 text-center">Bubble Manager</h1>
{/* <div className="mb-6">
<input
type="text"
value={bubbleName}
onChange={(e) => setBubbleName(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble name"
/>
<input
type="text"
value={bubbleText}
onChange={(e) => setBubbleText(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble text"
/>
{isEditing ? (
<button
onClick={updateBubble}
className="bg-yellow-500 text-white rounded p-2 w-full hover:bg-yellow-600"
>
Update Bubble
</button>
) : (
<button
onClick={addBubble}
className="bg-blue-500 text-white rounded p-2 w-full hover:bg-blue-600"
>
Add Bubble
</button>
)}
</div> */}
{isEditing && (
<div className="mb-6">
<input
type="text"
value={bubbleName}
onChange={(e) => setBubbleName(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble name"
/>
<input
type="text"
value={bubbleText}
onChange={(e) => setBubbleText(e.target.value)}
className="border rounded p-2 w-full mb-4 focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter bubble text"
/>
<button
onClick={updateBubble}
className="bg-yellow-500 text-white rounded p-2 w-full hover:bg-yellow-600"
>
Update Bubble
</button>
</div>
)}
<ul className="list-none p-0">
{bubbles.map((bubble, index) => (
<li
key={index}
className="flex justify-between items-center mb-2 bg-gray-100 p-2 rounded shadow"
>
<div className="flex-1">
<h2 className="font-bold">{bubble.name}</h2>
<p>{bubble.text}</p>
</div>
<div>
<button
onClick={() => editBubble(index)}
className="bg-yellow-500 text-white rounded p-1 mr-2 hover:bg-yellow-600"
>
Edit
</button>
</div>
</li>
))}
</ul>
</div>
);
};
export default BubblesManager;

84
bron/ColorSelector.js Normal file
View File

@@ -0,0 +1,84 @@
import { IoMdClose } from "react-icons/io";
import { useEffect, useState } from "react";
import { useContext } from "react";
import { RiSearchLine } from "react-icons/ri";
import rals from "./logic/data/colors.json";
import { MyContext } from "./logic/data/contextapi";
export default function ColorSelector() {
const { colorPickerOpened, setColorPickerOpened, setFrameType, setCustomFrameType } = useContext(MyContext);
const iconSize = "16px";
const [value, setValue] = useState("");
const handleChange = (event) => setValue(event.target.value);
const colors = rals;
let resColors = [];
for (const [key, value] of Object.entries(colors)) {
resColors.push(value);
}
if (value) {
resColors = resColors.filter((x) =>
x.code.startsWith(value.toLowerCase().trim())
);
}
return (
<div
className={
"absolute bg-neutral-200 bottom-0 left-[108px] flex flex-col " +
(!colorPickerOpened ? "hidden" : "")
}
style={{ width: "180px" }}
>
<div className="bg-gray-200 p-2 text-xs flex flex-row items-center">
<div>Color selector</div>
<div className="ml-auto">
<IoMdClose
className="cursor-pointer"
onClick={() => setColorPickerOpened(false)}
size={iconSize}
/>
</div>
</div>
<div className="p-1 flex flex-col gap-2">
<div className="relative">
<span className="absolute inset-y-0 left-0 flex items-center pl-2">
<RiSearchLine className="text-gray-300" />
</span>
<input
value={value}
onChange={handleChange}
type="text"
placeholder="RAL code"
className="pl-8 pr-2 py-1 border border-gray-300 rounded bg-white text-xs w-full"
/>
</div>
<div className="" style={{ overflowY: "scroll", maxHeight: "350px" }}>
<div className="flex flex-row flex-wrap gap-1">
{resColors.map((c) => {
return (
<div
onClick={() => {
setFrameType(`./images/custom_colors/${c.img}`);
setCustomFrameType({name: c.names.en, color: c.color.hex})
setColorPickerOpened(false);
}}
key={c.code}
className="flex h-5 w-9 text-xs items-center justify-center text-white cursor-pointer"
style={{ background: c.color.hex }}
>
{c.code}
</div>
);
})}
</div>
</div>
</div>
</div>
);
}

1210
bron/DoorHole.js Normal file

File diff suppressed because it is too large Load Diff

BIN
bron/Handle%203.glb Normal file

Binary file not shown.

BIN
bron/Handle%204.glb Normal file

Binary file not shown.

51
bron/InfoIcon.js Normal file
View File

@@ -0,0 +1,51 @@
import React, { useContext, useEffect } from "react";
import { MyContext } from "../data/contextapi";
import Tooltip from "../../Tooltip";
const InfoIcon = ({ title, containerStyles }) => {
const { bubbles } = useContext(MyContext);
const bubbleText = bubbles?.find(({ name }) => name === title)
? bubbles.find(({ name }) => name === title).text
: "";
return (
<span
style={{
display: "flex",
alignItems: "center",
gap: "10px",
...containerStyles,
}}
>
{title}
<Tooltip message={bubbleText}>
<span
style={{
borderRadius: "100%",
backgroundColor: "#bdc79d",
display: "flex",
justifyContent: "center",
alignItems: "center",
color: "white",
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
fill="currentColor"
className="bi bi-info"
viewBox="0 0 16 16"
>
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0" />
</svg>
</span>
</Tooltip>
</span>
);
};
export default InfoIcon;

145
bron/RequestConfirmation.js Normal file
View File

@@ -0,0 +1,145 @@
import React, { useEffect } from "react";
export default function RequestConfirmation() {
useEffect(() => {
// Function to retrieve the GA Client ID
const getGAClientId = () => {
const trackers = window.ga?.getAll?.();
if (trackers && trackers.length) {
return trackers[0].get('clientId');
}
return null;
};
const timer = setTimeout(() => {
const vid = window?.gaGlobal?.vid;
console.log("gaClientId", vid)
// If GA Client ID is found, append it to the URL
const redirectUrl = vid
? `https://cloozdoors.nl?gaClientId=${vid}`
: "https://cloozdoors.nl"; // fallback if GA Client ID is not found
window.location.href = redirectUrl;
}, 20000);
return () => clearTimeout(timer);
}, []);
return (
<div className="min-h-screen bg-white">
<div className="w-full h-20 bg-[#bdc79d]"></div>
<div className="mt-10 p-8">
<div className="max-w-5xl mx-auto bg-[#ececec] shadow-lg">
<div className="p-6 pt-0 rounded-t-lg text-center">
<div className="w-1/6">
<img src="/images/Logo_CLOOZ.jpg" className="w-full" />
</div>
</div>
<div className="p-6 text-left px-[15%]">
<h2 className="text-4xl font-bold mb-0">
BEDANKT VOOR UW AANVRAAG!
</h2>
<p className="text-gray-700 mb-8">
Binnen 48 uur neemt onze verkoop binnendienst contact met u op om
deze online aanvraag volledig te optimaliseren en u van de juiste
offerte te voorzien.
</p>
</div>
</div>
<div className="max-w-5xl mx-auto mt-4 shadow-lg">
<div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Waarom kies
</h3>
<h3 className="font-semibold text-white text-xl">
Je Clooz doors
</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Why choose.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Eigen fabriek</li>
<li>Uniek eigen profiel</li>
<li>Snelste levering</li>
<li>Perfecte afwerking</li>
<li>Kindveilig product</li>
</ul>
</div>
</div>
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Waarom het
</h3>
<h3 className="font-semibold text-white text-xl">
Clooz doors profiel?
</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Why it.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Tweezijdig hetzelfde aanzicht</li>
<li>Elke design mogelijk</li>
<li>Ongedeelde glasplaat</li>
<li>Rankste profiel</li>
</ul>
</div>
</div>
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Bezoek onze
</h3>
<h3 className="font-semibold text-white text-xl">SHOWROOM</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Visit our.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Met persoonlijk advies</li>
<li>Alle deuren</li>
<li>Ontwerp samen</li>
<li>Ook op zaterdag</li>
<li>Centraal in NL</li>
</ul>
</div>
</div>
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Gebruik onze
</h3>
<h3 className="font-semibold text-white text-xl">
inmeetservice
</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Use our.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Door heel NL</li>
<li>Voorkom fouten</li>
<li>Voorkom kosten</li>
<li>Met het beste advies</li>
<li>Voor het gemak</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,145 @@
import React, { useEffect } from "react";
export default function RequestConfirmation() {
useEffect(() => {
// Function to retrieve the GA Client ID
const getGAClientId = () => {
const trackers = window.ga?.getAll?.();
if (trackers && trackers.length) {
return trackers[0].get('clientId');
}
return null;
};
const timer = setTimeout(() => {
const vid = window?.gaGlobal?.vid;
console.log("gaClientId", vid)
// If GA Client ID is found, append it to the URL
const redirectUrl = vid
? `https://cloozdoors.nl?gaClientId=${vid}`
: "https://cloozdoors.nl"; // fallback if GA Client ID is not found
window.location.href = redirectUrl;
}, 20000);
return () => clearTimeout(timer);
}, []);
return (
<div className="min-h-screen bg-white">
<div className="w-full h-20 bg-[#bdc79d]"></div>
<div className="mt-10 p-8">
<div className="max-w-5xl mx-auto bg-[#ececec] shadow-lg">
<div className="p-6 pt-0 rounded-t-lg text-center">
<div className="w-1/6">
<img src="/images/Logo_CLOOZ.jpg" className="w-full" />
</div>
</div>
<div className="p-6 text-left px-[15%]">
<h2 className="text-4xl font-bold mb-0">
BEDANKT VOOR UW AANVRAAG!
</h2>
<p className="text-gray-700 mb-8">
Binnen 48 uur neemt onze verkoop binnendienst contact met u op om
deze online aanvraag volledig te optimaliseren en u van de juiste
offerte te voorzien.
</p>
</div>
</div>
<div className="max-w-5xl mx-auto mt-4 shadow-lg">
<div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Waarom kies
</h3>
<h3 className="font-semibold text-white text-xl">
Je Clooz doors
</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Why choose.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Eigen fabriek</li>
<li>Uniek eigen profiel</li>
<li>Snelste levering</li>
<li>Perfecte afwerking</li>
<li>Kindveilig product</li>
</ul>
</div>
</div>
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Waarom het
</h3>
<h3 className="font-semibold text-white text-xl">
Clooz doors profiel?
</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Why it.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Tweezijdig hetzelfde aanzicht</li>
<li>Elke design mogelijk</li>
<li>Ongedeelde glasplaat</li>
<li>Rankste profiel</li>
</ul>
</div>
</div>
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Bezoek onze
</h3>
<h3 className="font-semibold text-white text-xl">SHOWROOM</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Visit our.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Met persoonlijk advies</li>
<li>Alle deuren</li>
<li>Ontwerp samen</li>
<li>Ook op zaterdag</li>
<li>Centraal in NL</li>
</ul>
</div>
</div>
<div className="bg-[#bdc79d] border">
<div className="px-4 pt-6 pb-4">
<h3 className="font-semibold text-white text-xl">
Gebruik onze
</h3>
<h3 className="font-semibold text-white text-xl">
inmeetservice
</h3>
</div>
<div className="p-2 bg-[#000]">
<img src="/images/request confirm/Use our.jpg" />
</div>
<div className="px-4 pt-3 pb-4">
<ul className="text-left text-white text-base list-disc list-inside">
<li>Door heel NL</li>
<li>Voorkom fouten</li>
<li>Voorkom kosten</li>
<li>Met het beste advies</li>
<li>Voor het gemak</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

416
bron/RequestForm.js Normal file
View File

@@ -0,0 +1,416 @@
import React, { useEffect, useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import TechInformation from "./TechInformation";
const RequestForm = ({ techInformation, attachDesign, glContext, sceneContext, cameraContext }) => {
const navigate = useNavigate();
const [formData, setFormData] = useState({
aanhef: "Dhr",
voornaam: "",
tussenvoegsel: "",
achternaam: "",
straatnaam: "",
huisnummer: "",
postcode: "",
woonplaats: "",
land: "Nederland",
emailadres: "",
telefoonnummer: "",
comment: "",
file: null,
});
useEffect(() => {
setFormData({...formData, file: attachDesign});
}, [attachDesign])
const [isSubmitting, setIsSubmitting] = useState(false);
const [isClearSubmitting, setIsClearSubmitting] = useState(false);
const [formErrors, setFormErrors] = useState({});
const handleChange = (e) => {
const { name, value, files } = e.target;
if (name === "file") {
setFormData({
...formData,
[name]: files[0],
});
} else {
setFormData({
...formData,
[name]: value,
});
}
};
const validate = () => {
const errors = {};
Object.keys(formData).forEach((key) => {
if (["comment", "tussenvoegsel", "file"].includes(key)) return;
if (!formData[key]) {
errors[key] = "Dit veld is verplicht";
}
});
return errors;
};
const dataURLToBlob = (dataURL) => {
const byteString = atob(dataURL.split(',')[1]);
const mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0];
const arrayBuffer = new ArrayBuffer(byteString.length);
const uint8Array = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i++) {
uint8Array[i] = byteString.charCodeAt(i);
}
return new Blob([arrayBuffer], { type: mimeString });
};
const handleSubmit = async (isReset = false) => {
const errors = validate();
if (Object.keys(errors).length === 0) {
setIsSubmitting(true);
setIsClearSubmitting(isReset);
try {
glContext.render(sceneContext, cameraContext);
const image = glContext.domElement.toDataURL('image/png');
const imageBlob = dataURLToBlob(image);
const formDataToSubmit = new FormData();
Object.keys(formData).forEach((key) => {
formDataToSubmit.append(key, formData[key]);
});
formDataToSubmit.append('constructImage', imageBlob, 'constructImage.png');
formDataToSubmit.append(
"techInformation",
JSON.stringify(techInformation)
);
formDataToSubmit.append(
"platform", "clooz"
);
const response = await axios.post(
"https://api-lumbronch.agreatidea.studio/api/request-a-quote",
formDataToSubmit,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
navigate("/request-confirmation");
if (isReset) {
setFormData({
aanhef: "Dhr",
voornaam: "",
tussenvoegsel: "",
achternaam: "",
straatnaam: "",
huisnummer: "",
postcode: "",
woonplaats: "",
land: "Nederland",
emailadres: "",
telefoonnummer: "",
comment: "",
file: null,
});
}
// Handle successful form submission
} catch (error) {
console.error(error);
// Handle error in form submission
} finally {
setIsSubmitting(false);
}
} else {
setFormErrors(errors);
}
};
const formStyle = {
maxWidth: "400px",
margin: "0 auto",
backgroundColor: "#2D3748",
padding: "20px",
borderRadius: "8px",
};
const inputStyle = {
width: "100%",
padding: "10px",
marginBottom: "10px",
borderRadius: "4px",
backgroundColor: "#fff",
color: "#333",
border: "none",
boxSizing: "border-box",
};
const fileInputStyle = {
display: "none",
};
const labelStyle = {
color: "#fff",
fontSize: "14px",
fontWeight: "bold",
display: "block",
};
const errorStyle = {
color: "red",
fontSize: "12px",
margin: 0,
};
const buttonStyle = {
backgroundColor: "#48BB78",
color: "#FFF",
fontSize: "16px",
padding: "10px 20px",
borderRadius: "100px",
border: "none",
cursor: "pointer",
};
const linkButtonStyle = {
fontSize: "14px",
color: "#FFF",
cursor: "pointer",
display: "block",
};
const fileUploadLabelStyle = {
display: "flex",
alignItems: "center",
gap: "10px",
cursor: "pointer",
backgroundColor: "#48BB78",
padding: "8px 15px",
borderRadius: "50px",
color: "#FFF",
fontSize: "14px",
textAlign: "center",
};
return (
<form onSubmit={handleSubmit}>
<TechInformation techInformation={techInformation} />
<div style={formStyle}>
<h2 style={{ color: "#FFF", marginBottom: "20px", fontSize: "16px" }}>
Vul uw gegevens in
</h2>
<div style={{ marginBottom: "10px" }}>
<select
name="aanhef"
value={formData.aanhef}
onChange={handleChange}
style={{
...inputStyle,
border: formErrors.aanhef ? "1px solid red" : "none",
}}
required
>
<option value="Dhr">Dhr.</option>
<option value="Mevr">Mevr.</option>
</select>
{formErrors.aanhef && <p style={errorStyle}>{formErrors.aanhef}</p>}
</div>
{[
"voornaam",
"tussenvoegsel",
"achternaam",
"straatnaam",
"huisnummer",
"postcode",
"woonplaats",
"emailadres",
"telefoonnummer",
].map((field) => (
<div
key={field}
style={{
marginBottom: "10px",
display: "flex",
flexDirection: "column",
}}
>
<input
type="text"
name={field}
value={formData[field]}
onChange={handleChange}
placeholder={field.charAt(0).toUpperCase() + field.slice(1)}
style={{
...inputStyle,
border: formErrors[field] ? "1px solid red" : "none",
}}
required
/>
{formErrors[field] && <p style={errorStyle}>{formErrors[field]}</p>}
</div>
))}
<div style={{ marginBottom: "10px" }}>
<select
name="land"
value={formData.land}
onChange={handleChange}
style={{
...inputStyle,
border: formErrors.land ? "1px solid red" : "none",
}}
required
>
<option value="Nederland">Nederland</option>
<option value="Spanje">Spanje</option>
<option value="Duitsland">Duitsland</option>
<option value="België">België</option>
{/* Add more options as needed */}
</select>
{formErrors.land && <p style={errorStyle}>{formErrors.land}</p>}
</div>
<div key="comment" style={{ marginBottom: "10px", display: "flex" }}>
<textarea
rows={3}
name="comment"
value={formData.comment}
onChange={handleChange}
placeholder="Opmerkingen"
style={{
...inputStyle,
border: formErrors.comment ? "1px solid red" : "none",
}}
/>
{formErrors.comment && <p style={errorStyle}>{formErrors.comment}</p>}
</div>
<div style={{ color: "red", marginBottom: "20px" }}>
* Vul alle velden correct in.
</div>
<div
style={{
marginBottom: "10px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<label htmlFor="file" style={labelStyle}>
Afbeelding bijvoegen:
</label>
<label
htmlFor="file"
style={{
...fileUploadLabelStyle,
backgroundColor: formData.file ? "#48BB78" : "red",
}}
>
<img src="/images/upload.png" width={20} />
Kies bestand
</label>
<input
type="file"
name="file"
id="file"
onChange={handleChange}
style={{
...fileInputStyle,
border: formErrors.file ? "1px solid red" : "none",
}}
/>
{formErrors.file && <p style={errorStyle}>{formErrors.file}</p>}
</div>
<div
style={{
display: "flex",
justifyContent: "end",
alignItems: "center",
}}
>
<button
type="button"
onClick={() => handleSubmit(false)}
style={{ ...buttonStyle, marginTop: "10px", minHeight: "44px", minWidth: "187px" }}
disabled={isSubmitting}
className={`relative ${
isSubmitting ? "opacity-50 cursor-not-allowed" : ""
}`}
>
{isSubmitting && !isClearSubmitting ? (
<div className="absolute inset-0 flex justify-center items-center">
<svg
className="animate-spin h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
></path>
</svg>
</div>
) : (
"Offerte aanvragen"
)}
</button>
</div>
<button
type="button"
onClick={() => handleSubmit(true)}
style={{ ...buttonStyle, marginTop: "20px", width: "100%", minHeight: "44px" }}
disabled={isSubmitting}
className={`relative ${
isSubmitting ? "opacity-50 cursor-not-allowed" : ""
}`}
>
{isSubmitting && isClearSubmitting ? (
<div className="absolute inset-0 flex justify-center items-center">
<svg
className="animate-spin h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
></path>
</svg>
</div>
) : (
"Versturen en nog een offerte aanvragen"
)}
</button>
</div>
</form>
);
};
export default RequestForm;

146
bron/Stalen.js Normal file
View File

@@ -0,0 +1,146 @@
import { MyContext } from './data/contextapi';
import { useContext } from 'react';
import Structure from './Structure';
export default function Stalen() {
const { width, height, stalenPart, stalenType, frameSize } = useContext(MyContext);
const doorWidth = (0.06 * width) / stalenPart;
const doorHeightn = 0.053 * height;
return (
<>
{stalenType == 'tussen' ? (
<>
{stalenPart >= 1 && (
<group
position={[
(0.06 * width + 4 * frameSize + (stalenPart - 1) * 3.5 * frameSize) / 2 - (doorWidth + (4 * frameSize + (stalenPart - 1) * 4 * frameSize) / stalenPart) / 2 - 3 * frameSize/2,
(-12 + doorHeightn) * 0.5,
-13.5,
]}
>
<group position={[0, 0, 0]}>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
{stalenPart >= 2 && (
<group
position={[
(0.06 * width + 4 * frameSize + (stalenPart - 1) * 3.5 * frameSize) / 2 - 3 * (doorWidth + (4 * frameSize + (stalenPart - 1) * 4 * frameSize) / stalenPart) / 2 - frameSize,
(-12 + doorHeightn) * 0.5,
-13.5,
]}
rotation={[0, Math.PI, 0]}
>
<group
position={[0, 0, 0]}
rotation={[0, Math.PI, 0]}
>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
{stalenPart >= 3 && (
<group
position={[
(0.06 * width + 4 * frameSize + (stalenPart - 1) * 3.5 * frameSize) / 2 - 5 * (doorWidth + (4 * frameSize + (stalenPart - 1) * 4 * frameSize) / stalenPart) / 2,
(-12 + doorHeightn) * 0.5,
-13.5,
]}
>
<group position={[0, 0, 0]}>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
{stalenPart >= 4 && (
<group
position={[
(0.06 * width + 4 * frameSize + (stalenPart - 1) * 3.5 * frameSize) / 2 - 7 * (doorWidth + (4 * frameSize + (stalenPart - 1) * 4 * frameSize) / stalenPart) / 2 + frameSize / 2,
(-12 + doorHeightn) * 0.5,
-13.5,
]}
>
<group position={[0, 0, 0]}>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
</>
) : (
<>
{stalenPart >= 1 && (
<group
position={[
2 * (0.06 * width + 4 * frameSize) - (doorWidth + 4 * frameSize),
(-12 + doorHeightn) * 0.5,
-13.5,
]}
rotation={[0, Math.PI, 0]}
>
<group
position={[-doorWidth / 2, 0, 0]}
rotation={[0, Math.PI, 0]}
>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
{stalenPart >= 2 && (
<group
position={[
2 * (0.06 * width + 4 * frameSize) - 2 * (doorWidth + 4 * frameSize) + frameSize / 2,
(-12 + doorHeightn) * 0.5,
-13.5,
]}
rotation={[0, Math.PI, 0]}
>
<group
position={[-doorWidth / 2, 0, 0]}
rotation={[0, Math.PI, 0]}
>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
{stalenPart >= 3 && (
<group
position={[
2 * (0.06 * width + 4 * frameSize) - 3 * (doorWidth + 4 * frameSize) + frameSize,
(-12 + doorHeightn) * 0.5,
-13.5,
]}
rotation={[0, Math.PI, 0]}
>
<group
position={[-doorWidth / 2, 0, 0]}
rotation={[0, Math.PI, 0]}
>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
{stalenPart >= 4 && (
<group
position={[
2 * (0.06 * width + 4 * frameSize) - 4 * (doorWidth + 4 * frameSize) + 3 * frameSize/2,
(-12 + doorHeightn) * 0.5,
-13.5,
]}
rotation={[0, Math.PI, 0]}
>
<group
position={[-doorWidth / 2, 0, 0]}
rotation={[0, Math.PI, 0]}
>
<Structure sizePannel={0} stalenWidth={doorWidth} />
</group>
</group>
)}
</>
)}
</>
);
}

2742
bron/Structure.js Normal file

File diff suppressed because it is too large Load Diff

477
bron/TechInformation.js Normal file
View File

@@ -0,0 +1,477 @@
import React from "react";
export default function TechInformation({techInformation}) {
return (
<>
<div style={{ width: "100%" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<span>Technische informatie</span>
</div>
</div>
<div style={{ width: "100%" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Type deur
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Deur type
</span>
</div>
<span>{techInformation.type}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Aantal deuren in offerte
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Samenstelling deur
</span>
<span>{techInformation.doorConfig}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Aantal en plaats zijpanelen
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Samenstelling zijpaneel
</span>
<span>{techInformation.sidePannel}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Verdeling elementen
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Paneel verdeling
</span>
<span>{techInformation.sidePannelConfig}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
{techInformation.sidePannelConfig === "eigen maat" && (
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Breedte deur
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Breedte deur
</span>
<span>{techInformation.sidePannelSize}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
)}
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Breedte deur
</span>
<span>
{techInformation.width}
</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Hoogte sparing
</span>
<span>{techInformation.height}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Breedte sparing
</span>
<span>
{techInformation.holeWidth}
</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Vlakverdeling
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Design
</span>
<span>{techInformation.door}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Handgreep
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Handgreep
</span>
<span>{techInformation.handle}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Kleur glas
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Glas soort
</span>
<span>{techInformation.colorGlass}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
RAL Kleur
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Kleur
</span>
<span>{techInformation.steelColor}</span>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
<div style={{ width: "100%", marginTop: "15px" }}>
<div
style={{
margin: "2% 5% 2% 5%",
paddingTop: "0.5rem",
fontWeight: "bolder",
fontSize: "normal",
borderBottom: "1px solid GrayText",
}}
>
{/* <div>
<span
style={{
fontSize: "small",
color: "GrayText",
fontWeight: "normal",
}}
>
Verzending en montage
</span>
</div> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span
style={{
fontSize: "14px",
color: "GrayText",
fontWeight: "bold",
}}
>
Extra opties
</span>
<div
style={{ display: "flex", flexDirection: "column", width: "80%" }}
>
{techInformation.extraOptions.map((extraOption, index) => {
return (
<span style={{ fontSize: "14px" }} key={`extra-${index}`}>
- {extraOption}
</span>
);
})}
</div>
{/* <span>&euro; 0,00</span> */}
</div>
</div>
</div>
</>
);
}

19
bron/Tooltip.js Normal file
View File

@@ -0,0 +1,19 @@
import React from "react";
const Tooltip = ({ message, children }) => {
return (
<div className="relative group">
{children}
{message !== "" && (
<div className="absolute top-[30px] left-1/2 w-[140px] transform -translate-x-1/2 mb-2 hidden group-hover:block z-10">
<div className="relative bg-gray-800 text-white text-xs rounded py-1 px-4">
{message}
<div className="absolute top-[-5px] left-1/2 transform -translate-x-1/2 w-3 h-3 bg-gray-800 rotate-45"></div>
</div>
</div>
)}
</div>
);
};
export default Tooltip;

27
bron/bootstrap Normal file
View File

@@ -0,0 +1,27 @@
// The module cache
var __webpack_module_cache__ = {};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
var cachedModule = __webpack_module_cache__[moduleId];
if (cachedModule !== undefined) {
return cachedModule.exports;
}
// Create a new module (and put it into the cache)
var module = __webpack_module_cache__[moduleId] = {
id: moduleId,
loaded: false,
exports: {}
};
// Execute the module function
__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// Flag the module as loaded
module.loaded = true;
// Return the exports of the module
return module.exports;
}

View File

@@ -0,0 +1,8 @@
// getDefaultExport function for compatibility with non-harmony modules
__webpack_require__.n = (module) => {
var getter = module && module.__esModule ?
() => (module['default']) :
() => (module);
__webpack_require__.d(getter, { a: getter });
return getter;
};

View File

@@ -0,0 +1,601 @@
DoorHole.js:345 THREE.Material: 'castShadow' is not a property of THREE.MeshStandardMaterial.
setValues @ three.module.js:9206
Ip @ three.module.js:40946
(anonymous) @ DoorHole.js:345
useMemo @ react-reconciler.production.min.js:93
t.useMemo @ react.production.min.js:26
zR @ DoorHole.js:344
kr @ react-reconciler.production.min.js:78
ca @ react-reconciler.production.min.js:196
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
DoorHole.js:359 THREE.Material: 'castShadow' is not a property of THREE.MeshStandardMaterial.
setValues @ three.module.js:9206
Ip @ three.module.js:40946
(anonymous) @ DoorHole.js:359
useMemo @ react-reconciler.production.min.js:93
t.useMemo @ react.production.min.js:26
zR @ DoorHole.js:358
kr @ react-reconciler.production.min.js:78
ca @ react-reconciler.production.min.js:196
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
DoorHole.js:372 THREE.Material: 'castShadow' is not a property of THREE.MeshStandardMaterial.
setValues @ three.module.js:9206
Ip @ three.module.js:40946
(anonymous) @ DoorHole.js:372
useMemo @ react-reconciler.production.min.js:93
t.useMemo @ react.production.min.js:26
zR @ DoorHole.js:371
kr @ react-reconciler.production.min.js:78
ca @ react-reconciler.production.min.js:196
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
DoorHole.js:345 THREE.Material: 'castShadow' is not a property of THREE.MeshStandardMaterial.
setValues @ three.module.js:9206
Ip @ three.module.js:40946
(anonymous) @ DoorHole.js:345
useMemo @ react-reconciler.production.min.js:93
t.useMemo @ react.production.min.js:26
zR @ DoorHole.js:344
kr @ react-reconciler.production.min.js:78
ca @ react-reconciler.production.min.js:196
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
DoorHole.js:359 THREE.Material: 'castShadow' is not a property of THREE.MeshStandardMaterial.
setValues @ three.module.js:9206
Ip @ three.module.js:40946
(anonymous) @ DoorHole.js:359
useMemo @ react-reconciler.production.min.js:93
t.useMemo @ react.production.min.js:26
zR @ DoorHole.js:358
kr @ react-reconciler.production.min.js:78
ca @ react-reconciler.production.min.js:196
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
DoorHole.js:372 THREE.Material: 'castShadow' is not a property of THREE.MeshStandardMaterial.
setValues @ three.module.js:9206
Ip @ three.module.js:40946
(anonymous) @ DoorHole.js:372
useMemo @ react-reconciler.production.min.js:93
t.useMemo @ react.production.min.js:26
zR @ DoorHole.js:371
kr @ react-reconciler.production.min.js:78
ca @ react-reconciler.production.min.js:196
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
n @ index-99983b2d.esm.js:64
Ii @ react-reconciler.production.min.js:109
Ua @ react-reconciler.production.min.js:187
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
n @ index-99983b2d.esm.js:64
Ii @ react-reconciler.production.min.js:109
Ua @ react-reconciler.production.min.js:187
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
n @ index-99983b2d.esm.js:64
Ii @ react-reconciler.production.min.js:109
Ua @ react-reconciler.production.min.js:187
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
n @ index-99983b2d.esm.js:64
Ii @ react-reconciler.production.min.js:109
Ua @ react-reconciler.production.min.js:187
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29710
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
n @ index-99983b2d.esm.js:64
Ii @ react-reconciler.production.min.js:109
Ua @ react-reconciler.production.min.js:187
Oa @ react-reconciler.production.min.js:186
Fa @ react-reconciler.production.min.js:186
Ma @ react-reconciler.production.min.js:175
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
commitUpdate @ index-99983b2d.esm.js:303
Ms @ react-reconciler.production.min.js:155
(anonymous) @ react-reconciler.production.min.js:161
(anonymous) @ react-reconciler.production.min.js:189
za @ react-reconciler.production.min.js:187
Ma @ react-reconciler.production.min.js:177
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
commitUpdate @ index-99983b2d.esm.js:303
Ms @ react-reconciler.production.min.js:155
(anonymous) @ react-reconciler.production.min.js:161
(anonymous) @ react-reconciler.production.min.js:189
za @ react-reconciler.production.min.js:187
Ma @ react-reconciler.production.min.js:177
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
commitUpdate @ index-99983b2d.esm.js:303
Ms @ react-reconciler.production.min.js:155
(anonymous) @ react-reconciler.production.min.js:161
(anonymous) @ react-reconciler.production.min.js:189
za @ react-reconciler.production.min.js:187
Ma @ react-reconciler.production.min.js:177
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29710
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
commitUpdate @ index-99983b2d.esm.js:303
Ms @ react-reconciler.production.min.js:155
(anonymous) @ react-reconciler.production.min.js:161
(anonymous) @ react-reconciler.production.min.js:189
za @ react-reconciler.production.min.js:187
Ma @ react-reconciler.production.min.js:177
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
endpoint.js:133 Error fetching bubbles: Zy {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
console.error @ index.tsx:86
Qe @ endpoint.js:133
await in Qe
(anonymous) @ endpoint.js:116
rl @ react-dom.production.min.js:243
wc @ react-dom.production.min.js:285
(anonymous) @ react-dom.production.min.js:281
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
endpoint.js:128 GET https://api.config-fencing.com/api/get-bubbles net::ERR_CONNECTION_TIMED_OUT
(anonymous) @ xhr.js:188
xhr @ xhr.js:15
hb @ dispatchRequest.js:51
_request @ Axios.js:173
request @ Axios.js:40
Qy.forEach.yb.<computed> @ Axios.js:199
(anonymous) @ bind.js:5
Qe @ endpoint.js:128
(anonymous) @ endpoint.js:116
rl @ react-dom.production.min.js:243
wc @ react-dom.production.min.js:285
(anonymous) @ react-dom.production.min.js:281
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
invalidate @ index-99983b2d.esm.js:1300
lv @ index-99983b2d.esm.js:779
ov @ index-99983b2d.esm.js:758
n @ index-99983b2d.esm.js:64
Ii @ react-reconciler.production.min.js:109
Ua @ react-reconciler.production.min.js:187
Oa @ react-reconciler.production.min.js:186
ja @ react-reconciler.production.min.js:186
Da @ react-reconciler.production.min.js:186
Ra @ react-reconciler.production.min.js:179
Yt @ react-reconciler.production.min.js:39
w @ scheduler.production.min.js:13
B @ scheduler.production.min.js:14
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29708
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
(anonymous) @ index-99983b2d.esm.js:1590
t @ index-99983b2d.esm.js:1590
sE @ gsap-core.js:990
n.render @ gsap-core.js:3464
n.render @ gsap-core.js:2257
pC @ gsap-core.js:192
t.updateRoot @ gsap-core.js:2695
n @ gsap-core.js:1316
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
three.module.js:19367 THREE.WebGLProgram: Unsupported toneMapping: srgb
Bc @ three.module.js:19367
Gc @ three.module.js:20038
acquireProgram @ three.module.js:21011
Fe @ three.module.js:29960
(anonymous) @ three.module.js:30223
renderBufferDirect @ three.module.js:29037
je @ three.module.js:29896
De @ three.module.js:29865
Pe @ three.module.js:29710
render @ three.module.js:29526
Mv @ index-99983b2d.esm.js:1544
a @ index-99983b2d.esm.js:1570
requestAnimationFrame
t @ index-99983b2d.esm.js:1609
(anonymous) @ index-99983b2d.esm.js:1590
t @ index-99983b2d.esm.js:1590
sE @ gsap-core.js:990
n.render @ gsap-core.js:3464
n.render @ gsap-core.js:2257
pC @ gsap-core.js:192
t.updateRoot @ gsap-core.js:2695
n @ gsap-core.js:1316
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
requestAnimationFrame
n @ gsap-core.js:1311
Warning: Dont paste code into the DevTools Console that you dont understand or havent reviewed yourself. This could allow attackers to steal your identity or take control of your computer. Please type allow pasting below and press Enter to allow pasting.
allow pasting
[...performance.getEntriesByType('resource')]
.map(e => decodeURIComponent(e.name))
.filter(u => u.endsWith('.glb'));
['https://config.cloozdoors.nl/models/Handle 1.glb']0: "https://config.cloozdoors.nl/models/Handle 1.glb"length: 1[[Prototype]]: Array(0)
(async () => {
// 1) Probeer de basis-map te vinden uit eerdere .glb-requests
const entries = performance.getEntriesByType('resource')
.map(e => e.name)
.filter(u => /\.glb(\?|#|$)/i.test(u));
let base = '';
if (entries.length) {
const u = new URL(entries[0]);
u.pathname = u.pathname.replace(/[^/]+$/, ''); // strip bestandsnaam
base = u.href;
} else {
// fallback (meest waarschijnlijke pad bij deze site)
base = `${location.origin}/static/js/components/logic/models/`;
}
console.log('GLB base:', base);
// 2) Probe range en log welke bestaan
const found = [];
const tryFetch = async (url) => {
try {
// HEAD wordt soms geblokkeerd; daarom GET met no-store
const r = await fetch(url, { cache: 'no-store' });
return r.ok && /model\/gltf-binary|octet-stream/i.test(r.headers.get('content-type') || '');
} catch (e) { return false; }
};
for (let i = 1; i <= 200; i++) {
const url = `${base}Handle%20${i}.glb`;
// %20 i.p.v. spatie zo worden ze ook aangevraagd
if (await tryFetch(url)) {
found.push({ i, url: decodeURIComponent(url) });
console.log('GLB gevonden:', decodeURIComponent(url));
}
}
if (!found.length) {
console.warn('Geen Handle {n}.glb gevonden in', base);
} else {
console.log('Totaal gevonden:', found.length, found.map(f => `Handle ${f.i}.glb`));
}
})();
VM925:17 GLB base: https://config.cloozdoors.nl/models/
Promise {<pending>}
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 1.glb
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 2.glb
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 3.glb
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 4.glb
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 5.glb
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 6.glb
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 7.glb
VM925:34 GLB gevonden: https://config.cloozdoors.nl/models/Handle 8.glb
VM925:41 Totaal gevonden: 8 (8) ['Handle 1.glb', 'Handle 2.glb', 'Handle 3.glb', 'Handle 4.glb', 'Handle 5.glb', 'Handle 6.glb', 'Handle 7.glb', 'Handle 8.glb']

3
bron/contextapi.js Normal file
View File

@@ -0,0 +1,3 @@
import { createContext } from 'react';
export const MyContext = createContext("");

View File

@@ -0,0 +1,26 @@
var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
var leafPrototypes;
// create a fake namespace object
// mode & 1: value is a module id, require it
// mode & 2: merge all properties of value into the ns
// mode & 4: return value when already ns object
// mode & 16: return value when it's Promise-like
// mode & 8|1: behave like require
__webpack_require__.t = function(value, mode) {
if(mode & 1) value = this(value);
if(mode & 8) return value;
if(typeof value === 'object' && value) {
if((mode & 4) && value.__esModule) return value;
if((mode & 16) && typeof value.then === 'function') return value;
}
var ns = Object.create(null);
__webpack_require__.r(ns);
var def = {};
leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {
Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
}
def['default'] = () => (value);
__webpack_require__.d(ns, def);
return ns;
};

View File

@@ -0,0 +1,8 @@
// define getter functions for harmony exports
__webpack_require__.d = (exports, definition) => {
for(var key in definition) {
if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
}
}
};

4831
bron/design.js Normal file

File diff suppressed because it is too large Load Diff

735
bron/door.js Normal file
View File

@@ -0,0 +1,735 @@
import { useContext, useState, useEffect } from "react";
import { MyContext } from "../data/contextapi";
import InfoIcon from "./InfoIcon";
export default function Door() {
const {
type,
settype,
setStep,
width,
setWidth,
doorConfig,
setDoorConfig,
sidePannel,
setSidePannel,
sidePannelConfig,
setSidePannelConfig,
sidePannelSize,
setSidePannelSize,
stalenPart,
setStalenPart,
stalenType,
setStalenType,
open,
inprogress,
setInprogress,
height,
setHeight,
holeWidth,
setHoleWidth,
} = useContext(MyContext);
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
// Function to check the window width
const checkScreenWidth = () => {
setIsMobile(window.innerWidth <= 800);
};
// Initial check
checkScreenWidth();
// Add event listener to check screen width on resize
window.addEventListener("resize", checkScreenWidth);
// Clean up event listener on component unmount
return () => {
window.removeEventListener("resize", checkScreenWidth);
};
}, []);
useEffect(() => {
if (
(doorConfig == "dubbele" && sidePannel === "beide") ||
sidePannel === "beide"
) {
setSidePannelSize(width);
} else {
setSidePannelSize(width);
}
setWidth(90);
setSidePannelSize(90);
setHoleWidth(calculateHoleWidth());
}, [doorConfig, sidePannelConfig, sidePannel]);
const handleHeightChange = (e) => {
if (e.target.value > 285) {
return
}
const value = e.target.value;
if (!isNaN(value)) {
setHeight(value);
}
};
const calculateHoleMinWidth = () => {
if (
(doorConfig != "dubbele" &&
(sidePannel === "links" || sidePannel === "rechts")) ||
(doorConfig == "dubbele" && sidePannel == "geen")
) {
return 120;
}
if (doorConfig != "dubbele" && sidePannel === "beide") {
return 180;
}
if (
doorConfig == "dubbele" &&
(sidePannel == "links" || sidePannel == "rechts")
) {
return 180;
}
if (doorConfig == "dubbele" && sidePannel == "beide") {
return 240;
}
return 60;
};
const calculateHoleMaxWidth = () => {
if (
(doorConfig != "dubbele" &&
(sidePannel === "links" || sidePannel === "rechts")) ||
(doorConfig == "dubbele" && sidePannel == "geen")
) {
return 240;
}
if (doorConfig != "dubbele" && sidePannel === "beide") {
return 360;
}
if (
doorConfig == "dubbele" &&
(sidePannel == "links" || sidePannel == "rechts")
) {
return 360;
}
if (doorConfig == "dubbele" && sidePannel == "beide") {
return 400;
}
return 120;
};
const calculateHoleWidth = () => {
if (
(doorConfig != "dubbele" &&
(sidePannel === "links" || sidePannel === "rechts")) ||
(doorConfig == "dubbele" && sidePannel == "geen")
) {
return 180;
}
if (doorConfig != "dubbele" && sidePannel === "beide") {
return 270;
}
if (
doorConfig == "dubbele" &&
(sidePannel == "links" || sidePannel == "rechts")
) {
return 270;
}
if (doorConfig == "dubbele" && sidePannel == "beide") {
return 360;
}
return 90;
};
const handleHoleWidth = (e) => {
if (e.target.value > calculateHoleMaxWidth()) {
return
}
setHoleWidth(e.target.value);
setSidePannelSize(calculateSidePanelWidth(e.target.value, width));
if (sidePannel == "geen") {
setWidth(doorConfig === "dubbele" ? e.target.value / 2 : e.target.value);
}
};
const calculateSidePanelWidth = (totalWidth, doorWidth) => {
if (
doorConfig != "dubbele" &&
(sidePannel === "links" || sidePannel === "rechts")
) {
return totalWidth - Number(doorWidth);
}
if (doorConfig == "dubbele" && sidePannel == "geen") {
return 0;
}
if (doorConfig != "dubbele" && sidePannel === "beide") {
return (totalWidth - Number(doorWidth)) / 2;
}
if (
doorConfig == "dubbele" &&
(sidePannel == "links" || sidePannel == "rechts")
) {
return totalWidth - Number(doorWidth) * 2;
}
if (doorConfig == "dubbele" && sidePannel == "beide") {
return (totalWidth - Number(doorWidth) * 2) / 2;
}
return 0;
};
return (
<>
{/* <div style={{ width: '100%' }}>
<div style={{ margin: '5%', paddingTop: '0.5rem', display: 'flex', justifyContent: 'space-between', fontWeight: 'bolder', fontSize: 'normal' }}>
<span>Type Deur</span>
<div style={{ backgroundColor: 'white', borderRadius: '20px', width: 'auto', padding: '10px', margin: '0 0 0 10px' }}>
<span className="body-txt" style={{}} onClick={() => { setStep('door') }}>&euro; 0,00</span>
</div>
</div>
</div> */}
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<span>Afmeting</span>
</div>
<div className="slider-container" style={{ margin: "5%" }}>
<div className="">
<p style={{ marginBottom: "-5px" }}>Hoogte</p>
</div>
<div
className="slider-container"
style={{ display: "flex", alignItems: "center" }}
>
<div style={{ flex: 1 }}>
<input
type="range"
min="180"
max="285"
value={height}
onChange={handleHeightChange}
className="slider"
id="range1"
style={{
width: "100%",
height: "8px",
borderRadius: "5px",
appearance: "none",
background: "#F2F2F3", // Grey line
outline: "none", // Remove default outline
marginTop: "10px", // Adjust margin to separate from the text above
}}
/>
</div>
<div
style={{
marginLeft: "10px",
paddingLeft: "10px",
paddingRight: "10px",
paddingTop: "5px",
paddingBottom: "5px",
backgroundColor: "#F2F2F3",
position: "relative",
width: "5rem",
fontSize: "small",
border: "1px solid",
borderRadius: "4px",
}}
>
<input
type="text"
style={{
width: "100%",
border: "none",
outline: "none",
background: "transparent",
}}
value={height}
onChange={handleHeightChange}
onInput={(e) => e.target.value = e.target.value.replace(/[^0-9]/g, '')}
/>
<span
style={{
position: "absolute",
right: "10px",
top: "50%",
transform: "translateY(-50%)",
}}
>
cm
</span>
</div>
</div>
</div>
<div
className="slider-container"
style={{
margin: "5%",
borderBottom: "1px solid #d1d1d1",
paddingBottom: "15px",
}}
>
<div className="">
<p style={{ marginBottom: "-5px" }}>Breedte</p>
</div>
<div
className="slider-container"
style={{ display: "flex", alignItems: "center" }}
>
<div style={{ flex: 1 }}>
<input
type="range"
min={calculateHoleMinWidth()}
max={calculateHoleMaxWidth()}
value={holeWidth}
onChange={handleHoleWidth}
style={{
width: "100%",
height: "8px",
borderRadius: "5px",
appearance: "none",
background: "#F2F2F3", // Grey line
outline: "none", // Remove default outline
marginTop: "10px", // Adjust margin to separate from the text above
}}
/>
</div>
<div
style={{
marginLeft: "10px",
paddingLeft: "10px",
paddingRight: "10px",
paddingTop: "5px",
paddingBottom: "5px",
backgroundColor: "#F2F2F3",
position: "relative",
width: "5rem",
fontSize: "small",
border: "1px solid",
borderRadius: "4px",
}}
>
<input
type="text"
style={{
width: "100%",
border: "none",
outline: "none",
background: "transparent",
}}
value={holeWidth}
onChange={handleHoleWidth}
onInput={(e) => e.target.value = e.target.value.replace(/[^0-9]/g, '')}
/>
<span
style={{
position: "absolute",
right: "10px",
top: "50%",
transform: "translateY(-50%)",
}}
>
cm
</span>
</div>
</div>
</div>
<div style={{ width: "100%" }}>
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<InfoIcon title={"Deur type"} />
</div>
</div>
<div
className="door-content-2"
style={{
display: "flex",
justifyContent: "center",
}}
>
<div
className="door-content-2-1 door-content-custom-1"
style={{
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
gridColumnGap: "10px",
fontSize: "11px",
margin: "0 5%",
width: "100%",
}}
>
<div
className="custom-card-1"
style={{
position: "relative",
margin: "5px",
borderRadius: "5px",
}}
onClick={() => {
if (!inprogress) settype("Taatsdeur");
}}
>
<div
className="main-img-div"
style={{
border: type === "Taatsdeur" ? "2px solid black" : "none",
borderRadius: "10px",
boxShadow: "-5px -2px 10px -2px rgba(0,0,0,0.6)",
padding: "10px",
backgroundColor: "white",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div style={{ position: "absolute", top: "5px", right: "5px" }}>
<input
type="radio"
className="sm"
checked={type === "Taatsdeur"}
readOnly
onChange={() => {
if (!inprogress) settype("Taatsdeur");
}}
/>
</div>
<center>
<img
src="./images/doortypes/door_type_1_staging.jpg"
style={{
maxWidth: "80%",
maxHeight: "100%",
width: "80%",
borderRadius: "10px",
overflow: "hidden",
}}
/>
</center>
</div>
<div
style={{
margin: "10px 0 0 0",
backgroundColor: type === "Taatsdeur" ? "black" : "#bdc79d",
color: "white",
position: "relative",
paddingTop: "5px",
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
Taatsdeur
</span>
</div>
<div></div>
</div>
<div
className="custom-card-1"
style={{ position: "relative", margin: "5px", borderRadius: "5px" }}
onClick={() => {
if (!inprogress) settype("Schuifdeur");
}}
>
<div
className="main-img-div"
style={{
border: type === "Schuifdeur" ? "2px solid black" : "none",
borderRadius: "10px",
boxShadow: "-5px -2px 10px -2px rgba(0,0,0,0.6)",
padding: "10px",
backgroundColor: "white",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div style={{ position: "absolute", top: "5px", right: "5px" }}>
<input
type="radio"
className="sm"
checked={type === "Schuifdeur"}
readOnly
onChange={() => {
if (!inprogress) settype("Schuifdeur");
}}
/>
</div>
<center>
<img
src="./images/doortypes/door_type_2_staging.jpg"
style={{
maxWidth: "80%",
maxHeight: "100%",
width: "80%",
borderRadius: "10px",
overflow: "hidden",
}}
/>
</center>
</div>
<div
style={{
margin: "10px 0 0 0",
backgroundColor: type === "Schuifdeur" ? "black" : "#bdc79d",
color: "white",
position: "relative",
paddingTop: "5px",
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
SCHUIFDEUR
</span>
</div>
<div></div>
</div>
<div
className="custom-card-1"
style={{ position: "relative", margin: "5px", borderRadius: "5px" }}
onClick={() => {
if (!inprogress) settype("Scharnier");
}}
>
<div
className="main-img-div"
style={{
border: type === "Scharnier" ? "2px solid black" : "none",
borderRadius: "10px",
boxShadow: "-5px -2px 10px -2px rgba(0,0,0,0.6)",
padding: "10px",
backgroundColor: "white",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div style={{ position: "absolute", top: "5px", right: "5px" }}>
<input
type="radio"
className="sm"
checked={type === "Scharnier"}
readOnly
onChange={() => {
if (!inprogress) settype("Scharnier");
}}
/>
</div>
<center>
<img
src="./images/doortypes/door_type_3_staging.jpg"
style={{
maxWidth: "80%",
maxHeight: "100%",
width: "80%",
borderRadius: "10px",
overflow: "hidden",
}}
/>
</center>
</div>
<div
style={{
margin: "10px 0 0 0",
backgroundColor: type === "Scharnier" ? "black" : "#bdc79d",
color: "white",
position: "relative",
paddingTop: "5px",
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
KOZIJN DEUR
</span>
</div>
<div></div>
</div>
<div
className="custom-card-1"
style={{ position: "relative", margin: "5px", borderRadius: "5px" }}
onClick={() => {
settype("vast-stalen");
setDoorConfig("enkele");
setSidePannel("geen");
setInprogress(false);
}}
>
<div
className="main-img-div"
style={{
border: type === "vast-stalen" ? "2px solid black" : "none",
borderRadius: "10px",
boxShadow: "-5px -2px 10px -2px rgba(0,0,0,0.6)",
padding: "10px",
backgroundColor: "white",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div style={{ position: "absolute", top: "5px", right: "5px" }}>
<input
type="radio"
className="sm"
checked={type === "vast-stalen"}
readOnly
onChange={() => {
settype("vast-stalen");
setDoorConfig("enkele");
setSidePannel("geen");
setInprogress(false);
}}
/>
</div>
<center>
<img
src="./images/doortypes/door_type_4.jpg"
style={{
maxWidth: "80%",
maxHeight: "100%",
width: "80%",
borderRadius: "10px",
overflow: "hidden",
}}
/>
</center>
</div>
<div
style={{
margin: "10px 0 0 0",
backgroundColor: type === "vast-stalen" ? "black" : "#bdc79d",
color: "white",
position: "relative",
paddingTop: "5px",
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
Vast stalen
</span>
</div>
<div></div>
</div>
</div>
</div>
<button
className="volgende btn"
onClick={() => {
setStep("samenstling");
}}
>
Volgende
</button>
</>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
bron/door_type_4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

BIN
bron/draco_decoder.wasm Normal file

Binary file not shown.

47
bron/draco_decover.js.rtf Normal file

File diff suppressed because one or more lines are too long

653
bron/endpoint.js Normal file
View File

@@ -0,0 +1,653 @@
import { Canvas, useThree } from "@react-three/fiber";
import axios from "axios";
// import { EffectComposer } from "@react-three/postprocessing";
import DoorHole from "./logic/DoorHole";
import { Suspense, useState, useEffect } from "react";
import Preloader from "./logic/preloader";
import Door from "./logic/UI/door";
import Design from "./logic/UI/design";
import Information from "./logic/UI/information";
import * as THREE from "three";
import { MyContext } from "./logic/data/contextapi";
import Extra from "./logic/UI/extra";
import Samenstling from "./logic/UI/samenstling";
import Arrow from "./logic/UI/arrow";
import { DirectionalLightHelper, CameraHelper } from "three";
import React, { useRef } from "react";
export default function Endpoint() {
const [json, setJson] = useState({ Data: [] });
const [step, setStep] = useState("door");
const [type, settype] = useState("Taatsdeur");
const [door, setdoor] = useState("3panel");
const [frameSize, setFrameSize] = useState(0.125);
const [glassType, setGlassType] = useState(0x111111);
const [frameType, setFrameType] = useState(
"./images/doortypes/RAL 9005 fijn structuur.png"
);
const [width, setWidth] = useState(90); // State for width
const [height, setHeight] = useState(250); // State for height
const [holeWidth, setHoleWidth] = useState(90);
const [doorConfig, setDoorConfig] = useState("enkele");
const [sidePannel, setSidePannel] = useState("geen");
const [sidePannelConfig, setSidePannelConfig] = useState("eigen maat");
const [sidePannelSize, setSidePannelSize] = useState(width);
const [stalenType, setStalenType] = useState("tussen");
const [stalenPart, setStalenPart] = useState(1);
const [handle, setHandle] = useState(1);
const [maxWidth, setMaxWidth] = useState(105);
const [prwType, setPrwType] = useState("Enkele");
const [prwImage, setPrwImage] = useState(
"./images/doortypes/enkele deur.png"
);
const [extraOptions, setExtraOptions] = useState([
"Meetservice",
"Montage service",
]);
const [count, setCount] = useState(1);
const [coverSheetSteel, setCoverSheetSteel] = useState(false);
const [coverLearn, setCoverLearn] = useState(false);
const [coverWoodliness, setCoverWoodliness] = useState(false);
const [coverMirrors, setCoverMirrors] = useState(false);
const [coverCylinderLockKey, setCoverCylinderLockKey] = useState(false);
const [coverDontKnow, setCoverDontKnow] = useState(false);
const [handleSheetSteel, setHandleSheetSteel] = useState(false);
const [handleLearn, setHandleLearn] = useState(false);
const [handleWoodliness, setHandleWoodliness] = useState(false);
const [handleMirrors, setHandleMirrors] = useState(false);
const [handleCylinderLockKey, setHandleCylinderLockKey] = useState(false);
const [standardBlack, setStandardBlack] = useState(false);
const [alternativeRALColour, setAlternativeRALColour] = useState(false);
const [metallicCoating, setMetallicCoating] = useState(false);
const [bright, setBright] = useState(false);
const [canaleOrCrepi, setCanaleOrCrepi] = useState(false);
const [fireResistant, setFireResistant] = useState(false);
const [outdoorPlacement, setOutdoorPlacement] = useState(false);
const [maxHeight, setMaxHeight] = useState(0);
const [contentHeight, setContentHeight] = useState("calc(100vh - 320px)");
const [open, setOpen] = useState(false);
const [inprogress, setInprogress] = useState(false);
const [bubbles, setBubbles] = useState();
const [attachDesign, setAttachDesign] = useState(null);
const [colorPickerOpened, setColorPickerOpened] = useState(false);
const [customFrameType, setCustomFrameType] = useState({name: "", color: ""});
const [compositionImage, setCompositionImage] = useState("https://config.livingsteel.nl/images/doortypes/3%20panel.png");
const [glContext, setGlContext] = useState(null);
const [sceneContext, setSceneContext] = useState(null); // Store the Scene context
const [cameraContext, setCameraContext] = useState(null); // Store the Camera context
// Calculate the maximum height based on the available screen height
useEffect(() => {
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
const isAndroid = /android/i.test(userAgent);
const isIOS = /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream;
const calculateMaxHeight = () => {
let availableHeight;
if (window.innerWidth > 800) {
const screenHeight = window.innerHeight;
// Adjust maxHeight to leave space for other elements like headers or footers
availableHeight = screenHeight - 100; // Adjust this value as needed
} else {
setContentHeight(
`calc(100vh - 25vh - ${isAndroid ? "270px" : "310px"})`
);
const screenHeight = window.innerHeight * 0.65;
// Adjust maxHeight to leave space for other elements like headers or footers 30
availableHeight = screenHeight + 210; // Adjust this value as needed
}
setMaxHeight(availableHeight);
};
fetchBubbles();
calculateMaxHeight(); // Call once initially
window.addEventListener("resize", calculateMaxHeight); // Recalculate on window resize
return () => {
window.removeEventListener("resize", calculateMaxHeight); // Cleanup
};
}, []);
const fetchBubbles = async () => {
try {
const response = await axios.get(
"https://api.config-fencing.com/api/get-bubbles"
);
setBubbles(response.data.bubbles);
} catch (error) {
console.error("Error fetching bubbles:", error);
}
};
// Create a ref for the SpotLight
const spotLightRef = useRef();
return (
<>
<MyContext.Provider
value={{
json,
setJson,
setStep,
sidePannel,
setSidePannel,
type,
settype,
door,
setdoor,
width,
setWidth,
height,
setHeight,
holeWidth,
setHoleWidth,
doorConfig,
setDoorConfig,
prwType,
setPrwType,
prwImage,
setPrwImage,
count,
setCount,
frameSize,
setFrameSize,
glassType,
setGlassType,
frameType,
setFrameType,
sidePannelConfig,
setSidePannelConfig,
sidePannelSize,
setSidePannelSize,
stalenType,
setStalenType,
stalenPart,
setStalenPart,
handle,
setHandle,
maxWidth,
setMaxWidth,
coverSheetSteel,
setCoverSheetSteel,
coverLearn,
setCoverLearn,
coverWoodliness,
setCoverWoodliness,
coverMirrors,
setCoverMirrors,
coverCylinderLockKey,
setCoverCylinderLockKey,
coverDontKnow,
setCoverDontKnow,
handleSheetSteel,
setHandleSheetSteel,
handleLearn,
setHandleLearn,
handleWoodliness,
setHandleWoodliness,
handleMirrors,
setHandleMirrors,
handleCylinderLockKey,
setHandleCylinderLockKey,
standardBlack,
setStandardBlack,
alternativeRALColour,
setAlternativeRALColour,
metallicCoating,
setMetallicCoating,
bright,
setBright,
canaleOrCrepi,
setCanaleOrCrepi,
fireResistant,
setFireResistant,
outdoorPlacement,
setOutdoorPlacement,
setExtraOptions,
extraOptions,
open,
setOpen,
inprogress,
setInprogress,
bubbles,
setBubbles,
attachDesign,
setAttachDesign,
colorPickerOpened,
setColorPickerOpened,
customFrameType,
setCustomFrameType,
compositionImage,
setCompositionImage,
glContext,
sceneContext,
cameraContext,
}}
>
<div style={{ width: "100vw", height: "100svh", overflow: "hidden" }}>
<div className="body-can-2" style={{}}>
<div className="body-can-2-1" style={{}}>
<div className="body-can-2-1-1" style={{}}>
<Suspense fallback={<Preloader />}>
<Canvas
frameloop="demand"
gl={{
antialias: true,
alpha: true,
toneMapping: THREE.SRGBColorSpace,
}}
camera={{ fov: 53 }}
onCreated={({ gl, scene, camera }) => {
setGlContext(gl);
setSceneContext(scene);
setCameraContext(camera);
}}
// shadows // Enable shadows
>
{/* Ambient light for basic illumination */}
<DoorHole />
</Canvas>
</Suspense>
</div>
<div className="body-can-2-1-2" style={{ overflowY: "hidden" }}>
<div
className="quot"
style={{
backgroundColor: "#bdc79d",
display: "flex",
alignItems: "center",
padding: "10px",
}}
>
{/* <span
style={{
color: "white",
fontWeight: "bold",
marginLeft: "30px",
}}
>
Prijs incl. BTW
</span> */}
{/* <div
style={{
backgroundColor: "white",
borderRadius: "20px",
width: "auto",
padding: "5px",
margin: "0 0 0 10px",
}}
>
<span
className="body-txt"
style={{}}
onClick={() => {
setStep("door");
}}
>
&euro; 2200,00
</span>
</div> */}
</div>
<div
className={`step-content ${
step === "door" ? "expand" : "collapsed"
}`}
style={{
maxHeight: `${maxHeight}px`,
}}
>
<div
style={{
position: "relative",
cursor: "pointer",
marginTop: "auto",
}}
onClick={() => {
setStep("door");
}}
>
<button
className={`body-btn ${
step === "door" ? "expand" : "collapsed"
}`}
style={{}}
>
1
</button>
<span
className={`body-txt ${
step === "door" ? "expand" : "collapsed"
}`}
style={{ opacity: step === "door" ? 1 : 0.4 }}
onClick={() => {
setStep("door");
}}
>
DEURMAAT & TYPE
</span>
<div
style={{
position: "absolute",
top: "5px",
right: "20px",
}}
>
<input
type="radio"
checked={step === "door"}
readOnly
onChange={() => setStep("door")}
className={`radio ${
step === "door" ? "expand" : "collapsed"
}`}
/>
{/* <Arrow direction={step === 'door' ? 'down' : 'up'} /> */}
</div>
</div>
<div
style={{
overflowY: "auto",
padding: step == "door" ? "10px" : 0,
height: step == "door" ? contentHeight : 0,
opacity: step == "door" ? 1 : 0,
transition:
"height 0.3s ease-in-out, opacity 0.5s ease-in-out",
}}
>
<Door />
</div>
</div>
<div
className={`step-content ${
step === "samenstling" ? "expand" : "collapsed"
}`}
style={{
maxHeight: `${maxHeight}px`,
}}
>
<div
style={{
position: "relative",
cursor: "pointer",
}}
onClick={() => {
setStep("samenstling");
}}
>
<button
className={`body-btn ${
step === "samenstling" ? "expand" : "collapsed"
}`}
>
2
</button>
<span
className={`body-txt ${
step === "samenstling" ? "expand" : "collapsed"
}`}
style={{ opacity: step === "samenstling" ? 1 : 0.4 }}
onClick={() => {
setStep("samenstling");
}}
>
Samenstelling
</span>
<div
style={{
position: "absolute",
top: "5px",
right: "20px",
}}
>
<input
type="radio"
checked={step === "samenstling"}
readOnly
onChange={() => setStep("samenstling")}
className={`radio ${
step === "samenstling" ? "expand" : "collapsed"
}`}
/>
</div>
</div>
<div
style={{
overflowY: "auto",
padding: step == "samenstling" ? "10px" : 0,
height: step == "samenstling" ? contentHeight : 0,
opacity: step == "samenstling" ? 1 : 0,
transition:
"height 0.3s ease-in-out, opacity 0.5s ease-in-out",
}}
>
<Samenstling />
</div>
</div>
<div
className={`step-content ${
step === "design" ? "expand" : "collapsed"
}`}
style={{
maxHeight: `${maxHeight}px`,
}}
>
<div
style={{
position: "relative",
cursor: "pointer",
}}
onClick={() => {
setStep("design");
}}
>
<button
className={`body-btn ${
step === "design" ? "expand" : "collapsed"
}`}
style={{}}
>
3
</button>
<span
className={`body-txt ${
step === "design" ? "expand" : "collapsed"
}`}
style={{ opacity: step === "design" ? 1 : 0.4 }}
onClick={() => {
setStep("design");
}}
>
Design, Kleur & GLAS
</span>
<div
style={{
position: "absolute",
top: "5px",
right: "20px",
}}
>
<input
type="radio"
checked={step === "design"}
readOnly
onChange={() => setStep("design")}
className={`radio ${
step === "design" ? "expand" : "collapsed"
}`}
/>
</div>
</div>
<div
style={{
backgroundColor: "#fff",
overflowY: "auto",
padding: step == "design" ? "10px" : 0,
height: step == "design" ? contentHeight : 0,
opacity: step == "design" ? 1 : 0,
transition:
"height 0.3s ease-in-out, opacity 0.5s ease-in-out",
}}
>
<Design />
</div>
</div>
<div
className={`step-content ${
step === "extra" ? "expand" : "collapsed"
}`}
style={{
maxHeight: `${maxHeight}px`,
}}
>
<div
style={{
position: "relative",
cursor: "pointer",
}}
onClick={() => {
setStep("extra");
}}
>
<button
className={`body-btn ${
step === "extra" ? "expand" : "collapsed"
}`}
>
4
</button>
<span
className={`body-txt ${
step === "extra" ? "expand" : "collapsed"
}`}
style={{ opacity: step === "extra" ? 1 : 0.4 }}
onClick={() => {
setStep("extra");
}}
>
Extra Opties
</span>
<div
style={{
position: "absolute",
top: "5px",
right: "20px",
}}
>
<input
type="radio"
checked={step === "extra"}
readOnly
onChange={() => setStep("extra")}
className={`radio ${
step === "extra" ? "expand" : "collapsed"
}`}
/>
{/* <Arrow direction={step === 'extra' ? 'down' : 'up'} /> */}
</div>
</div>
<div
style={{
overflowY: "auto",
padding: step == "extra" ? "10px" : 0,
height: step == "extra" ? contentHeight : 0,
opacity: step == "extra" ? 1 : 0,
transition:
"height 0.3s ease-in-out, opacity 0.5s ease-in-out",
}}
>
<Extra />
</div>
</div>
<div
className={`pd step-content ${
step === "information" ? "expand" : "collapsed"
}`}
style={{
maxHeight: `${maxHeight}px`,
}}
>
<div
style={{
position: "relative",
cursor: "pointer",
}}
onClick={() => {
setStep("information");
}}
>
<button
className={`body-btn ${
step === "information" ? "expand" : "collapsed"
}`}
style={{}}
>
5
</button>
<span
className={`body-txt ${
step === "information" ? "expand" : "collapsed"
}`}
style={{ opacity: step === "information" ? 1 : 0.4 }}
onClick={() => {
setStep("information");
}}
>
Order informatie
</span>
<div
style={{
position: "absolute",
top: "5px",
right: "20px",
}}
>
<input
type="radio"
checked={step === "information"}
readOnly
onChange={() => setStep("information")}
className={`radio ${
step === "information" ? "expand" : "collapsed"
}`}
/>
{/* <Arrow
direction={step === 'information' ? 'down' : 'up'}
/> */}
</div>
</div>
<div
style={{
backgroundColor: "#fff",
overflowY: "auto",
padding: step == "information" ? "10px" : 0,
height: step == "information" ? contentHeight : 0,
opacity: step == "information" ? 1 : 0,
transition:
"height 0.3s ease-in-out, opacity 0.5s ease-in-out",
}}
>
<Information />
</div>
</div>
</div>
</div>
</div>
</div>
</MyContext.Provider>
</>
);
}

10
bron/extends.js Normal file
View File

@@ -0,0 +1,10 @@
function _extends() {
return _extends = Object.assign ? Object.assign.bind() : function (n) {
for (var e = 1; e < arguments.length; e++) {
var t = arguments[e];
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
}
return n;
}, _extends.apply(null, arguments);
}
export { _extends as default };

148
bron/extra.js Normal file
View File

@@ -0,0 +1,148 @@
import { useContext, useState } from "react";
import { MyContext } from "../data/contextapi";
import InfoIcon from "./InfoIcon";
export default function Extra() {
const { settype, type, setStep, extraOptions, setExtraOptions } =
useContext(MyContext);
const [extras, setExtra] = useState([]);
const [montage, setMontage] = useState([]);
const handleExtra = (val) =>
setExtraOptions((prev) =>
prev.includes(val)
? [...prev.filter((itm) => itm != val)]
: [...prev, val]
);
return (
<>
<div style={{ backgroundColor: "#fff" }}>
<div style={{ width: "100%" }}>
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: "bolder",
fontSize: "normal",
paddingLeft: "10px",
}}
>
<InfoIcon title={"Kies hier wat van toepassing is"} />
{/* <div
style={{
backgroundColor: "white",
borderRadius: "20px",
width: "auto",
padding: "2px 10px",
margin: "0 0 0 10px",
}}
>
<span
className="body-txt"
style={{}}
onClick={() => {
setStep("door");
}}
>
&euro; 400,00
</span>
</div> */}
</div>
</div>
<div style={{ margin: "5%", fontSize: "small" }}>
{[
"Meetservice",
"Montage service",
"Taatsbeslag in kleur",
"Vloerverwarming montageset",
"Adviesgesprek",
].map((option, idx) => (
<div
key={`${option}_${idx}`}
style={{ display: "flex", cursor: "pointer" }}
>
<input
type="checkbox"
checked={extraOptions.includes(option)}
onChange={() => handleExtra(option)}
style={{ marginRight: "10px", width: "15px", height: "15px" }}
/>
<span onClick={() => handleExtra(option)}>{option}</span>
</div>
))}
</div>
<div style={{ width: "100%" }}>
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: "bolder",
fontSize: "normal",
paddingLeft: "5px",
}}
>
<InfoIcon title={"Afhalen of verzenden"} />
{/* <div
style={{
backgroundColor: "white",
borderRadius: "20px",
width: "auto",
padding: "2px 10px",
margin: "0 0 0 10px",
}}
>
<span
className="body-txt"
style={{}}
// onClick={() => {
// setStep('door');
// }}
>
&euro; 400,00
</span>
</div> */}
</div>
</div>
<div
style={{
margin: "5%",
fontSize: "small",
borderBottom: "1px solid #d1d1d1",
paddingBottom: "25px",
}}
>
{[
"Afleveren NL per koeriersdienst (excl. Waddeneilanden)",
"Afleveren buiten NL",
"Afhalen fabriek",
].map((option, idx) => (
<div key={`${option}_${idx}`} style={{ display: "flex" }}>
<input
type="checkbox"
checked={extraOptions.includes(option)}
onChange={() => handleExtra(option)}
style={{ marginRight: "10px", width: "15px", height: "15px" }}
/>
<span onClick={() => handleExtra(option)}>{option}</span>
</div>
))}
</div>
<button
className="volgende btn"
onClick={() => {
setStep("information");
}}
>
Volgende
</button>
</div>
</>
);
}

8
bron/global Normal file
View File

@@ -0,0 +1,8 @@
__webpack_require__.g = (function() {
if (typeof globalThis === 'object') return globalThis;
try {
return this || new Function('return this')();
} catch (e) {
if (typeof window === 'object') return window;
}
})();

50
bron/handle.js Normal file
View File

@@ -0,0 +1,50 @@
import { Clone, useGLTF, useTexture } from "@react-three/drei";
import { MyContext } from "./data/contextapi";
import { useContext } from "react";
import * as THREE from "three";
export default function Handle() {
const { width, height, handle, frameType } = useContext(MyContext);
const grip = useGLTF(`./models/Handle ${handle}.glb`);
const texture = useTexture(frameType);
grip.scene.traverse((child) => {
if (child.isMesh) {
child.material = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide,
});
}
});
return (
<>
<Clone
object={grip.scene}
position={[
0.03 * width + 0.1 - (handle === 5 || handle === 6 ? 0.6 : 0),
-(0.053 * height) / 10000,
0.045,
]}
scale={handle === 7 ? 4.88 : handle === 4 ? 6 : 5}
rotation={[0, -Math.PI / 2, 0]}
/>
<Clone
object={grip.scene}
position={[
0.03 * width + 0.1 - (handle === 5 || handle === 6 ? 0.6 : 0),
-(0.053 * height) / 10000,
-0.045,
]}
scale={handle === 7 ? 4.88 : handle === 4 ? 6 : 5}
rotation={[
0,
[5, 6, 7, 8].includes(handle) ? Math.PI / 2 : -Math.PI / 2,
[5, 6, 7, 8].includes(handle) ? 0 : Math.PI,
]}
/>
</>
);
}

View File

@@ -0,0 +1 @@
__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))

19
bron/index.css Normal file
View File

@@ -0,0 +1,19 @@
/* poppins-latin-ext-400-normal */
@font-face {
font-family: 'Poppins';
font-style: normal;
font-display: swap;
font-weight: 400;
src: url(./files/poppins-latin-ext-400-normal.woff2) format('woff2'), url(./files/poppins-latin-ext-400-normal.woff) format('woff');
unicode-range: U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
/* poppins-latin-400-normal */
@font-face {
font-family: 'Poppins';
font-style: normal;
font-display: swap;
font-weight: 400;
src: url(./files/poppins-latin-400-normal.woff2) format('woff2'), url(./files/poppins-latin-400-normal.woff) format('woff');
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

16
bron/index.js Normal file
View File

@@ -0,0 +1,16 @@
import App from './App'
import './style.css'
import './style0.css'
import './tailwind.css'
import ReactDOM from 'react-dom/client'
import "@fontsource/poppins";
import ConsentBanner from './components/ConsentBanner'
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(
<>
<App />
{/* <ConsentBanner /> */}
</>
)

16
bron/indexx.js Normal file
View File

@@ -0,0 +1,16 @@
import App from './App'
import './style.css'
import './style0.css'
import './tailwind.css'
import ReactDOM from 'react-dom/client'
import "@fontsource/poppins";
import ConsentBanner from './components/ConsentBanner'
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(
<>
<App />
{/* <ConsentBanner /> */}
</>
)

198
bron/information.js Normal file
View File

@@ -0,0 +1,198 @@
import { useContext, useEffect, useState } from "react";
import { MyContext } from "../data/contextapi";
import RequestForm from "../../RequestForm";
const doorTypes = {
Taatsdeur: "TAATSDEUR",
Schuifdeur: "SCHUIFDEUR",
Scharnier: "KOZIJN DEUR",
"vast-stalen": "VAST STALEN",
};
const doorConfigs = {
enkele: "ENKELE DEUR",
dubbele: "DUBBELE DEUR",
};
const panels = {
links: "LINKS",
rechts: "RECHTS",
beide: "BEIDE",
geen: "GEEN",
};
const sidePannelConfigs = {
"gelijk vardelen": "GELIJKE DELEN",
"eigen maat": "EIGEN MAAT",
};
const doors = {
george: "1 paneel",
"2panel": "2 panelen",
"3panel": "3 panelen",
"4panel": "4 panelen",
"3pannel": "3 panelen ongelijk plus",
annelot: "Annelot",
notaris: "Notaris",
boerderij: "Boerderij",
herenhuis: "Herenhuis",
rond: "Rond",
rondPlus: "Rond Plus",
"low-deep": "Low Deep",
rivera: "Rivera",
porto: "Porto",
toog: "Toog",
toogPlus: "Toog plus",
boender: "Boender",
contempera: "Contempera",
fabric: "Fabric",
dt13: "Hoogh",
larino: "Larino",
dt11: "Mexico",
parallel: "Parallel",
grandma: "Grandma",
kasteel: "Kasteel",
kathedraal: "Kathedraal",
"the-judge": "The Judge",
prison: "Prison",
curved: "Curved",
lindsey: "Lindsey",
baku: "Baku",
supreme: "Supreme",
ultimate: "Ultimate",
fisherman: "Fisherman",
primier: "Primier",
elite: "Elite"
};
const handles = [
"Hoeklijn",
"Beugel",
"Circle M",
"Circle L",
"Koker M",
"Koker L",
"Greeploos",
"Handgreep met leer",
];
const colorGlass = {
1118481: "Helderglas",
395529: "Rookglas",
13467442: "Bronsglas",
16777215: "Melkglas"
};
const steelColor = {
"./images/doortypes/RAL 9005 fijn structuur.png": "RAL 9005 fijn structuur",
"./images/doortypes/RAL 9004 fijn structuur.png": "RAL 9004 fijn structuur",
"./images/doortypes/RAL 7021 structuur.png": "RAL 7021 structuur",
"./images/doortypes/RAL 7016 structuur.png": "RAL 7016 structuur",
"./images/doortypes/RAL 9010 structuur.png": "RAL 9010 structuur",
"./images/doortypes/RAL 9016 structuur.png": "RAL 9016 structuur",
"./images/doortypes/Anodic brown.png": "Anodic brown",
"./images/doortypes/Sterling.png": "Sterling",
"./images/doortypes/Nobble bronze.png": "Nobble bronze",
"./images/doortypes/Halo 1036.png": "Halo 1036",
"./images/doortypes/Halo 1037.png": "Halo 1037",
"./images/doortypes/Anodic_bronze.png": "Anodic bronze",
};
export default function Information() {
const {
step,
setStep,
width,
setWidth,
height,
door,
doorConfig,
sidePannel,
type,
sidePannelConfig,
sidePannelSize,
frameSize,
glassType,
handle,
frameType,
customFrameType,
extraOptions,
holeWidth,
attachDesign,
compositionImage,
glContext,
sceneContext,
cameraContext
} = useContext(MyContext);
const [techInformation, setTechInformation] = useState({
type: "",
doorConfig: "",
sidePannel: "",
sidePannelConfig: "",
sidePannelSize: "",
height: "",
doorConfig: "",
width: "",
door: "",
frameSize: "",
handle: "",
colorGlass: "",
steelColor: "",
extraOptions: [],
compositionImage: compositionImage,
});
useEffect(() => {
setTechInformation({
type: doorTypes[type],
doorConfig: doorConfigs[doorConfig],
sidePannel: panels[sidePannel],
sidePannelConfig: sidePannelConfigs[sidePannelConfig],
sidePannelSize,
height: height,
width: width,
holeWidth: holeWidth,
door: doors[door],
frameSize:
frameSize === 0.25 ? "40mm" : frameSize === 0.2 ? "30mm" : "20mm",
handle: handles[handle - 1],
colorGlass: colorGlass[glassType],
steelColor:
customFrameType.name === ""
? steelColor[frameType]
: customFrameType.name,
extraOptions,
compositionImage: compositionImage
});
}, [
type,
doorConfig,
sidePannel,
sidePannelConfig,
sidePannelSize,
height,
doorConfig,
width,
holeWidth,
door,
frameSize,
handle,
glassType,
steelColor,
extraOptions,
customFrameType,
compositionImage
]);
return (
<>
<RequestForm
techInformation={techInformation}
attachDesign={attachDesign}
glContext={glContext}
sceneContext={sceneContext}
cameraContext={cameraContext}
/>
</>
);
}

6
bron/main.4524c4d6.css Normal file

File diff suppressed because one or more lines are too long

72323
bron/main.45858049.js Normal file

File diff suppressed because one or more lines are too long

72323
bron/main.458580499.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
// define __esModule on exports
__webpack_require__.r = (exports) => {
if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
};

View File

@@ -0,0 +1,5 @@
__webpack_require__.nmd = (module) => {
module.paths = [];
if (!module.children) module.children = [];
return module;
};

9
bron/preloader.js Normal file
View File

@@ -0,0 +1,9 @@
export default function Preloader() {
return (
<>
<div style={{ width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center', backgroundSize: 'cover' }}>
<div className="loader"></div>
</div>
</>
)
}

Binary file not shown.

BIN
bron/samenstelling_link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

910
bron/samenstling.js Normal file
View File

@@ -0,0 +1,910 @@
import { useContext, useState } from "react";
import { MyContext } from "../data/contextapi";
import InfoIcon from "./InfoIcon";
export default function Samenstling() {
const {
type,
settype,
setStep,
width,
setWidth,
doorConfig,
setDoorConfig,
sidePannel,
setSidePannel,
sidePannelConfig,
setSidePannelConfig,
sidePannelSize,
setSidePannelSize,
stalenPart,
setStalenPart,
stalenType,
setStalenType,
open,
inprogress,
holeWidth,
setHoleWidth,
} = useContext(MyContext);
const doorImages = {
Taatsdeur: "door_type_1_staging.jpg",
Schuifdeur: "door_type_2_staging.jpg",
Scharnier: "door_type_3.jpg",
"vast-stalen": "door_type_4.jpg",
};
const handleStalenPart = (e) => {
setStalenPart(e.target.value);
};
const handleWidthChange = (e) => {
if (doorConfig === "dubbele" || sidePannel != "geen") {
setSidePannelSize(calculateSidePanelWidth(holeWidth, e.target.value));
setWidth(e.target.value);
} else {
setWidth(e.target.value);
setSidePannelSize(e.target.value);
}
if (sidePannel == "geen") {
setHoleWidth(
doorConfig === "dubbele" ? 2 * e.target.value : e.target.value
);
}
};
const calculateSidePanelWidth = (totalWidth, doorWidth) => {
if (
doorConfig != "dubbele" &&
(sidePannel === "links" || sidePannel === "rechts")
) {
return totalWidth - Number(doorWidth);
}
if (doorConfig == "dubbele" && sidePannel == "geen") {
return 0;
}
if (doorConfig != "dubbele" && sidePannel === "beide") {
return (totalWidth - Number(doorWidth)) / 2;
}
if (
doorConfig == "dubbele" &&
(sidePannel == "links" || sidePannel == "rechts")
) {
return totalWidth - Number(doorWidth) * 2;
}
if (doorConfig == "dubbele" && sidePannel == "beide") {
return (totalWidth - Number(doorWidth) * 2) / 2;
}
return 0;
};
return (
<>
<div style={{ width: "100%", height: "100%" }}>
{type != "vast-stalen" ? (
<>
<div style={{ width: "100%" }}>
<div
style={{
margin: "0 5%",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<span>Samenstelling deur</span>
{/* <div
style={{
backgroundColor: "white",
borderRadius: "20px",
width: "auto",
padding: "2px 10px",
margin: "0 0 0 10px",
}}
>
<span
className="body-txt"
style={{}}
onClick={() => {
setStep("door");
}}
>
&euro; 1200,00
</span>
</div> */}
</div>
</div>
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
gridColumnGap: "10px",
fontSize: "11px",
margin: "5%",
borderBottom: "1px solid #d1d1d1",
paddingBottom: "15px",
}}
>
<div
style={{
position: "relative",
margin: "5px",
}}
onClick={() => {
if (!inprogress) setDoorConfig("enkele");
}}
>
<div
style={{
border:
doorConfig === "enkele" ? "2px solid black" : "none",
borderRadius: "5px",
overflow: "hidden",
backgroundColor: "white",
padding: "10px",
boxShadow:
doorConfig === "enkele"
? "none"
: "rgba(0, 0, 0, 0.6) -5px -2px 10px -2px",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<center>
<img
src={`./images/doortypes/door_type_3_staging.jpg`}
style={{
maxHeight: "100%",
width: "80%",
objectFit: "contain",
}}
/>
</center>
<div
style={{ position: "absolute", top: "2px", right: "2px" }}
>
<input
type="radio"
className="sm"
checked={doorConfig === "enkele"}
readOnly
/>
</div>
</div>
<div
style={{
position: "relative",
paddingTop: "5px",
margin: "10px 0 0 0",
backgroundColor:
doorConfig === "enkele" ? "black" : "#bdc79d",
color: "white",
border: `1px solid ${
doorConfig === "enkele" ? "black" : "white"
}`,
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
borderBottom: `1px solid ${
doorConfig === "enkele" ? "black" : "white"
}`,
}}
/>
<span
style={{
width: "100%",
display: "inline-block",
flex: 1,
textAlign: "center",
textTransform: "uppercase",
padding: "2px 0",
}}
>
Enkele deur
</span>
</div>
</div>
<div
style={{
position: "relative",
margin: "5px",
}}
onClick={() => {
if (!inprogress) setDoorConfig("dubbele");
}}
>
<div
style={{
border:
doorConfig === "dubbele" ? "2px solid black" : "none",
borderRadius: "10px",
boxShadow: "-5px -2px 10px -2px rgba(0,0,0,0.6)",
padding: "10px",
backgroundColor: "white",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<center>
<img
src={`./images/doortypes/double-door-type_staging.jpg`}
style={{
maxWidth: "80%",
maxHeight: "100%",
}}
/>
</center>
<div
style={{ position: "absolute", top: "2px", right: "2px" }}
>
<input
type="radio"
className="sm"
checked={doorConfig === "dubbele"}
readOnly
/>
</div>
</div>
<div
style={{
position: "relative",
margin: "10px 0 0 0",
paddingTop: "5px",
backgroundColor:
doorConfig === "dubbele" ? "black" : "#bdc79d",
color: "white",
border: `1px solid ${
doorConfig === "dubbele" ? "black" : "white"
}`,
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
borderBottom: `1px solid ${
doorConfig === "dubbele" ? "black" : "white"
}`,
}}
/>
<span
style={{
width: "100%",
display: "inline-block",
flex: 1,
textTransform: "uppercase",
textAlign: "center",
padding: "2px 0",
}}
>
Dubbele deur
</span>
</div>
</div>
</div>
<div style={{ width: "100%" }}>
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<InfoIcon title={"Samenstelling zijpaneel"} />
{/* <div
style={{
backgroundColor: "white",
borderRadius: "20px",
width: "auto",
padding: "2px 10px",
margin: "0 0 0 10px",
}}
>
<span
className="body-txt"
style={{}}
onClick={() => {
setStep("door");
}}
>
&euro; 900,00
</span>
</div> */}
</div>
</div>
<div
className="door-content-2"
style={{
borderBottom: "25px",
}}
>
<div
className="door-content-2-1"
style={{
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
gridColumnGap: "10px",
fontSize: "11px",
padding: "5%",
borderBottom: "2px solid #d1d1d1",
}}
>
<div
style={{
position: "relative",
margin: "5px",
}}
onClick={() => {
if (!inprogress) setSidePannel("links");
}}
>
<div
style={{
border:
sidePannel === "links"
? "2px solid black"
: "2px solid #d7d7d7",
borderRadius: "5px",
overflow: "hidden",
boxShadow:
sidePannel === "links"
? "none"
: "rgba(0, 0, 0, 0.6) -5px -2px 10px -2px",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div
style={{ position: "absolute", top: "2px", right: "2px" }}
>
<input
type="radio"
className="sm"
checked={sidePannel === "links"}
readOnly
/>
</div>
<center>
<img
src="./images/doortypes/samenstelling_link.png"
style={{
maxWidth: "80%",
maxHeight: "100%",
objectFit: "contain",
}}
/>
</center>
</div>
<div
style={{
position: "relative",
margin: "10px 0 0 0",
backgroundColor:
sidePannel === "links" ? "black" : "#bdc79d",
color: "white",
paddingTop: "5px",
// border: '2px solid white',
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
links
</span>
</div>
</div>
<div
style={{
position: "relative",
margin: "5px",
borderRadius: "5px",
}}
onClick={() => {
if (!inprogress) setSidePannel("rechts");
}}
>
<div
style={{
border:
sidePannel === "rechts"
? "2px solid black"
: "2px solid #d7d7d7",
borderRadius: "5px",
overflow: "hidden",
boxShadow:
sidePannel === "rechts"
? "none"
: "rgba(0, 0, 0, 0.6) -5px -2px 10px -2px",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div
style={{ position: "absolute", top: "2px", right: "2px" }}
>
<input
type="radio"
className="sm"
checked={sidePannel === "rechts"}
readOnly
/>
</div>
<center>
<img
src="./images/doortypes/samenstelling_rechts.png"
style={{ maxWidth: "80%", maxHeight: "100%" }}
/>
</center>
</div>
<div
style={{
position: "relative",
paddingTop: "5px",
margin: "10px 0 0 0",
backgroundColor:
sidePannel === "rechts" ? "black" : "#bdc79d",
color: "white",
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
rechts
</span>
</div>
</div>
<div
style={{
position: "relative",
margin: "5px",
}}
onClick={() => {
if (!inprogress) setSidePannel("beide");
}}
>
<div
style={{
border:
sidePannel === "beide"
? "2px solid black"
: "2px solid #d7d7d7",
borderRadius: "5px",
overflow: "hidden",
boxShadow:
sidePannel === "beide"
? "none"
: "rgba(0, 0, 0, 0.6) -5px -2px 10px -2px",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div
style={{ position: "absolute", top: "2px", right: "2px" }}
>
<input
type="radio"
className="sm"
checked={sidePannel === "beide"}
readOnly
/>
</div>
<center>
<img
src="./images/doortypes/samenstelling_beide.png"
style={{ maxWidth: "80%", maxHeight: "100%" }}
/>
</center>
</div>
<div
style={{
position: "relative",
paddingTop: "5px",
margin: "10px 0 0 0",
backgroundColor:
sidePannel === "beide" ? "black" : "#bdc79d",
color: "white",
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
beide
</span>
</div>
</div>
<div
style={{
position: "relative",
margin: "5px",
borderRadius: "5px",
}}
onClick={() => {
if (!inprogress) {
setSidePannel("geen");
setSidePannelSize(width);
}
}}
>
<div
style={{
border:
sidePannel === "geen"
? "2px solid black"
: "2px solid #d7d7d7",
borderRadius: "5px",
overflow: "hidden",
boxShadow:
sidePannel === "geen"
? "none"
: "rgba(0, 0, 0, 0.6) -5px -2px 10px -2px",
aspectRatio: "1/1",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div
style={{ position: "absolute", top: "2px", right: "2px" }}
>
<input
type="radio"
className="sm"
checked={sidePannel === "geen"}
readOnly
/>
</div>
<center>
<img
src="./images/doortypes/samenstelling_geen.png"
style={{ maxWidth: "80%", maxHeight: "100%" }}
/>
</center>
</div>
<div
style={{
position: "relative",
paddingTop: "5px",
margin: "10px 0 0 0",
backgroundColor:
sidePannel === "geen" ? "black" : "#bdc79d",
color: "white",
}}
>
<div
style={{
position: "absolute",
top: "-5px",
left: "0",
width: "100%",
height: "8px",
borderRadius: "50px",
backgroundColor: "#fff",
}}
/>
<span
className="itm-txt"
style={{
display: "block",
wordWrap: "break-word",
textAlign: "center",
fontWeight: "normal",
textTransform: "uppercase",
}}
>
geen
</span>
</div>
</div>
</div>
</div>
</>
) : (
<>
<div style={{ width: "100%" }}>
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<span>Situatie van het vaste paneel</span>
{/* <div
style={{
backgroundColor: "white",
borderRadius: "20px",
width: "auto",
padding: "10px",
margin: "0 0 0 10px",
}}
>
<span
className="body-txt"
style={{}}
onClick={() => {
setStep("door");
}}
>
&euro; 0,00
</span>
</div> */}
</div>
</div>
<div
style={{
fontSize: "small",
display: "flex",
flexDirection: "column",
margin: "5%",
}}
>
<div style={{ display: "flex", alignItems: "center" }}>
<input
type="radio"
className="sm"
checked={stalenType == "divider"}
readOnly
onChange={() => {
setStalenType("divider");
}}
/>
<span style={{ marginLeft: "0.5rem" }}>Roomdivider</span>
</div>
<div style={{ display: "flex", alignItems: "center" }}>
<input
type="radio"
className="sm"
checked={stalenType == "tussen"}
readOnly
onChange={() => {
setStalenType("tussen");
}}
/>
<span style={{ marginLeft: "0.5rem" }}>Tussen 2 wanden</span>
</div>
</div>
<div style={{ width: "100%" }}>
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<span>Aantal panelen</span>
{/* <div
style={{
backgroundColor: "white",
borderRadius: "20px",
width: "auto",
padding: "10px",
margin: "0 0 0 10px",
}}
>
<span
className="body-txt"
style={{}}
onClick={() => {
setStep("door");
}}
>
&euro; 0,00
</span>
</div> */}
</div>
</div>
<div
className="slider-container"
style={{ display: "flex", alignItems: "center", padding: "5%" }}
>
<div style={{ flex: 1 }}>
<input
type="range"
min="1"
max="4"
value={stalenPart}
onChange={handleStalenPart}
style={{
width: "100%",
height: "8px",
borderRadius: "5px",
appearance: "none",
background: "#F2F2F3",
outline: "none",
marginTop: "10px",
}}
/>
</div>
<div
style={{
marginLeft: "10px",
paddingLeft: "10px",
paddingRight: "10px",
paddingTop: "5px",
paddingBottom: "5px",
backgroundColor: "#F2F2F3",
position: "relative",
width: "6rem",
fontSize: "small",
borderRadius: "4px",
}}
>
<span style={{ marginRight: "10px" }}>{stalenPart}</span>
<span>panelen</span>
</div>
</div>
</>
)}
{type !== "vast-stalen" && (
<>
<div style={{ width: "100%" }}>
<div
style={{
margin: "5%",
paddingTop: "0.5rem",
display: "flex",
justifyContent: "space-between",
fontWeight: "bolder",
fontSize: "normal",
}}
>
<InfoIcon title={"Breedte deur"} />
</div>
</div>
<div style={{ display: "flex", alignItems: "center" }}>
<div style={{ flex: 1 }}>
<input
type="range"
min={60}
max={120}
value={width}
onChange={handleWidthChange}
style={{
width: "100%",
height: "8px",
borderRadius: "5px",
appearance: "none",
background: "#F2F2F3", // Grey line
outline: "none", // Remove default outline
marginTop: "10px", // Adjust margin to separate from the text above
}}
/>
</div>
<div
style={{
marginLeft: "10px",
paddingLeft: "10px",
paddingRight: "10px",
paddingTop: "5px",
paddingBottom: "5px",
backgroundColor: "#F2F2F3",
position: "relative",
width: "5rem",
fontSize: "small",
border: "1px solid",
borderRadius: "4px",
}}
>
<span style={{ marginRight: "10px" }}>{width}</span>
<span
style={{
position: "absolute",
right: "10px",
top: "50%",
transform: "translateY(-50%)",
}}
>
cm
</span>
</div>
</div>
</>
)}
<button
className="volgende btn"
onClick={() => {
setStep("design");
}}
>
Volgende
</button>
</div>
</>
);
}

246
bron/style.css Normal file
View File

@@ -0,0 +1,246 @@
/* CSS Styles for endpoint.js Starts*/
/* CSS Styles for Computer in endpoint.js Starts */
.body-can-2 {
width: 100%;
height: 100%;
display: flex;
}
.body-can-2-1 {
position: relative;
/* Change to relative */
display: flex;
width: 100%;
}
.door-content-2-1{
grid-template-columns: repeat(2 , 1fr);
grid-template-rows: repeat(1 , 1fr);
}
.step-content {
box-shadow: 0px -8px 10px -5px rgba(0, 0, 0, 0.8);
overflow-y: hidden;
z-index: 99999;
padding: 0 0 10px 0;
background-color: #fff;
}
.body-can-2-1-1 {
position: relative;
height: 100%;
width: calc(100% - 400px);
}
.body-can-2-1-2 {
right: 0;
background-color: white;
height: 100%;
width: 400px;
overflow-y: auto;
}
.body-btn {
margin: 0 10px 5px 10px;
width: 70px;
height: 35px;
font-size: 26px;
font-weight: 700;
line-height: 1;
background-color: #bdc79d;
color: white;
border: 2px solid #bdc79d;
position: relative;
font-family: 'Poppins', sans-serif;
cursor: pointer;
/* Ensure the parent container is relative */
}
.body-txt {
font-size: 16px;
font-weight: bold;
color: #110000;
text-transform: uppercase;
}
.itm-txt {
font-size: small;
}
/* Hide the scrollbar track (the background) */
::-webkit-scrollbar-track {
background: white;
/* Use any background color you want */
}
/* Customize the scrollbar thumb (the draggable part) */
::-webkit-scrollbar-thumb {
background-color: gray;
/* Color of the scrollbar thumb */
border-radius: 10px;
/* Rounded corners of the scrollbar thumb */
}
/* Hide the scrollbar buttons (arrows at the ends) */
::-webkit-scrollbar-button {
display: none;
}
/* Optional: Customize the scrollbar corner */
::-webkit-scrollbar-corner {
background: transparent;
/* Background color of the scrollbar corner */
}
/* Hide the scrollbar on hover */
::-webkit-scrollbar:hover {
width: 8px;
/* Width of the scrollbar on hover */
}
/* Optional: Add a shadow to the scrollbar */
::-webkit-scrollbar {
width: 8px;
/* Width of the scrollbar */
height: 8px;
/* Height of the scrollbar */
background-color: transparent;
/* Background color of the scrollbar area */
border-radius: 10px;
/* Rounded corners of the scrollbar */
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
/* Shadow inside the scrollbar */
}
#range1 {
-webkit-appearance: none;
appearance: none;
width: 100%;
cursor: pointer;
outline: none;
border-radius: 16px;
}
::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
height: 20px;
width: 20px;
background-color: red;
border-radius: 50%;
border: 2px solid white;
z-index: 12;
/* box-shadow: -407px 0 0 400px #f50; */
}
.quot {
height: 2rem;
}
.volgende.btn {
background-color: #bdc79d;
}
.btn:hover {
background-color: black;
}
.consent-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #f1f1f1;
padding: 15px;
text-align: center;
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
}
.consent-banner button {
margin: 0 10px;
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
.consent-banner button:hover {
background-color: #0056b3;
}
/* CSS Styles for Mobile in endpoint.js Ends */
/* CSS Styles for endpoint.js Ends*/
@media screen and (max-width: 800px) {
.ham-icon {
display: none;
}
.body-can-2-1-1 {
height: 33%;
width: 100%;
}
.body-can-2-1-2 {
position: absolute;
bottom: 0;
width: 100%;
height: 67%;
}
.door-content-2-1{
grid-template-columns: repeat(4 , 1fr);
grid-template-rows: repeat(1 , 1fr);
}
.step-content.collapsed {
padding-bottom: 3px;
}
.body-btn.collapsed {
width: 30px;
height: 20px;
font-size: 14px;
}
.body-txt.collapsed {
font-size: 14px;
}
.radio.collapsed {
width: 15px;
height: 15px;
}
}
@media screen and (max-width: 490px) {
.body-btn {
margin: 7px 10px 3px 10px;
width: 45px;
height: 30px;
}
.quot {
height: 1rem;
display: none !important;
}
}
@media screen and (max-width: 500px) {
.pd {
margin-bottom: 10rem;
}
}
@media screen and (max-width: 400px) {
.itm-txt {
font-size: x-small;
}
}
@media screen and (max-width: 350px) {
.itm-txt {
font-size: xx-small;
}
}

132
bron/style0.css Normal file
View File

@@ -0,0 +1,132 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
html,
body,
#root {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background: #efefef;
font-family: 'Poppins', sans-serif;
}
img {
vertical-align: bottom;
}
input[type='radio'] {
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background-clip: content-box;
border: 2px solid #bdc79d;
background-color: white;
}
input[type='radio'].sm {
width: 15px;
height: 15px;
}
input[type='radio']:checked {
background-color: #bdc79d;
/* padding: 2px; */
border: 2px solid #bdc79d;
}
input[type='checkbox'] {
accent-color: #bdc79d;
background-color: white;
}
.loader {
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
/* Safari */
animation: spin 2s linear infinite;
}
/* Safari */
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.volgende {
background-color: #fab500;
cursor: pointer;
border-radius: 20px;
padding: 5px 10px;
border: none;
color: white;
margin: 5%;
height: 2.5rem;
width: 6rem;
}
.volgende:hover {
background-color: #000000;
}
input[type='range']::-webkit-slider-thumb {
appearance: none;
width: 16px;
height: 16px;
background-color: #bdc79d;
border-radius: 50%;
cursor: pointer;
}
input[type='number']::-webkit-inner-spin-button {
opacity: 1;
}
.handle-title-box {
display: flex;
justify-content: center;
align-items: center;
margin: 10px 0 0 0;
color: white;
position: relative;
height: 40px;
cursor: pointer;
}
.flex-center-box {
display: flex;
justify-content: center;
align-items: center;
}
/* .door-content-2-1 {
display: flex;
} */
/* .door-content-2-1>div>div {
box-shadow: 0px 8px 0px 0px rgba(0, 0, 0, 0.3);
}
.door-content-2-1>div>div:hover {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
} */

3
bron/tailwind.css Normal file
View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;