mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
ajout front images gallery
This commit is contained in:
parent
16d594c61d
commit
c9d65c0082
5 changed files with 136 additions and 5 deletions
11
client/src/Types/Images.tsx
Normal file
11
client/src/Types/Images.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
export interface Images {
|
||||||
|
id: string;
|
||||||
|
file_content: string;
|
||||||
|
file_name: string;
|
||||||
|
mime_type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImagesResponse {
|
||||||
|
images: Images[];
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,8 @@ import ReturnButton from 'src/components/ReturnButton/ReturnButton';
|
||||||
|
|
||||||
import ApiService from '../../../services/ApiService';
|
import ApiService from '../../../services/ApiService';
|
||||||
import { escapeForGIFT } from '../../../utils/giftUtils';
|
import { escapeForGIFT } from '../../../utils/giftUtils';
|
||||||
import { Upload } from '@mui/icons-material';
|
import { Upload, ImageSearch } from '@mui/icons-material';
|
||||||
|
import { Images } from '../../../Types/Images';
|
||||||
|
|
||||||
interface EditQuizParams {
|
interface EditQuizParams {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -40,7 +41,12 @@ const QuizForm: React.FC = () => {
|
||||||
};
|
};
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
|
const [galleryOpen, setGalleryOpen] = useState(false);
|
||||||
const [showScrollButton, setShowScrollButton] = useState(false);
|
const [showScrollButton, setShowScrollButton] = useState(false);
|
||||||
|
const [images, setImages] = useState<Images[]>([]);
|
||||||
|
const [totalImg, setTotalImg] = useState(0);
|
||||||
|
const [imgPage, setImgPage] = useState(1);
|
||||||
|
const [imgLimit] = useState(5);
|
||||||
|
|
||||||
const scrollToTop = () => {
|
const scrollToTop = () => {
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
|
|
@ -69,9 +75,19 @@ const QuizForm: React.FC = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchImages = async (page: number , limit: number) => {
|
||||||
|
const data = await ApiService.getImages(page, limit);
|
||||||
|
const imgs = data.images;
|
||||||
|
const total = data.total;
|
||||||
|
|
||||||
|
setImages(imgs as Images[]);
|
||||||
|
setTotalImg(total);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
const userFolders = await ApiService.getUserFolders();
|
const userFolders = await ApiService.getUserFolders();
|
||||||
|
fetchImages(1, imgLimit);
|
||||||
setFolders(userFolders as FolderType[]);
|
setFolders(userFolders as FolderType[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -205,6 +221,13 @@ const QuizForm: React.FC = () => {
|
||||||
navigator.clipboard.writeText(link);
|
navigator.clipboard.writeText(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleMoreImages = async () => {
|
||||||
|
let page = imgPage;
|
||||||
|
page += 1;
|
||||||
|
setImgPage(page);
|
||||||
|
fetchImages(imgPage, imgLimit);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='quizEditor'>
|
<div className='quizEditor'>
|
||||||
|
|
||||||
|
|
@ -290,6 +313,48 @@ const QuizForm: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4>Mes images :</h4>
|
<h4>Mes images :</h4>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
aria-label='Téléverser'
|
||||||
|
onClick={() => setGalleryOpen(true)}>
|
||||||
|
Images <ImageSearch />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Dialog
|
||||||
|
open={galleryOpen}
|
||||||
|
onClose={() => setDialogOpen(false)} >
|
||||||
|
<DialogTitle>Images disponibles</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-3 gap-4 p-4">
|
||||||
|
{images.map((obj: Images, index) => (
|
||||||
|
<div key={obj.id}>
|
||||||
|
<img
|
||||||
|
key={index}
|
||||||
|
src={`data:${obj.mime_type};base64,${obj.file_content}`}
|
||||||
|
alt={`Image ${obj.file_name + 1}`}
|
||||||
|
className="w-full h-auto rounded-lg shadow-md"
|
||||||
|
/>
|
||||||
|
{`lien: ${obj.id}`}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
{
|
||||||
|
totalImg > 10 ?
|
||||||
|
<Button onClick={() => handleMoreImages()} color="primary">
|
||||||
|
Plus
|
||||||
|
</Button>
|
||||||
|
:
|
||||||
|
<Button onClick={() => setDialogOpen(false)} color="primary">
|
||||||
|
OK
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
}
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ display: "inline" }}>(Voir section </div>
|
<div style={{ display: "inline" }}>(Voir section </div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import axios, { AxiosError, AxiosResponse } from 'axios';
|
import axios, { AxiosError, AxiosResponse } from 'axios';
|
||||||
|
|
||||||
import { FolderType } from 'src/Types/FolderType';
|
import { FolderType } from 'src/Types/FolderType';
|
||||||
|
import { ImagesResponse } from '../Types/Images';
|
||||||
import { QuizType } from 'src/Types/QuizType';
|
import { QuizType } from 'src/Types/QuizType';
|
||||||
import { ENV_VARIABLES } from 'src/constants';
|
import { ENV_VARIABLES } from 'src/constants';
|
||||||
|
|
||||||
|
|
@ -65,6 +66,16 @@ class ApiService {
|
||||||
return object.token;
|
return object.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getUserID(): string | null {
|
||||||
|
const objStr = localStorage.getItem("uid");
|
||||||
|
|
||||||
|
if (!objStr) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return objStr;
|
||||||
|
}
|
||||||
|
|
||||||
public isLoggedIn(): boolean {
|
public isLoggedIn(): boolean {
|
||||||
const token = this.getToken()
|
const token = this.getToken()
|
||||||
|
|
||||||
|
|
@ -141,7 +152,8 @@ class ApiService {
|
||||||
throw new Error(`La connexion a échoué. Status: ${result.status}`);
|
throw new Error(`La connexion a échoué. Status: ${result.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.saveToken(result.data.token);
|
this.saveToken(result.data.result.token);
|
||||||
|
localStorage.setItem("uid", JSON.stringify(result.data.result.userId));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
@ -886,7 +898,38 @@ class ApiService {
|
||||||
return `ERROR : Une erreur inattendue s'est produite.`
|
return `ERROR : Une erreur inattendue s'est produite.`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// NOTE : Get Image pas necessaire
|
|
||||||
|
|
||||||
|
public async getImages(page: number, limit: number): Promise<ImagesResponse> {
|
||||||
|
try {
|
||||||
|
const url: string = this.constructRequestUrl(`/image/getImages`);
|
||||||
|
const headers = this.constructRequestHeaders();
|
||||||
|
const params = { page: page, limit: limit};
|
||||||
|
|
||||||
|
const result: AxiosResponse = await axios.get(url, { params: params, headers: headers });
|
||||||
|
|
||||||
|
if (result.status !== 200) {
|
||||||
|
throw new Error(`L'enregistrement a échoué. Status: ${result.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(result.data);
|
||||||
|
const images = result.data;
|
||||||
|
|
||||||
|
return images;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error details: ", error);
|
||||||
|
|
||||||
|
if (axios.isAxiosError(error)) {
|
||||||
|
const err = error as AxiosError;
|
||||||
|
const data = err.response?.data as { error: string } | undefined;
|
||||||
|
const msg = data?.error || 'Erreur serveur inconnue lors de la requête.';
|
||||||
|
throw new Error(`L'enregistrement a échoué. Status: ${msg}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`ERROR : Une erreur inattendue s'est produite.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,12 @@ class UsersController {
|
||||||
|
|
||||||
const token = jwt.create(user.email, user._id);
|
const token = jwt.create(user.email, user._id);
|
||||||
|
|
||||||
return res.status(200).json({ token });
|
let result = {
|
||||||
|
token: token,
|
||||||
|
userId: user._id
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({ result });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ class Images {
|
||||||
|
|
||||||
if (!result) return null;
|
if (!result) return null;
|
||||||
|
|
||||||
|
const total = result.length;
|
||||||
|
|
||||||
const objImages = result.slice((page - 1) * limit, page * limit).map(image => ({
|
const objImages = result.slice((page - 1) * limit, page * limit).map(image => ({
|
||||||
id: image._id,
|
id: image._id,
|
||||||
user: image.userId,
|
user: image.userId,
|
||||||
|
|
@ -60,7 +62,12 @@ class Images {
|
||||||
mime_type: image.mime_type
|
mime_type: image.mime_type
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return objImages;
|
let respObj = {
|
||||||
|
images: objImages,
|
||||||
|
total: total
|
||||||
|
}
|
||||||
|
|
||||||
|
return respObj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue