-
+
+
+
+
+
-
Swap Stations
-
Never wait to charge. Swap your depleted battery for a fully charged one in less than 2 minutes.
+
+
Swap Stations
+
Never wait to charge. Swap your depleted battery for a fully charged one in less than 2 minutes.
+
- {/* Service 4 (Merchant/Rent to own) */}
-
-
-
-
-
-
-
-
Merchants & Deliveries
-
Are you a delivery partner or company? Request any amount of riders for your delivery needs. Partner with us for dedicated EV riders.
-
-
+ {/* Service 3 (Merchant/Deliveries) */}
+
+
+
+
+
+
+
Merchants & Deliveries
+
Are you a delivery partner or company? Request any amount of riders for your delivery needs. Partner with us for dedicated EV riders.
+
+
diff --git a/src/components/ui/3d/CardIcon3D.tsx b/src/components/ui/3d/CardIcon3D.tsx
index 11356b1..44a32ee 100644
--- a/src/components/ui/3d/CardIcon3D.tsx
+++ b/src/components/ui/3d/CardIcon3D.tsx
@@ -3,20 +3,56 @@ import { useRef } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Float, Torus, Cylinder, Box, Octahedron, MeshTransmissionMaterial } from '@react-three/drei';
import * as THREE from 'three';
+import { useLoader } from '@react-three/fiber';
+import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
+import { Suspense, useMemo } from 'react';
+
+function ActualBikeIcon() {
+ const obj = useLoader(OBJLoader, '/uploads_files_3634924_uploads_files_850048_aerox.obj');
+ const group = useRef
(null);
+
+ const model = useMemo(() => {
+ const clone = obj.clone();
+
+ const box = new THREE.Box3().setFromObject(clone);
+ const center = box.getCenter(new THREE.Vector3());
+ const size = box.getSize(new THREE.Vector3());
+ const maxDim = Math.max(size.x, size.y, size.z);
+
+ const scale = 2.0 / maxDim;
+ clone.scale.setScalar(scale);
+ clone.position.sub(center.multiplyScalar(scale));
+ clone.rotation.y = -Math.PI / 4;
+
+ const bodyMat = new THREE.MeshStandardMaterial({ color: '#00bc84', roughness: 0.2, metalness: 0.8 });
+ const darkMat = new THREE.MeshStandardMaterial({ color: '#111111', roughness: 0.9 });
+
+ clone.traverse((child) => {
+ if (child instanceof THREE.Mesh) {
+ const b = new THREE.Box3().setFromObject(child);
+ const s = new THREE.Vector3();
+ b.getSize(s);
+ const minLocal = Math.min(s.x, s.y, s.z);
+ const maxLocal = Math.max(s.x, s.y, s.z);
+ if (minLocal < 0.3 && maxLocal > 0.4) child.material = darkMat;
+ else child.material = bodyMat;
+ }
+ });
+
+ return clone;
+ }, [obj]);
-function BikeIcon() {
- const mesh = useRef(null);
useFrame((_, delta) => {
- if (mesh.current) {
- mesh.current.rotation.y += delta;
- mesh.current.rotation.x += delta * 0.5;
+ if (group.current) {
+ group.current.rotation.y += delta * 1.5;
}
});
+
return (
-
-
-
-
+
+
+
+
);
}
@@ -38,44 +74,68 @@ function InvestorIcon() {
}
function SwapIcon() {
- const mesh = useRef(null);
+ const group = useRef(null);
useFrame((_, delta) => {
- if (mesh.current) {
- mesh.current.rotation.x += delta;
- mesh.current.rotation.y += delta * 1.2;
+ if (group.current) {
+ group.current.rotation.y += delta * 1.2;
}
});
return (
-
-
-
-
-
-
-
+
+
+ {/* Main Station Body */}
+
+
+
+ {/* Glowing Screen */}
+
+
+
+ {/* Battery Slots Container */}
+
+
+
+ {/* Battery 1 inside slot */}
+
+
+
+ {/* Battery 2 inside slot */}
+
+
+
+
);
}
function MerchantIcon() {
- const mesh = useRef(null);
+ const group = useRef(null);
useFrame((_, delta) => {
- if (mesh.current) {
- mesh.current.rotation.x += delta * 0.5;
- mesh.current.rotation.y += delta;
+ if (group.current) {
+ group.current.rotation.y += delta * 1.2;
+ group.current.rotation.z = Math.sin(_.clock.elapsedTime * 3) * 0.05;
}
});
return (
-
-
-
-
+
+
+ {/* Main Cargo Box */}
+
+
+
+ {/* Tape / Ribbon 1 */}
+
+
+
+ {/* Tape / Ribbon 2 */}
+
+
+
+ {/* Delivery Logo / Detail */}
+
+
+
+
);
}
@@ -87,7 +147,9 @@ export default function CardIcon3D({ type }: { type: 'bike' | 'investor' | 'swap
- {type === 'bike' && }
+
+ {type === 'bike' && }
+
{type === 'investor' && }
{type === 'swap' && }
{type === 'merchant' && }