Fix jwt-token
This commit is contained in:
@@ -148,6 +148,8 @@ const BrandingSettings = ({ tenantConfig, onRefresh }) => {
|
||||
company_name: ''
|
||||
});
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [logoPreview, setLogoPreview] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (tenantConfig?.branding) {
|
||||
@@ -168,6 +170,56 @@ const BrandingSettings = ({ tenantConfig, onRefresh }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogoUpload = async (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
// Validate file type
|
||||
if (!file.type.startsWith('image/')) {
|
||||
toast.error('Please select an image file');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate file size (5MB)
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
toast.error('File size must be less than 5MB');
|
||||
return;
|
||||
}
|
||||
|
||||
setUploading(true);
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('logo', file);
|
||||
|
||||
const response = await api.post('/tenant/logo-upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
setBranding(prev => ({ ...prev, logo_url: response.data.data.logo_url }));
|
||||
setLogoPreview(null);
|
||||
toast.success('Logo uploaded successfully');
|
||||
if (onRefresh) onRefresh();
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Failed to upload logo');
|
||||
} finally {
|
||||
setUploading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFilePreview = (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (file && file.type.startsWith('image/')) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => setLogoPreview(e.target.result);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white shadow rounded-lg">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
@@ -184,14 +236,70 @@ const BrandingSettings = ({ tenantConfig, onRefresh }) => {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700">Logo URL</label>
|
||||
<input
|
||||
type="url"
|
||||
value={branding.logo_url}
|
||||
onChange={(e) => setBranding(prev => ({ ...prev, logo_url: e.target.value }))}
|
||||
className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500"
|
||||
placeholder="https://example.com/logo.png"
|
||||
/>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Company Logo</label>
|
||||
|
||||
{/* Current logo display */}
|
||||
{branding.logo_url && (
|
||||
<div className="mb-4">
|
||||
<img
|
||||
src={branding.logo_url.startsWith('http') ? branding.logo_url : `${api.defaults.baseURL.replace('/api', '')}${branding.logo_url}`}
|
||||
alt="Current logo"
|
||||
className="h-16 w-auto object-contain border border-gray-200 rounded p-2"
|
||||
onError={(e) => {
|
||||
e.target.style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Current logo</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Upload interface */}
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex-1">
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={(e) => {
|
||||
handleFilePreview(e);
|
||||
handleLogoUpload(e);
|
||||
}}
|
||||
className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-medium file:bg-primary-50 file:text-primary-700 hover:file:bg-primary-100"
|
||||
disabled={uploading}
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">PNG, JPG up to 5MB</p>
|
||||
</div>
|
||||
|
||||
{uploading && (
|
||||
<div className="flex items-center">
|
||||
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-primary-600"></div>
|
||||
<span className="ml-2 text-sm text-gray-600">Uploading...</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Preview */}
|
||||
{logoPreview && (
|
||||
<div className="mt-4">
|
||||
<img
|
||||
src={logoPreview}
|
||||
alt="Logo preview"
|
||||
className="h-16 w-auto object-contain border border-gray-200 rounded p-2"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Preview</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Manual URL input as fallback */}
|
||||
<div className="mt-4">
|
||||
<label className="block text-sm font-medium text-gray-700">Or enter logo URL manually</label>
|
||||
<input
|
||||
type="url"
|
||||
value={branding.logo_url}
|
||||
onChange={(e) => setBranding(prev => ({ ...prev, logo_url: e.target.value }))}
|
||||
className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500"
|
||||
placeholder="https://example.com/logo.png"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
|
||||
Reference in New Issue
Block a user