Commit b9828c34 by Arjun Jhukal

updated the fixes to file upload ui and game updated

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