feat : save map.json on project

This commit is contained in:
math-pixel
2026-04-23 15:40:10 +02:00
parent d0cf876372
commit 6b8ba3d58d
5 changed files with 122 additions and 11 deletions
+46 -10
View File
@@ -2,22 +2,58 @@
{
"name": "test_cube",
"type": "Mesh",
"position": [0, 5, 0],
"rotation": [0, 0, 0],
"scale": [2, 2, 2]
"position": [
0,
5,
0
],
"rotation": [
0,
0,
0
],
"scale": [
2,
2,
2
]
},
{
"name": "test_sphere",
"type": "Mesh",
"position": [10, 5, 0],
"rotation": [0, 0, 0],
"scale": [3, 3, 3]
"position": [
-35.67436887305092,
-12.343540259022419,
0
],
"rotation": [
0,
0,
0
],
"scale": [
3,
3,
3
]
},
{
"name": "test_cylinder",
"type": "Mesh",
"position": [-10, 5, 0],
"rotation": [0, 0, 0],
"scale": [1, 4, 1]
"position": [
-10,
5,
0
],
"rotation": [
0,
0,
0
],
"scale": [
1,
4,
1
]
}
]
]
+8
View File
@@ -11,6 +11,7 @@ interface EditorControlsProps {
onUndo: () => void;
onRedo: () => void;
onExportJson: () => void;
onSaveToServer?: () => void;
onResetCamera?: () => void;
onPlayerMode?: () => void;
isPlayerMode?: boolean;
@@ -27,6 +28,7 @@ export default function EditorControls({
onUndo,
onRedo,
onExportJson,
onSaveToServer,
onResetCamera,
onPlayerMode,
isPlayerMode,
@@ -89,6 +91,12 @@ export default function EditorControls({
💾 Export JSON
</button>
{onSaveToServer && (
<button className="save-button" onClick={onSaveToServer}>
💾 Save to Server
</button>
)}
<h3>View</h3>
{onResetCamera && (
+17
View File
@@ -236,6 +236,23 @@ code {
background: #ff8533;
}
.save-button {
width: 100%;
margin-top: 10px;
padding: 12px;
background: #22c55e;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
}
.save-button:hover {
background: #16a34a;
}
.reset-button {
width: 100%;
padding: 12px;
+23
View File
@@ -145,6 +145,28 @@ export function EditorPage(): React.JSX.Element {
}
}, [applySnapshot]);
const handleSaveToServer = useCallback(async () => {
if (!sceneData) return;
const json = JSON.stringify(sceneData.mapNodes, null, 2);
try {
const response = await fetch("/api/save-map", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: json,
});
if (response.ok) {
alert("Map enregistrée avec succès!");
} else {
alert("Erreur lors de l'enregistrement");
}
} catch (err) {
console.error("Error saving map:", err);
alert("Erreur lors de l'enregistrement");
}
}, [sceneData]);
const handleExportJson = useCallback(() => {
if (!sceneData) return;
const json = JSON.stringify(sceneData.mapNodes, null, 2);
@@ -406,6 +428,7 @@ export function EditorPage(): React.JSX.Element {
onUndo={handleUndo}
onRedo={handleRedo}
onExportJson={handleExportJson}
onSaveToServer={handleSaveToServer}
onResetCamera={handleResetCamera}
onPlayerMode={handlePlayerMode}
isPlayerMode={isPlayerMode}
+28 -1
View File
@@ -1,10 +1,37 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "node:path";
import fs from "node:fs";
import type { ViteDevServer } from "vite";
const saveMapPlugin = () => ({
name: "save-map-api",
configureServer(server: ViteDevServer) {
server.middlewares.use("/api/save-map", async (req: any, res: any) => {
if (req.method !== "POST") {
res.writeHead(405).end();
return;
}
let body = "";
req.on("data", (chunk: any) => (body += chunk));
req.on("end", () => {
try {
const mapPath = path.resolve(__dirname, "public/map.json");
fs.writeFileSync(mapPath, body);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ success: true }));
} catch (err: any) {
res.writeHead(500).end(JSON.stringify({ error: err.message }));
}
});
});
},
});
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
plugins: [react(), saveMapPlugin()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),