feat: import FreePro accepte .xls, .xlsx et .csv
This commit is contained in:
@@ -226,8 +226,8 @@ function VentilationFreeProContent() {
|
|||||||
// Gestion du fichier
|
// Gestion du fichier
|
||||||
const handleFile = useCallback(
|
const handleFile = useCallback(
|
||||||
(file: File) => {
|
(file: File) => {
|
||||||
if (!file.name.match(/\.(xlsx|xls)$/i)) {
|
if (!file.name.match(/\.(xlsx|xls|csv)$/i)) {
|
||||||
toast.error("Format invalide : veuillez sélectionner un fichier Excel (.xlsx ou .xls)");
|
toast.error("Format invalide : veuillez sélectionner un fichier Excel (.xlsx, .xls) ou CSV (.csv)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
@@ -305,7 +305,7 @@ function VentilationFreeProContent() {
|
|||||||
<input
|
<input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
type="file"
|
type="file"
|
||||||
accept=".xlsx,.xls"
|
accept=".xlsx,.xls,.csv"
|
||||||
className="hidden"
|
className="hidden"
|
||||||
onChange={(e) => { const f = e.target.files?.[0]; if (f) handleFile(f); }}
|
onChange={(e) => { const f = e.target.files?.[0]; if (f) handleFile(f); }}
|
||||||
/>
|
/>
|
||||||
@@ -320,7 +320,7 @@ function VentilationFreeProContent() {
|
|||||||
<p className="text-sm font-medium text-foreground">
|
<p className="text-sm font-medium text-foreground">
|
||||||
Glissez-déposez le fichier Excel FreePro ici
|
Glissez-déposez le fichier Excel FreePro ici
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-muted-foreground">ou cliquez pour sélectionner (.xlsx, .xls)</p>
|
<p className="text-xs text-muted-foreground">ou cliquez pour sélectionner (.xlsx, .xls, .csv)</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -77,9 +77,16 @@ function getType(labelClient: string, script: string): string {
|
|||||||
*/
|
*/
|
||||||
export function processFreeproExcel(
|
export function processFreeproExcel(
|
||||||
buffer: Buffer,
|
buffer: Buffer,
|
||||||
moisLabel: string
|
moisLabel: string,
|
||||||
|
fileName?: string
|
||||||
): FreeproVentilationResult {
|
): FreeproVentilationResult {
|
||||||
const wb = xlsx.read(buffer, { type: "buffer", cellDates: true });
|
// Détecter si c'est un CSV (par extension ou par détection du contenu)
|
||||||
|
const isCsv = fileName
|
||||||
|
? /\.csv$/i.test(fileName)
|
||||||
|
: !buffer[0] || (buffer[0] !== 0x50 && buffer[0] !== 0xD0); // PK = xlsx, D0CF = xls
|
||||||
|
const wb = isCsv
|
||||||
|
? xlsx.read(buffer.toString("utf8"), { type: "string", cellDates: true })
|
||||||
|
: xlsx.read(buffer, { type: "buffer", cellDates: true });
|
||||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||||
const rawRows = xlsx.utils.sheet_to_json<Record<string, unknown>>(ws, {
|
const rawRows = xlsx.utils.sheet_to_json<Record<string, unknown>>(ws, {
|
||||||
header: [
|
header: [
|
||||||
|
|||||||
@@ -2218,7 +2218,7 @@ export const appRouter = router({
|
|||||||
)
|
)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const buffer = Buffer.from(input.fileBase64, "base64");
|
const buffer = Buffer.from(input.fileBase64, "base64");
|
||||||
const result = processFreeproExcel(buffer, input.moisLabel);
|
const result = processFreeproExcel(buffer, input.moisLabel, input.fileName);
|
||||||
|
|
||||||
const importId = await createFreeproImport(
|
const importId = await createFreeproImport(
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user