Commit b9828c34 by Arjun Jhukal

updated the fixes to file upload ui and game updated

parent 86252171
......@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev -p 3000",
"build": "next build",
"start": "next start",
"lint": "eslint"
......@@ -35,4 +35,4 @@
"tailwindcss": "^4",
"typescript": "^5"
}
}
}
\ No newline at end of file
......@@ -16,6 +16,7 @@ interface InputFileProps {
touched?: boolean;
multiple?: boolean;
serverFile?: string | string[] | null
onRemoveServerFile?: (fileUrl?: string) => void;
}
export default function InputFile({
......@@ -29,7 +30,8 @@ export default function InputFile({
error,
touched,
multiple = false,
serverFile
serverFile,
onRemoveServerFile
}: InputFileProps) {
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files;
......@@ -59,9 +61,12 @@ export default function InputFile({
Choose File
</span>
<span className="truncate text-gray-500">
{Array.isArray(value)
{/* {Array.isArray(value)
? value.map((f) => f.name).join(", ") || "No file chosen"
: value?.name || "No file chosen"}
: value?.name || "No file chosen"} */}
{
Array.isArray(value) && value.length || value ? "Update File" : "No file chosen"
}
</span>
<input
type="file"
......@@ -69,34 +74,101 @@ export default function InputFile({
accept={accept}
hidden
multiple={multiple}
onChange={handleFileChange}
onChange={(e) => {
handleFileChange(e)
e.target.value = '';
}}
onBlur={onBlur}
/>
</label>
{Array.isArray(value) && value.length > 0 && (
<div className="flex gap-3 flex-wrap mt-2">
{value.map((f) => (
<div
key={f.name}
className="flex items-center gap-2 rounded-[20px] py-[2px] px-3 bg-primary-light text-white"
>
<Tooltip title={f.name}>
<span className="text-[12px]">
{f?.name.length > 5
? f.name.slice(0, 5) + "..."
: f.name}
</span>
</Tooltip>
<CloseCircle
size={14}
className="cursor-pointer hover:text-red-500"
onClick={() => handleRemoveFile(f)}
/>
</div>
))}
</div>
)}
{
<div className="flex gap-3 flex-wrap mt-2">
{value && (
<>
{Array.isArray(value) ? (
value.map((f) => (
<div
key={f.name}
className="relative w-[80px] h-[80px] rounded-lg overflow-hidden border border-gray-200"
>
{f instanceof File && (
<img
src={URL.createObjectURL(f)}
alt={f.name}
className="w-full h-full object-cover"
/>
)}
<CloseCircle
size={16}
className="absolute top-1 right-1 cursor-pointer text-white hover:text-red-500"
onClick={() => handleRemoveFile(f)}
/>
</div>
))
) : (
value instanceof File && (
<div
key={value.name}
className="relative w-[80px] h-[80px] rounded-lg overflow-hidden border border-gray-200"
>
<img
src={URL.createObjectURL(value)}
alt={value.name}
className="w-full h-full object-cover"
/>
<CloseCircle
size={16}
className="absolute top-1 right-1 cursor-pointer text-white hover:text-red-500"
onClick={() => onChange(null)}
/>
</div>
)
)}
</>
)}
{serverFile && (
<>
{Array.isArray(serverFile) ? (
serverFile.map((f) => (
<div
key={f}
className="relative w-[80px] h-[80px] rounded-lg overflow-hidden border border-gray-200"
>
<img
src={f}
alt={f}
className="w-full h-full object-cover"
/>
<CloseCircle
size={16}
className="absolute top-1 right-1 cursor-pointer text-white hover:text-red-500"
onClick={() => onRemoveServerFile && onRemoveServerFile(f)}
/>
</div>
))
) : (
<div
key={serverFile}
className="relative w-[80px] h-[80px] rounded-lg overflow-hidden border border-gray-200"
>
<img
src={serverFile}
alt={serverFile}
className="w-full h-full object-cover"
/>
<CloseCircle
size={16}
className="absolute top-1 right-1 cursor-pointer text-white hover:text-red-500"
onClick={() => onRemoveServerFile && onRemoveServerFile(serverFile)}
/>
</div>
)}
</>
)}
</div>
{/* {
Array.isArray(serverFile) && serverFile.length > 0 ? (
serverFile.map((f) => (
<div
......@@ -110,11 +182,7 @@ export default function InputFile({
: f}
</span>
</Tooltip>
{/* <CloseCircle
size={14}
className="cursor-pointer hover:text-red-500"
onClick={() => handleRemoveFile(f)}
/> */}
</div>
))
) : (<span className="text-[12px]">
......@@ -122,7 +190,7 @@ export default function InputFile({
? serverFile?.slice(0, 5) + "..."
: serverFile}
</span>)
}
} */}
{touched && error && (
<span className="text-red-500 text-xs mt-1">{error}</span>
......
......@@ -11,6 +11,7 @@ import { gameInitialValues, GameProps } from "@/types/game";
import { Button, InputLabel, Input, OutlinedInput } from "@mui/material";
import { useFormik } from "formik";
import { useRouter } from "next/navigation";
import React from "react";
import * as Yup from "yup";
interface AddGameFormProps {
......@@ -33,6 +34,26 @@ export default function AddGameForm({ id }: AddGameFormProps) {
const [addGame, { isLoading: addingGame }] = useAddGameMutation();
const { data, isLoading: loadingGameData } = useGetGameByIdQuery({ id: Number(id) }, { skip: !id })
const [updateGame, { isLoading: editing }] = useUpdateGameByIdMutation();
const [serverFiles, setServerFiles] = React.useState<{
thumbnail: string | null;
screenshots: string[];
subgames: string[];
}>({
thumbnail: data?.data.thumbnail || null,
screenshots: data?.data.screenshots || [],
subgames: data?.data.subgames || [],
});
React.useEffect(() => {
setServerFiles({
screenshots: data?.data?.screenshots || [],
subgames: data?.data?.subgames || [],
thumbnail: data?.data?.thumbnail || "",
})
}, [data])
const formik = useFormik<GameProps>({
initialValues: data ? {
name: data.data?.name,
......@@ -74,15 +95,15 @@ export default function AddGameForm({ id }: AddGameFormProps) {
}
if (id) {
if (data?.data.subgames && Array.isArray(data?.data.subgames)) {
data?.data.subgames.forEach((file, index) => {
if (serverFiles.subgames && Array.isArray(serverFiles.subgames)) {
serverFiles.subgames.forEach((file, index) => {
formData.append(`subgames_files[${index}]`, file);
});
}
}
if (id) {
if (data?.data.screenshots && Array.isArray(data?.data.screenshots)) {
data?.data.screenshots.forEach((file, index) => {
if (serverFiles.screenshots && Array.isArray(serverFiles.screenshots)) {
serverFiles.screenshots.forEach((file, index) => {
formData.append(`screenshots_files[${index}]`, file);
});
}
......@@ -96,6 +117,7 @@ export default function AddGameForm({ id }: AddGameFormProps) {
variant: ToastVariant.SUCCESS
})
)
router.push(PATH.ADMIN.GAMES.ROOT)
}
else {
try {
......@@ -121,6 +143,18 @@ export default function AddGameForm({ id }: AddGameFormProps) {
},
});
const handleServerFileRemoval = (field: "screenshots" | "subgames" | "thumbnail", fileUrl?: string) => {
if (field === "thumbnail") {
setServerFiles((prev) => ({ ...prev, thumbnail: null }));
} else {
setServerFiles((prev) => ({
...prev,
[field]: prev[field].filter((f: string) => f !== fileUrl),
}));
}
};
return (
<form onSubmit={formik.handleSubmit}>
<div className="form__field__wrapper border-solid border-[1px] border-gray rounded-[16px] mb-6">
......@@ -154,7 +188,8 @@ export default function AddGameForm({ id }: AddGameFormProps) {
value={formik.values.thumbnail || null}
onChange={(file: File | File[] | null) => formik.setFieldValue("thumbnail", file)}
onBlur={() => formik.setFieldTouched("thumbnail", true)}
serverFile={data?.data?.thumbnail}
serverFile={serverFiles.thumbnail}
onRemoveServerFile={() => handleServerFileRemoval("thumbnail")}
/>
<span className="error">
{formik.touched.thumbnail && formik.errors.thumbnail ? formik.errors.thumbnail : ""}
......@@ -212,7 +247,8 @@ export default function AddGameForm({ id }: AddGameFormProps) {
}
}
onBlur={() => formik.setFieldTouched("screenshots", true)}
serverFile={data?.data?.screenshots}
serverFile={serverFiles.screenshots}
onRemoveServerFile={(fileUrl) => handleServerFileRemoval("screenshots", fileUrl)}
/>
</div>
......@@ -234,7 +270,8 @@ export default function AddGameForm({ id }: AddGameFormProps) {
}
}
onBlur={() => formik.setFieldTouched("subgames", true)}
serverFile={data?.data?.subgames}
serverFile={serverFiles.subgames}
onRemoveServerFile={(fileUrl) => handleServerFileRemoval("subgames", fileUrl)}
/>
</div>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment