clodesigner / frontend /src /useStore.js
nimzuk's picture
Initial clean snapshot (no node_modules)
256b016
// frontend/src/useStore.js
import { create } from "zustand";
// небольшие хелперы для запросов
const postJSON = async (url, body) => {
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
};
const postFile = async (url, file) => {
const fd = new FormData();
fd.append("file", file);
const res = await fetch(url, { method: "POST", body: fd });
if (!res.ok) throw new Error(await res.text());
return res.json();
};
const useStore = create((set, get) => ({
// состояние
model: "MT",
view: "front",
tile: false,
offsetX: 0,
offsetY: 0,
scale: 1,
uploadedPath: null,
busy: false,
lastPreviewUrls: null,
lastOrderInfo: null,
// сеттеры
setModel: (model) => set({ model }),
setView: (view) => set({ view }),
setTile: (tile) => set({ tile }),
setOffsetX: (offsetX) => set({ offsetX }),
setOffsetY: (offsetY) => set({ offsetY }),
setScale: (scale) => set({ scale }),
// 1) загрузка принта
async upload(file) {
set({ busy: true });
try {
const { path } = await postFile("/api/upload", file);
set({ uploadedPath: path });
return path;
} finally {
set({ busy: false });
}
},
// 2) построение превью из текущих контролов
async spread() {
const { model, view, tile, offsetX, offsetY, scale, uploadedPath } = get();
if (!uploadedPath) throw new Error("Сначала загрузите принт");
set({ busy: true });
try {
const payload = {
model,
view,
details: {
print_path: uploadedPath,
tile,
offset_x: offsetX,
offset_y: offsetY,
scale,
},
};
const data = await postJSON("/api/preview", payload);
const urls =
data.previews ||
(data.preview_url ? { [view]: data.preview_url } : null);
set({ lastPreviewUrls: urls });
return data;
} finally {
set({ busy: false });
}
},
// удобный комбинированный экшен под кнопку "Upload / Spread"
async uploadAndSpread(file) {
await get().upload(file);
return get().spread();
},
// 3) создание заказа
async startOrder() {
const { model, view, tile, offsetX, offsetY, scale, uploadedPath } = get();
if (!uploadedPath) throw new Error("Сначала загрузите принт");
set({ busy: true });
try {
const payload = {
model,
view,
details: {
print_path: uploadedPath,
tile,
offset_x: offsetX,
offset_y: offsetY,
scale,
},
};
const data = await postJSON("/api/order", payload);
set({ lastOrderInfo: data });
return data;
} finally {
set({ busy: false });
}
},
}));
export default useStore;