missions s3
This commit is contained in:
parent
9f9280fbe8
commit
cf7538225e
@ -17,7 +17,7 @@ import {
|
|||||||
CardContent
|
CardContent
|
||||||
} from "../ui/card";
|
} from "../ui/card";
|
||||||
import { Badge } from "../ui/badge";
|
import { Badge } from "../ui/badge";
|
||||||
import { X, Search, UserPlus, Users, PlusCircle, AlertCircle, Check } from "lucide-react";
|
import { X, Search, UserPlus, Users, PlusCircle, AlertCircle, Check, UploadCloud, File } from "lucide-react";
|
||||||
import { toast } from "../ui/use-toast";
|
import { toast } from "../ui/use-toast";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@ -65,6 +65,7 @@ export function MissionsAdminPanel() {
|
|||||||
const [activeTab, setActiveTab] = useState<string>("general");
|
const [activeTab, setActiveTab] = useState<string>("general");
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [selectedLogoFile, setSelectedLogoFile] = useState<File | null>(null);
|
const [selectedLogoFile, setSelectedLogoFile] = useState<File | null>(null);
|
||||||
|
const [selectedAttachments, setSelectedAttachments] = useState<File[]>([]);
|
||||||
const [missionData, setMissionData] = useState<{
|
const [missionData, setMissionData] = useState<{
|
||||||
name?: string;
|
name?: string;
|
||||||
logo?: string;
|
logo?: string;
|
||||||
@ -416,18 +417,23 @@ export function MissionsAdminPanel() {
|
|||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
// If we have a selected logo file and this is a new mission, upload it now
|
const newMissionId = data.mission?.id;
|
||||||
if (selectedLogoFile && data.mission && data.mission.id) {
|
if (!newMissionId) {
|
||||||
console.log('Uploading logo for new mission:', data.mission.id);
|
throw new Error('Failed to get new mission ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload logo if selected
|
||||||
|
if (selectedLogoFile) {
|
||||||
|
console.log('Uploading logo for new mission:', newMissionId);
|
||||||
|
|
||||||
const formData = new FormData();
|
const logoFormData = new FormData();
|
||||||
formData.append('file', selectedLogoFile);
|
logoFormData.append('file', selectedLogoFile);
|
||||||
formData.append('missionId', data.mission.id);
|
logoFormData.append('missionId', newMissionId);
|
||||||
formData.append('type', 'logo');
|
logoFormData.append('type', 'logo');
|
||||||
|
|
||||||
const logoResponse = await fetch('/api/missions/upload', {
|
const logoResponse = await fetch('/api/missions/upload', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: logoFormData
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!logoResponse.ok) {
|
if (!logoResponse.ok) {
|
||||||
@ -438,6 +444,42 @@ export function MissionsAdminPanel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload all attachments if there are any
|
||||||
|
if (selectedAttachments.length > 0) {
|
||||||
|
console.log(`Uploading ${selectedAttachments.length} attachments for new mission:`, newMissionId);
|
||||||
|
|
||||||
|
const uploadPromises = selectedAttachments.map(async (file) => {
|
||||||
|
const attachmentFormData = new FormData();
|
||||||
|
attachmentFormData.append('file', file);
|
||||||
|
attachmentFormData.append('missionId', newMissionId);
|
||||||
|
attachmentFormData.append('type', 'attachment');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const attachmentResponse = await fetch('/api/missions/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: attachmentFormData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!attachmentResponse.ok) {
|
||||||
|
console.error(`Failed to upload attachment ${file.name}:`, await attachmentResponse.json());
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
console.log(`Attachment ${file.name} uploaded successfully`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error uploading attachment ${file.name}:`, error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for all attachments to upload
|
||||||
|
const results = await Promise.allSettled(uploadPromises);
|
||||||
|
const successCount = results.filter(r => r.status === 'fulfilled' && r.value === true).length;
|
||||||
|
|
||||||
|
console.log(`Uploaded ${successCount} of ${selectedAttachments.length} attachments`);
|
||||||
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Mission créée avec succès",
|
title: "Mission créée avec succès",
|
||||||
description: "Tous les gardiens ont été assignés et la mission a été enregistrée.",
|
description: "Tous les gardiens ont été assignés et la mission a été enregistrée.",
|
||||||
@ -837,11 +879,71 @@ export function MissionsAdminPanel() {
|
|||||||
<TabsContent value="attachments" className="space-y-6">
|
<TabsContent value="attachments" className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium mb-1 text-gray-700">Attachements</label>
|
<label className="block text-sm font-medium mb-1 text-gray-700">Attachements</label>
|
||||||
<AttachmentsList
|
{/* For new missions */}
|
||||||
missionId={missionId || ""}
|
{!missionId ? (
|
||||||
allowUpload={true}
|
<div className="space-y-4">
|
||||||
allowDelete={true}
|
<div className="border rounded-md p-4 bg-white">
|
||||||
/>
|
<h4 className="text-sm font-medium mb-3 text-gray-700">Add Attachments</h4>
|
||||||
|
<p className="text-xs text-gray-500 mb-3">Attachments will be uploaded when you save the mission.</p>
|
||||||
|
|
||||||
|
{selectedAttachments.length > 0 && (
|
||||||
|
<div className="mb-4 border rounded-md p-3 bg-gray-50">
|
||||||
|
<h5 className="text-sm font-medium mb-2 text-gray-700">Selected Files ({selectedAttachments.length})</h5>
|
||||||
|
<ul className="divide-y divide-gray-200">
|
||||||
|
{selectedAttachments.map((file, index) => (
|
||||||
|
<li key={index} className="py-2 flex items-center justify-between">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<File className="h-4 w-4 text-gray-500 mr-2" />
|
||||||
|
<span className="text-sm text-gray-700">{file.name}</span>
|
||||||
|
<span className="text-xs text-gray-500 ml-2">({(file.size / 1024).toFixed(1)} KB)</span>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedAttachments(prev => prev.filter((_, i) => i !== index));
|
||||||
|
}}
|
||||||
|
className="text-red-500 hover:text-red-700 hover:bg-red-50 h-7 w-7 p-0"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex items-center justify-center w-full">
|
||||||
|
<label className="flex flex-col items-center justify-center w-full h-32 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100">
|
||||||
|
<div className="flex flex-col items-center justify-center pt-5 pb-6">
|
||||||
|
<UploadCloud className="w-8 h-8 mb-3 text-gray-400" />
|
||||||
|
<p className="mb-2 text-sm text-gray-500">
|
||||||
|
<span className="font-semibold">Click to upload</span> or drag and drop
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-gray-500">PDF, DOC, DOCX, XLS, XLSX, JPG, JPEG, PNG</p>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
className="hidden"
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.files && e.target.files.length > 0) {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
setSelectedAttachments(prev => [...prev, file]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
/* For existing missions */
|
||||||
|
<AttachmentsList
|
||||||
|
missionId={missionId || ""}
|
||||||
|
allowUpload={true}
|
||||||
|
allowDelete={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user