Skip to content

Commit

Permalink
FEAT: Add Loading UI
Browse files Browse the repository at this point in the history
  • Loading branch information
thinley4 committed Nov 1, 2024
1 parent 276025b commit c123c8c
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 74 deletions.
1 change: 1 addition & 0 deletions web/package-lock.json

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

1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-toast": "^1.2.2",
"@radix-ui/themes": "^3.1.4",
Expand Down
214 changes: 142 additions & 72 deletions web/src/app/components/DragDrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import { useState } from "react";
import { upload } from "../../../actions/user";
import { useRouter } from "next/navigation";
import { CloudUpload, Loader2 } from "lucide-react";
import { CloudUpload } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { LoadingUI } from "./LoadingUI";


export const DragDrop = () => {
const [file, setFile] = useState<File | null>(null);
Expand All @@ -11,7 +14,6 @@ export const DragDrop = () => {
const router = useRouter();

const handleUpload = async (e: { preventDefault: () => void }) => {

if (localStorage.getItem("apikey") == null) {
alert("Submit API Key");
} else {
Expand Down Expand Up @@ -55,85 +57,153 @@ export const DragDrop = () => {
}
};

// Set API Key

const [apikey, setApiKey] = useState(null as string | null);
const { toast } = useToast();

function onSubmit() {
toast({
title: "API Key Set",
});
if (apikey) {
localStorage.setItem("apikey", apikey);
}
}
function removeKey() {
setApiKey(null);
localStorage.removeItem("apikey");
router.refresh();
}

return (
<div className="container px-4 max-w-5xl mx-auto">
{!file ? (
<div
onDragOver={(e) => {
e.preventDefault();
setFileEnter(true); // Set fileEnter to true when dragging over the area
}}
onDragLeave={() => {
setFileEnter(false); // Reset fileEnter when dragging leaves the area
}}
onDrop={(e) => {
e.preventDefault();
setFileEnter(false); // Reset fileEnter after dropping
const files = e.dataTransfer.files;
if (files.length > 0) {
setFile(files[0]); // Set the file
}
}}
className={`${
fileEnter ? "border-2 border-dashed" : "bg-[#1C1A35]"
} mx-auto flex flex-col w-full max-w-xs h-72 items-center justify-center`}
>
<div className="h-full flex flex-col gap-4 justify-center text-center text-white">
<div className="flex justify-center">
<CloudUpload className="h-24 w-28" />
</div>
<div>Drag & Drop to Upload File</div>
<div>OR</div>
<label htmlFor="file">
<div className="cursor-pointer text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-100 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700">
Select File
</div>
</label>
</div>
<input
id="file"
type="file"
className="hidden"
onChange={(e) => {
const files = e.target.files;
if (files && files[0]) {
setFile(files[0]);
<div>
<div className="container px-4 max-w-5xl mx-auto">
{!file ? (
<div
onDragOver={(e) => {
e.preventDefault();
setFileEnter(true); // Set fileEnter to true when dragging over the area
}}
onDragLeave={() => {
setFileEnter(false); // Reset fileEnter when dragging leaves the area
}}
onDrop={(e) => {
e.preventDefault();
setFileEnter(false); // Reset fileEnter after dropping
const files = e.dataTransfer.files;
if (files.length > 0) {
setFile(files[0]); // Set the file
}
}}
/>
</div>
) : (
<div className="flex flex-col items-center">
{loading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<div className="border border-gray-700 bg-[#0E0A24] rounded-lg shadow-xl p-8 flex flex-col items-center space-y-6 max-w-md mx-auto">
<h2 className="text-2xl font-bold text-white mb-4">
Upload Your File
</h2>
className={`${
fileEnter ? "border-2 border-dashed" : "bg-[#1C1A35]"
} mx-auto flex flex-col w-full max-w-xs h-72 items-center justify-center`}
>
<div className="h-full flex flex-col gap-4 justify-center text-center text-white">
<div className="flex justify-center">
<CloudUpload className="h-24 w-28" />
</div>
<div>Drag & Drop to Upload File</div>
<div>OR</div>
<label htmlFor="file">
<div className="cursor-pointer text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-100 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700">
Select File
</div>
</label>
</div>
<input
id="file"
type="file"
className="hidden"
onChange={(e) => {
const files = e.target.files;
if (files && files[0]) {
setFile(files[0]);
}
}}
/>
</div>
) : (
<div>
{loading ? (
<div className="flex h-96 items-center justify-center">
<LoadingUI />
</div>
) : (
<div className="border border-gray-700 bg-[#0E0A24] rounded-lg shadow-xl p-8 flex flex-col items-center space-y-6 max-w-md mx-auto">
<h2 className="text-2xl font-bold text-white mb-4">
Upload Your File
</h2>

<p className="text-gray-400 text-sm mb-6 text-center">
Only PDF files are allowed. Make sure your file size is below
1MB.
</p>
<p className="text-gray-400 text-sm mb-6 text-center">
Only PDF files are allowed. Make sure your file size is below
1MB.
</p>

<button
onClick={handleUpload}
className="w-full bg-gradient-to-r from-[#6D28D9] to-[#4F46E5] hover:from-[#5B21B6] hover:to-[#4338CA] text-white font-semibold py-3 px-6 rounded-lg shadow-md transform hover:scale-105 transition-transform duration-300 ease-in-out"
>
Submit
</button>
<button
onClick={handleUpload}
className="w-full bg-gradient-to-r from-[#6D28D9] to-[#4F46E5] hover:from-[#5B21B6] hover:to-[#4338CA] text-white font-semibold py-3 px-6 rounded-lg shadow-md transform hover:scale-105 transition-transform duration-300 ease-in-out"
>
Submit
</button>

<button
onClick={() => setFile(null)}
className="w-full bg-gradient-to-r from-gray-600 to-gray-500 hover:from-gray-500 hover:to-gray-400 text-white font-semibold py-3 px-6 rounded-lg shadow-md transform hover:scale-105 transition-transform duration-300 ease-in-out"
<button
onClick={() => setFile(null)}
className="w-full bg-gradient-to-r from-gray-600 to-gray-500 hover:from-gray-500 hover:to-gray-400 text-white font-semibold py-3 px-6 rounded-lg shadow-md transform hover:scale-105 transition-transform duration-300 ease-in-out"
>
Reset
</button>
</div>
)}
</div>
)}
</div>

{/* Set API Key */}
<div className="flex justify-center pt-5">
<div className="flex flex-col gap-2">
{!localStorage.getItem("apikey") ? (
<>
<div className="text-red-500">
*Get your API Key from Mistral AI
</div>
<form
className="flex flex-col justify-center gap-2 md:flex"
onSubmit={onSubmit}
>
Reset
</button>
</div>
<input
onChange={(e) => {
setApiKey(e.target.value);
}}
type="text"
id="first_name"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-72 p-2.5 "
placeholder="Mistral API Key"
required
/>
<button className="bg-[#1C1A35] p-2 text-white" type="submit">
Submit
</button>
</form>
</>
) : (
<>
{loading ? (
<></>
) : (
<button
onClick={removeKey}
className="bg-[#1C1A35] p-2 text-white"
type="submit"
>
Reset API Key
</button>
)}
</>
)}
</div>
)}
</div>
</div>
);
};
20 changes: 20 additions & 0 deletions web/src/app/components/LoadingUI.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use client"

import * as React from "react"

import { Progress } from "@/components/ui/progress"

export function LoadingUI() {
const [progress, setProgress] = React.useState(5)

React.useEffect(() => {
const timers = [
setTimeout(() => setProgress(33), 500),
setTimeout(() => setProgress(66), 1500),
setTimeout(() => setProgress(85), 2000),
]
return () => timers.forEach(timer => clearTimeout(timer))
}, [])

return <Progress value={progress} className="w-[60%]" />
}
4 changes: 2 additions & 2 deletions web/src/app/upload/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import logo from "../../../public/logo.png"
import { auth } from "../../../auth";
import { redirect } from "next/navigation";
import { DragDrop } from "../components/DragDrop";
import SetApi from "../components/SetApi";
// import SetApi from "../components/SetApi";
import { Sidebar } from "./Components/Sidebar";

export default async function Page() {
Expand All @@ -25,7 +25,7 @@ export default async function Page() {
<ProfileDropdown />
</div>
<DragDrop />
<SetApi />
{/* <SetApi /> */}
</div>
)
}
28 changes: 28 additions & 0 deletions web/src/components/ui/progress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client"

import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress"

import { cn } from "@/lib/utils"

const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-[#1C1A35]",
className
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-white transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
))
Progress.displayName = ProgressPrimitive.Root.displayName

export { Progress }

0 comments on commit c123c8c

Please sign in to comment.