feat: AddOrEditImageButton skeleton

This commit is contained in:
IlyaDoronin 2024-01-18 17:21:09 +03:00
parent 80a370959a
commit 043246d2f2
4 changed files with 150 additions and 96 deletions

@ -41,6 +41,7 @@ export default function OptionsAndPicture({
setOpenBranchingPage, setOpenBranchingPage,
}: Props) { }: Props) {
const [switchState, setSwitchState] = useState("setting"); const [switchState, setSwitchState] = useState("setting");
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
const [selectedVariantId, setSelectedVariantId] = useState<string | null>( const [selectedVariantId, setSelectedVariantId] = useState<string | null>(
null, null,
); );
@ -66,24 +67,30 @@ export default function OptionsAndPicture({
const handleImageUpload = async (file: File) => { const handleImageUpload = async (file: File) => {
if (!selectedVariantId) return; if (!selectedVariantId) return;
const url = await uploadQuestionImage( setPictureUploading(true);
question.id,
quizQid,
file,
(question, url) => {
if (!("variants" in question.content)) return;
const variant = question.content.variants.find( try {
(variant) => variant.id === selectedVariantId, const url = await uploadQuestionImage(
); question.id,
if (!variant) return; quizQid,
file,
(question, url) => {
if (!("variants" in question.content)) return;
variant.extendedText = url; const variant = question.content.variants.find(
variant.originalImageUrl = url; (variant) => variant.id === selectedVariantId,
}, );
); if (!variant) return;
closeImageUploadModal();
openCropModal(file, url); variant.extendedText = url;
variant.originalImageUrl = url;
},
);
closeImageUploadModal();
openCropModal(file, url);
} catch {}
setPictureUploading(false);
}; };
function handleCropModalSaveClick(imageBlob: Blob) { function handleCropModalSaveClick(imageBlob: Blob) {
@ -111,6 +118,7 @@ export default function OptionsAndPicture({
{!isMobile && ( {!isMobile && (
<AddOrEditImageButton <AddOrEditImageButton
imageSrc={variant.extendedText} imageSrc={variant.extendedText}
uploading={pictureUploding}
onImageClick={() => { onImageClick={() => {
setSelectedVariantId(variant.id); setSelectedVariantId(variant.id);
if (variant.extendedText) { if (variant.extendedText) {
@ -136,6 +144,7 @@ export default function OptionsAndPicture({
{isMobile && ( {isMobile && (
<AddOrEditImageButton <AddOrEditImageButton
imageSrc={variant.extendedText} imageSrc={variant.extendedText}
uploading={pictureUploding}
onImageClick={() => { onImageClick={() => {
setSelectedVariantId(variant.id); setSelectedVariantId(variant.id);
if (variant.extendedText) { if (variant.extendedText) {

@ -1,4 +1,11 @@
import { Box, Link, Typography, useMediaQuery, useTheme } from "@mui/material"; import {
Box,
Link,
Typography,
Skeleton,
useMediaQuery,
useTheme,
} from "@mui/material";
import { import {
addQuestionVariant, addQuestionVariant,
uploadQuestionImage, uploadQuestionImage,
@ -30,6 +37,7 @@ export default function OptionsPicture({
const theme = useTheme(); const theme = useTheme();
const onClickAddAnAnswer = useAddAnswer(); const onClickAddAnAnswer = useAddAnswer();
const quizQid = useCurrentQuiz()?.qid; const quizQid = useCurrentQuiz()?.qid;
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
const [selectedVariantId, setSelectedVariantId] = useState<string | null>( const [selectedVariantId, setSelectedVariantId] = useState<string | null>(
null, null,
); );
@ -53,24 +61,31 @@ export default function OptionsPicture({
const handleImageUpload = async (file: File) => { const handleImageUpload = async (file: File) => {
if (!selectedVariantId) return; if (!selectedVariantId) return;
const url = await uploadQuestionImage( setPictureUploading(true);
question.id,
quizQid,
file,
(question, url) => {
if (!("variants" in question.content)) return;
const variant = question.content.variants.find( try {
(variant) => variant.id === selectedVariantId, const url = await uploadQuestionImage(
); question.id,
if (!variant) return; quizQid,
file,
(question, url) => {
if (!("variants" in question.content)) return;
variant.extendedText = url; const variant = question.content.variants.find(
variant.originalImageUrl = url; (variant) => variant.id === selectedVariantId,
}, );
); if (!variant) return;
closeImageUploadModal();
openCropModal(file, url); variant.extendedText = url;
variant.originalImageUrl = url;
},
);
closeImageUploadModal();
openCropModal(file, url);
} catch {}
setPictureUploading(false);
}; };
function handleCropModalSaveClick(imageBlob: Blob) { function handleCropModalSaveClick(imageBlob: Blob) {
@ -98,6 +113,7 @@ export default function OptionsPicture({
{!isMobile && ( {!isMobile && (
<AddOrEditImageButton <AddOrEditImageButton
imageSrc={variant.extendedText} imageSrc={variant.extendedText}
uploading={pictureUploding}
onImageClick={() => { onImageClick={() => {
setSelectedVariantId(variant.id); setSelectedVariantId(variant.id);
if (variant.extendedText) { if (variant.extendedText) {
@ -123,6 +139,7 @@ export default function OptionsPicture({
{isMobile && ( {isMobile && (
<AddOrEditImageButton <AddOrEditImageButton
imageSrc={variant.extendedText} imageSrc={variant.extendedText}
uploading={pictureUploding}
onImageClick={() => { onImageClick={() => {
setSelectedVariantId(variant.id); setSelectedVariantId(variant.id);
if (variant.extendedText) { if (variant.extendedText) {

@ -1,12 +1,15 @@
import { Box, Button, Skeleton, useTheme, useMediaQuery } from "@mui/material";
import Plus from "@icons/questionsPage/plus"; import Plus from "@icons/questionsPage/plus";
import { Box, Button, SxProps, Theme } from "@mui/material";
import Image from "../assets/icons/questionsPage/image"; import Image from "../assets/icons/questionsPage/image";
import type { SxProps, Theme } from "@mui/material";
interface Props { interface Props {
sx?: SxProps<Theme>; sx?: SxProps<Theme>;
imageSrc?: string; imageSrc?: string;
onImageClick?: () => void; onImageClick?: () => void;
onPlusClick?: () => void; onPlusClick?: () => void;
uploading: boolean;
} }
export default function AddOrEditImageButton({ export default function AddOrEditImageButton({
@ -14,59 +17,76 @@ export default function AddOrEditImageButton({
onPlusClick, onPlusClick,
sx, sx,
imageSrc, imageSrc,
uploading = false,
}: Props) { }: Props) {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(790));
return ( return (
<Box <>
sx={{ {uploading ? (
display: "flex", <Skeleton
height: "40px", variant="rounded"
minWidth: "60px", sx={{
width: "60px", height: "40px",
borderRadius: "3px", width: isMobile ? "auto" : "80px",
overflow: "hidden", margin: isMobile ? "8px" : "0 10px 0 8px",
...sx, }}
}} />
> ) : (
<Button <Box
onClick={onImageClick} sx={{
sx={{ display: "flex",
p: 0, height: "40px",
minWidth: "40px", minWidth: "60px",
flexGrow: 1, width: "60px",
backgroundColor: "#EEE4FC", borderRadius: "3px",
}} overflow: "hidden",
> ...sx,
{imageSrc ? ( }}
<img >
src={imageSrc} <Button
alt="" onClick={onImageClick}
style={{
width: "100%",
height: "100%",
objectFit: "scale-down",
display: "block",
}}
/>
) : (
<Image
sx={{ sx={{
height: "100%", p: 0,
width: "100%", minWidth: "40px",
flexGrow: 1,
backgroundColor: "#EEE4FC",
}} }}
/> >
)} {imageSrc ? (
</Button> <img
<Button src={imageSrc}
onClick={onPlusClick} alt=""
data-cy="add-image-button" style={{
sx={{ width: "100%",
p: 0, height: "100%",
minWidth: "20px", objectFit: "scale-down",
width: "20px", display: "block",
}} }}
> />
<Plus /> ) : (
</Button> <Image
</Box> sx={{
height: "100%",
width: "100%",
}}
/>
)}
</Button>
<Button
onClick={onPlusClick}
data-cy="add-image-button"
sx={{
p: 0,
minWidth: "20px",
width: "20px",
}}
>
<Plus />
</Button>
</Box>
)}
</>
); );
} }

@ -1,4 +1,4 @@
import { FC } from "react"; import { useState, FC } from "react";
import { import {
Box, Box,
Button, Button,
@ -25,6 +25,7 @@ interface Iprops {
} }
export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => { export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
const quizQid = useCurrentQuiz()?.qid; const quizQid = useCurrentQuiz()?.qid;
const theme = useTheme(); const theme = useTheme();
const { const {
@ -38,17 +39,23 @@ export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] = const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] =
useDisclosure(); useDisclosure();
async function handleImageUpload(file: File) { async function handleImageUpload(file: File) {
const url = await uploadQuestionImage( setPictureUploading(true);
resultData.id,
quizQid, try {
file, const url = await uploadQuestionImage(
(question, url) => { resultData.id,
question.content.back = url; quizQid,
question.content.originalBack = url; file,
}, (question, url) => {
); question.content.back = url;
closeImageUploadModal(); question.content.originalBack = url;
openCropModal(file, url); },
);
closeImageUploadModal();
openCropModal(file, url);
} catch {}
setPictureUploading(false);
} }
function handleCropModalSaveClick(imageBlob: Blob) { function handleCropModalSaveClick(imageBlob: Blob) {
@ -142,6 +149,7 @@ export const MediaSelectionAndDisplay: FC<Iprops> = ({ resultData }) => {
> >
<AddOrEditImageButton <AddOrEditImageButton
imageSrc={resultData.content.back} imageSrc={resultData.content.back}
uploading={pictureUploding}
onImageClick={() => { onImageClick={() => {
if (resultData.content.back) { if (resultData.content.back) {
return openCropModal( return openCropModal(