Spaces:
Configuration error
Configuration error
File size: 3,064 Bytes
256b016 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
// 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; |