feat: uploading skeletons

This commit is contained in:
IlyaDoronin 2024-01-19 14:22:48 +03:00
parent 9b0454eab5
commit 95ae8c6a83
5 changed files with 277 additions and 180 deletions

@ -69,26 +69,24 @@ export default function OptionsAndPicture({
setPictureUploading(true); setPictureUploading(true);
try { const url = await uploadQuestionImage(
const url = await uploadQuestionImage( question.id,
question.id, quizQid,
quizQid, file,
file, (question, url) => {
(question, url) => { if (!("variants" in question.content)) return;
if (!("variants" in question.content)) return;
const variant = question.content.variants.find( const variant = question.content.variants.find(
(variant) => variant.id === selectedVariantId, (variant) => variant.id === selectedVariantId,
); );
if (!variant) return; if (!variant) return;
variant.extendedText = url; variant.extendedText = url;
variant.originalImageUrl = url; variant.originalImageUrl = url;
}, },
); );
closeImageUploadModal(); closeImageUploadModal();
openCropModal(file, url); openCropModal(file, url);
} catch {}
setPictureUploading(false); setPictureUploading(false);
}; };

@ -63,27 +63,25 @@ export default function OptionsPicture({
setPictureUploading(true); setPictureUploading(true);
try { const url = await uploadQuestionImage(
const url = await uploadQuestionImage( question.id,
question.id, quizQid,
quizQid, file,
file, (question, url) => {
(question, url) => { if (!("variants" in question.content)) return;
if (!("variants" in question.content)) return;
const variant = question.content.variants.find( const variant = question.content.variants.find(
(variant) => variant.id === selectedVariantId, (variant) => variant.id === selectedVariantId,
); );
if (!variant) return; if (!variant) return;
variant.extendedText = url; variant.extendedText = url;
variant.originalImageUrl = url; variant.originalImageUrl = url;
}, },
); );
closeImageUploadModal(); closeImageUploadModal();
openCropModal(file, url); openCropModal(file, url);
} catch {}
setPictureUploading(false); setPictureUploading(false);
}; };

@ -1,5 +1,6 @@
import { useState } from "react";
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { Box, ButtonBase, Typography, useTheme } from "@mui/material"; import { Box, Skeleton, Typography, useTheme } from "@mui/material";
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions"; import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
import { useCurrentQuiz } from "@root/quizes/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks";
import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal"; import { CropModal, useCropModalState } from "@ui_kit/Modal/CropModal";
@ -12,6 +13,7 @@ type UploadImageProps = {
}; };
export default function UploadImage({ question }: UploadImageProps) { export default function UploadImage({ question }: UploadImageProps) {
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
const theme = useTheme(); const theme = useTheme();
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
@ -29,29 +31,50 @@ export default function UploadImage({ question }: UploadImageProps) {
> >
Загрузить изображение Загрузить изображение
</Typography> </Typography>
<DropZone {pictureUploding ? (
text={"5 MB максимум"} <Skeleton variant="rounded" sx={{ height: "120px", width: "300px" }} />
heightImg={"110px"} ) : (
sx={{ maxWidth: "300px", width: "100%" }} <DropZone
imageUrl={question.content.back} text={"5 MB максимум"}
originalImageUrl={question.content.originalBack} sx={{ maxWidth: "300px", width: "100%" }}
onImageUploadClick={(file) => { imageUrl={question.content.back}
uploadQuestionImage(question.id, quiz.qid, file, (question, url) => { originalImageUrl={question.content.originalBack}
question.content.back = url; onImageUploadClick={async (file) => {
question.content.originalBack = url; setPictureUploading(true);
});
}} await uploadQuestionImage(
onDeleteClick={() => { question.id,
updateQuestion(question.id, (question) => { quiz.qid,
question.content.back = null; file,
}); (question, url) => {
}} question.content.back = url;
onImageSaveClick={(file) => { question.content.originalBack = url;
uploadQuestionImage(question.id, quiz.qid, file, (question, url) => { },
question.content.back = url; );
});
}} setPictureUploading(false);
/> }}
onDeleteClick={() => {
updateQuestion(question.id, (question) => {
question.content.back = null;
});
}}
onImageSaveClick={async (file) => {
setPictureUploading(true);
await uploadQuestionImage(
question.id,
quiz.qid,
file,
(question, url) => {
question.content.back = url;
},
);
setPictureUploading(false);
}}
/>
)}
</Box> </Box>
); );
} }

@ -25,6 +25,7 @@ import {
Select, Select,
Tooltip, Tooltip,
Typography, Typography,
Skeleton,
useMediaQuery, useMediaQuery,
useTheme, useTheme,
} from "@mui/material"; } from "@mui/material";
@ -75,6 +76,9 @@ export default function StartPageSettings() {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const [formState, setFormState] = useState<"design" | "content">("design"); const [formState, setFormState] = useState<"design" | "content">("design");
const [mobileVersion, setMobileVersion] = useState(false); const [mobileVersion, setMobileVersion] = useState(false);
const [faviconUploding, setFaviconUploading] = useState<boolean>(false);
const [backgroundUploding, setBackgroundUploading] = useState<boolean>(false);
const [logoUploding, setLogoUploading] = useState<boolean>(false);
if (!quiz) return null; if (!quiz) return null;
@ -84,14 +88,20 @@ export default function StartPageSettings() {
const designType = quiz?.config?.startpageType; const designType = quiz?.config?.startpageType;
const favIconDropZoneElement = ( const favIconDropZoneElement = faviconUploding ? (
<Skeleton sx={{ width: "48px", height: "48px", transform: "none" }} />
) : (
<FaviconDropZone <FaviconDropZone
imageUrl={quiz.config.startpage.favIcon} imageUrl={quiz.config.startpage.favIcon}
onImageUploadClick={async (file) => { onImageUploadClick={async (file) => {
setFaviconUploading(true);
const resizedImage = await resizeFavIcon(file); const resizedImage = await resizeFavIcon(file);
uploadQuizImage(quiz.id, resizedImage, (quiz, url) => {
await uploadQuizImage(quiz.id, resizedImage, (quiz, url) => {
quiz.config.startpage.favIcon = url; quiz.config.startpage.favIcon = url;
}); });
setFaviconUploading(false);
}} }}
onDeleteClick={() => { onDeleteClick={() => {
updateQuiz(quiz.id, (quiz) => { updateQuiz(quiz.id, (quiz) => {
@ -330,30 +340,47 @@ export default function StartPageSettings() {
> >
Изображение Изображение
</Typography> </Typography>
<DropZone {backgroundUploding ? (
value={"5 MB максимум"} <Skeleton
sx={{ maxWidth: "300px" }} sx={{
imageUrl={quiz.config.startpage.background.desktop} width: "300px",
originalImageUrl={ height: "120px",
quiz.config.startpage.background.originalDesktop transform: "none",
} }}
onImageUploadClick={(file) => { />
uploadQuizImage(quiz.id, file, (quiz, url) => { ) : (
quiz.config.startpage.background.desktop = url; <DropZone
quiz.config.startpage.background.originalDesktop = url; text={"5 MB максимум"}
}); sx={{ maxWidth: "300px" }}
}} imageUrl={quiz.config.startpage.background.desktop}
onImageSaveClick={(file) => { originalImageUrl={
uploadQuizImage(quiz.id, file, (quiz, url) => { quiz.config.startpage.background.originalDesktop
quiz.config.startpage.background.desktop = url; }
}); onImageUploadClick={async (file) => {
}} setBackgroundUploading(true);
onDeleteClick={() => { await uploadQuizImage(quiz.id, file, (quiz, url) => {
updateQuiz(quiz.id, (quiz) => { quiz.config.startpage.background.desktop = url;
quiz.config.startpage.background.desktop = null; quiz.config.startpage.background.originalDesktop =
}); url;
}} });
/>
setBackgroundUploading(false);
}}
onImageSaveClick={async (file) => {
setBackgroundUploading(true);
await uploadQuizImage(quiz.id, file, (quiz, url) => {
quiz.config.startpage.background.desktop = url;
});
setBackgroundUploading(false);
}}
onDeleteClick={() => {
updateQuiz(quiz.id, (quiz) => {
quiz.config.startpage.background.desktop = null;
});
}}
/>
)}
</Box> </Box>
<ModalSizeImage /> <ModalSizeImage />
@ -386,47 +413,68 @@ export default function StartPageSettings() {
</Tooltip> </Tooltip>
)} )}
</Box> </Box>
<ButtonBase {backgroundUploding ? (
component="label" <Skeleton
sx={{
justifyContent: "center",
height: "48px",
width: "48px",
display: "flex",
alignItems: "center",
my: "20px",
}}
>
<input
onChange={(event) => {
const file = event.target.files?.[0];
if (file) {
uploadQuizImage(quiz.id, file, (quiz, url) => {
quiz.config.startpage.background.video = url;
});
// setVideo(URL.createObjectURL(file));
}
}}
hidden
accept=".mp4"
multiple
type="file"
/>
<UploadBox
icon={<UploadIcon />}
sx={{ sx={{
height: "48px",
width: "48px", width: "48px",
height: "48px",
transform: "none",
margin: "20px 0",
}} }}
/> />
</ButtonBase> ) : (
{quiz.config.startpage.background.video ? ( <>
<video <ButtonBase
src={quiz.config.startpage.background.video} component="label"
width="400" sx={{
controls justifyContent: "center",
/> height: "48px",
) : null} width: "48px",
display: "flex",
alignItems: "center",
my: "20px",
}}
>
<input
onChange={async (event) => {
setBackgroundUploading(true);
const file = event.target.files?.[0];
if (file) {
await uploadQuizImage(
quiz.id,
file,
(quiz, url) => {
quiz.config.startpage.background.video = url;
},
);
// setVideo(URL.createObjectURL(file));
}
setBackgroundUploading(false);
}}
hidden
accept=".mp4"
multiple
type="file"
/>
<UploadBox
icon={<UploadIcon />}
sx={{
height: "48px",
width: "48px",
}}
/>
</ButtonBase>
{quiz.config.startpage.background.video && (
<video
src={quiz.config.startpage.background.video}
width="400"
controls
/>
)}
</>
)}
</> </>
)} )}
{designType !== "centered" && ( {designType !== "centered" && (
@ -500,28 +548,44 @@ export default function StartPageSettings() {
> >
Логотип Логотип
</Typography> </Typography>
<DropZone {logoUploding ? (
value={"5 MB максимум"} <Skeleton
sx={{ maxWidth: "300px" }} sx={{
imageUrl={quiz.config.startpage.logo} width: "300px",
originalImageUrl={quiz.config.startpage.originalLogo} height: "120px",
onImageUploadClick={(file) => { transform: "none",
uploadQuizImage(quiz.id, file, (quiz, url) => { }}
quiz.config.startpage.logo = url; />
quiz.config.startpage.originalLogo = url; ) : (
}); <DropZone
}} text={"5 MB максимум"}
onImageSaveClick={(file) => { sx={{ maxWidth: "300px" }}
uploadQuizImage(quiz.id, file, (quiz, url) => { imageUrl={quiz.config.startpage.logo}
quiz.config.startpage.logo = url; originalImageUrl={quiz.config.startpage.originalLogo}
}); onImageUploadClick={async (file) => {
}} setLogoUploading(true);
onDeleteClick={() => { await uploadQuizImage(quiz.id, file, (quiz, url) => {
updateQuiz(quiz.id, (quiz) => { quiz.config.startpage.logo = url;
quiz.config.startpage.logo = null; quiz.config.startpage.originalLogo = url;
}); });
}}
/> setLogoUploading(false);
}}
onImageSaveClick={async (file) => {
setLogoUploading(true);
await uploadQuizImage(quiz.id, file, (quiz, url) => {
quiz.config.startpage.logo = url;
});
setLogoUploading(false);
}}
onDeleteClick={() => {
updateQuiz(quiz.id, (quiz) => {
quiz.config.startpage.logo = null;
});
}}
/>
)}
</Box> </Box>
<Typography <Typography
@ -567,28 +631,44 @@ export default function StartPageSettings() {
> >
Логотип Логотип
</Typography> </Typography>
<DropZone {logoUploding ? (
value={"5 MB максимум"} <Skeleton
sx={{ maxWidth: "300px" }} sx={{
imageUrl={quiz.config.startpage.logo} width: "300px",
originalImageUrl={quiz.config.startpage.originalLogo} height: "120px",
onImageUploadClick={(file) => { transform: "none",
uploadQuizImage(quiz.id, file, (quiz, url) => { }}
quiz.config.startpage.logo = url; />
quiz.config.startpage.originalLogo = url; ) : (
}); <DropZone
}} text={"5 MB максимум"}
onImageSaveClick={(file) => { sx={{ maxWidth: "300px" }}
uploadQuizImage(quiz.id, file, (quiz, url) => { imageUrl={quiz.config.startpage.logo}
quiz.config.startpage.logo = url; originalImageUrl={quiz.config.startpage.originalLogo}
}); onImageUploadClick={async (file) => {
}} setLogoUploading(true);
onDeleteClick={() => { await uploadQuizImage(quiz.id, file, (quiz, url) => {
updateQuiz(quiz.id, (quiz) => { quiz.config.startpage.logo = url;
quiz.config.startpage.logo = null; quiz.config.startpage.originalLogo = url;
}); });
}}
/> setLogoUploading(false);
}}
onImageSaveClick={async (file) => {
setLogoUploading(true);
await uploadQuizImage(quiz.id, file, (quiz, url) => {
quiz.config.startpage.logo = url;
});
setLogoUploading(false);
}}
onDeleteClick={() => {
updateQuiz(quiz.id, (quiz) => {
quiz.config.startpage.logo = null;
});
}}
/>
)}
</Box> </Box>
<Typography <Typography

@ -41,19 +41,17 @@ export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
async function handleImageUpload(file: File) { async function handleImageUpload(file: File) {
setPictureUploading(true); setPictureUploading(true);
try { const url = await uploadQuestionImage(
const url = await uploadQuestionImage( resultData.id,
resultData.id, quizQid,
quizQid, file,
file, (question, url) => {
(question, url) => { question.content.back = url;
question.content.back = url; question.content.originalBack = url;
question.content.originalBack = url; },
}, );
); closeImageUploadModal();
closeImageUploadModal(); openCropModal(file, url);
openCropModal(file, url);
} catch {}
setPictureUploading(false); setPictureUploading(false);
} }