Skip to content

Commit

Permalink
add upload button
Browse files Browse the repository at this point in the history
upload csv data and parse for sample and plans params
  • Loading branch information
matyson committed Oct 14, 2024
1 parent d4a361a commit 34b4228
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
2 changes: 2 additions & 0 deletions apps/spu-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"lucide-react": "^0.396.0",
"next": "^14.2.3",
"next-auth": "5.0.0-beta.22",
"papaparse": "^5.4.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.0",
Expand All @@ -39,6 +40,7 @@
"@sophys-web/tailwind-config": "workspace:*",
"@sophys-web/typescript-config": "workspace:*",
"@types/node": "^20.11.24",
"@types/papaparse": "^5.3.14",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.18",
Expand Down
73 changes: 73 additions & 0 deletions apps/spu-ui/src/app/_components/upload-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"use client";

import { useRef } from "react";
import { parse } from "papaparse";
import { cn } from "@sophys-web/ui";
import { buttonVariants } from "@sophys-web/ui/button";
import { Input } from "@sophys-web/ui/input";
import { Label } from "@sophys-web/ui/label";
import { toast } from "@sophys-web/ui/sonner";
import type { SampleParams } from "../../lib/schemas/sample";
import { samplesSchema } from "../../lib/schemas/sample";

interface ButtonProps {
children: React.ReactNode;
handleUpload: (data: SampleParams[]) => void;
}

export function UploadButton(props: ButtonProps) {
const inputRef = useRef<HTMLInputElement>(null);
return (
<div className="flex flex-col items-center gap-8">
<Label
className={cn(
buttonVariants({ variant: "link" }),
"flex cursor-pointer items-center",
)}
htmlFor="upload-button"
>
{props.children}
</Label>
<Input
accept=".csv"
className="sr-only"
id="upload-button"
onChange={(e) => {
toast.info("Parsing CSV file...");
const files = e.target.files;
if (!files) return;
const file = files[0];
parse(file, {
header: true,
skipEmptyLines: true,
complete: async (results) => {
const { data: csvData, errors } = results;
if (errors.length > 0) {
toast.error("Error parsing CSV file", {
description: errors.map((error) => error.message).join("\n"),
});
return;
}
const parsedData = await samplesSchema.safeParseAsync(csvData);
if (!parsedData.success) {
toast.error("Error parsing CSV file", {
description: parsedData.error.errors
.map((err) => err.message)
.join("\n"),
});
return;
}
toast.success("CSV file parsed successfully");
props.handleUpload(parsedData.data);
},
});
if (inputRef.current) {
inputRef.current.value = "";
}
}}
ref={inputRef}
type="file"
/>
</div>
);
}
21 changes: 21 additions & 0 deletions apps/spu-ui/src/lib/schemas/sample.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { z } from "zod";

export const sampleSchema = z.object({
name: z.string(),
order: z.coerce.number(),
buffer: z.string(),
time: z.coerce.number(),
frames: z.coerce.number(),
volume: z.coerce.number(),
speed: z.coerce.number(),
position: z.string(),
energy: z.coerce.number(),
distance: z.coerce.number(),
detX: z.coerce.number(),
detY: z.coerce.number(),
comments: z.string(),
});

export const samplesSchema = z.array(sampleSchema);

export type SampleParams = z.infer<typeof sampleSchema>;
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 34b4228

Please sign in to comment.