53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
import React, { createContext, useContext, useState } from "react";
|
|
import { api } from "../api/client";
|
|
|
|
export interface UploadContextModel {
|
|
uploadFile: (file: File) => Promise<string | null>;
|
|
uploading: boolean;
|
|
error: string | null;
|
|
}
|
|
|
|
const UploadContext = createContext<UploadContextModel | undefined>(undefined);
|
|
|
|
export const UploadProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
const [uploading, setUploading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const uploadFile = async (file: File): Promise<string | null> => {
|
|
setUploading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
const binary = new Uint8Array(arrayBuffer);
|
|
|
|
const res = await api.post("/uploads", binary, {
|
|
headers: {
|
|
"Content-Type": file.type,
|
|
"Content-Disposition": `attachment; filename="${file.name}"`,
|
|
},
|
|
});
|
|
|
|
return res.data.url as string;
|
|
} catch (err: any) {
|
|
console.error("File upload failed:", err);
|
|
setError(err.response?.data?.detail || "Failed to upload file");
|
|
return null;
|
|
} finally {
|
|
setUploading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<UploadContext.Provider value={{ uploadFile, uploading, error }}>
|
|
{children}
|
|
</UploadContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useUpload = (): UploadContextModel => {
|
|
const ctx = useContext(UploadContext);
|
|
if (!ctx) throw new Error("useUpload must be used within UploadProvider");
|
|
return ctx;
|
|
};
|