images
This commit is contained in:
@@ -93,6 +93,19 @@ export const api = {
|
|||||||
}
|
}
|
||||||
return json.data;
|
return json.data;
|
||||||
},
|
},
|
||||||
|
async getFileContentBlob(token: string, fileId: string) {
|
||||||
|
const response = await fetch(`/api/v1/files/${fileId}/content`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new ApiError("Unable to load file content.", "FILE_CONTENT_FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.blob();
|
||||||
|
},
|
||||||
getCustomers(token: string, filters?: { q?: string; status?: CrmRecordStatus; state?: string }) {
|
getCustomers(token: string, filters?: { q?: string; status?: CrmRecordStatus; state?: string }) {
|
||||||
return request<CrmRecordSummaryDto[]>(
|
return request<CrmRecordSummaryDto[]>(
|
||||||
`/api/v1/crm/customers${buildQueryString({
|
`/api/v1/crm/customers${buildQueryString({
|
||||||
|
|||||||
@@ -13,14 +13,36 @@ export function CompanySettingsPage() {
|
|||||||
const [logoUrl, setLogoUrl] = useState<string | null>(null);
|
const [logoUrl, setLogoUrl] = useState<string | null>(null);
|
||||||
const [status, setStatus] = useState<string>("Loading company profile...");
|
const [status, setStatus] = useState<string>("Loading company profile...");
|
||||||
|
|
||||||
|
async function loadLogoPreview(nextToken: string, logoFileId: string | null) {
|
||||||
|
if (!logoFileId) {
|
||||||
|
setLogoUrl((current) => {
|
||||||
|
if (current?.startsWith("blob:")) {
|
||||||
|
window.URL.revokeObjectURL(current);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = await api.getFileContentBlob(nextToken, logoFileId);
|
||||||
|
const objectUrl = window.URL.createObjectURL(blob);
|
||||||
|
setLogoUrl((current) => {
|
||||||
|
if (current?.startsWith("blob:")) {
|
||||||
|
window.URL.revokeObjectURL(current);
|
||||||
|
}
|
||||||
|
return objectUrl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let active = true;
|
||||||
|
|
||||||
api.getCompanyProfile(token).then((profile) => {
|
api.getCompanyProfile(token).then((profile) => {
|
||||||
setCompanyId(profile.id);
|
setCompanyId(profile.id);
|
||||||
setLogoUrl(profile.logoUrl);
|
|
||||||
setForm({
|
setForm({
|
||||||
companyName: profile.companyName,
|
companyName: profile.companyName,
|
||||||
legalName: profile.legalName,
|
legalName: profile.legalName,
|
||||||
@@ -38,9 +60,37 @@ export function CompanySettingsPage() {
|
|||||||
});
|
});
|
||||||
applyBrandProfile(profile);
|
applyBrandProfile(profile);
|
||||||
setStatus("Company profile loaded.");
|
setStatus("Company profile loaded.");
|
||||||
|
|
||||||
|
if (profile.theme.logoFileId) {
|
||||||
|
loadLogoPreview(token, profile.theme.logoFileId)
|
||||||
|
.then(() => {
|
||||||
|
if (!active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
if (active) {
|
||||||
|
setLogoUrl(null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setLogoUrl(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
active = false;
|
||||||
|
};
|
||||||
}, [applyBrandProfile, token]);
|
}, [applyBrandProfile, token]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (logoUrl?.startsWith("blob:")) {
|
||||||
|
window.URL.revokeObjectURL(logoUrl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [logoUrl]);
|
||||||
|
|
||||||
if (!form || !token) {
|
if (!form || !token) {
|
||||||
return <div className="rounded-[28px] border border-line/70 bg-surface/90 p-8 text-sm text-muted shadow-panel">{status}</div>;
|
return <div className="rounded-[28px] border border-line/70 bg-surface/90 p-8 text-sm text-muted shadow-panel">{status}</div>;
|
||||||
}
|
}
|
||||||
@@ -52,7 +102,7 @@ export function CompanySettingsPage() {
|
|||||||
}
|
}
|
||||||
const profile = await api.updateCompanyProfile(token, form);
|
const profile = await api.updateCompanyProfile(token, form);
|
||||||
applyBrandProfile(profile);
|
applyBrandProfile(profile);
|
||||||
setLogoUrl(profile.logoUrl);
|
await loadLogoPreview(token, profile.theme.logoFileId);
|
||||||
setStatus("Company settings saved.");
|
setStatus("Company settings saved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +124,7 @@ export function CompanySettingsPage() {
|
|||||||
}
|
}
|
||||||
: current
|
: current
|
||||||
);
|
);
|
||||||
setLogoUrl(`/api/v1/files/${attachment.id}/content`);
|
await loadLogoPreview(token, attachment.id);
|
||||||
setStatus("Logo uploaded. Save to persist it on the profile.");
|
setStatus("Logo uploaded. Save to persist it on the profile.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user