From 1cfadd711b0e39db20ff8ec19c0453b2ce07e412 Mon Sep 17 00:00:00 2001 From: alij Date: Sat, 22 Jun 2024 16:28:15 +0430 Subject: [PATCH] feat : dynamic tutorial page --- src/pages/tutorial/section/Tutorials.tsx | 37 ++--- .../tutorial/section/components/Leran.tsx | 157 ++++++++---------- .../section/components/ListTutorial.tsx | 37 +++++ src/types/props.d.ts | 80 ++++++++- 4 files changed, 205 insertions(+), 106 deletions(-) diff --git a/src/pages/tutorial/section/Tutorials.tsx b/src/pages/tutorial/section/Tutorials.tsx index f97469b..f76de3b 100644 --- a/src/pages/tutorial/section/Tutorials.tsx +++ b/src/pages/tutorial/section/Tutorials.tsx @@ -1,27 +1,19 @@ import { useState } from "react"; import Learn from "./components/Leran"; import ListTutorials from "./components/ListTutorial"; -import { TutorialList } from "../../../types/props"; +import useAxios from "../../../hooks/useAxios"; +import { useQuery } from "@tanstack/react-query"; const Tutorials = () => { - const tutorialList: TutorialList = [ - { - id: 1, - name: "آموزش اشتراکی اندروید", - }, - { - id: 2, - name: "آموزش اشتراکی آیفون", - }, - { - id: 3, - name: "آموزش سرویس مولتی", - }, - { - id: 4, - name: "آموزش open vpn در اندروید", - }, - ]; + const axios = useAxios() + const {data,error,isLoading,isFetching} = useQuery({ + queryKey:["categoryLearning"], + queryFn:()=>{ + return axios.get('/home/category/learning') + } + }) + console.log(data?.data?.result); + const [activeTutorial, setActiveTutorial] = useState(1); return (
@@ -31,10 +23,13 @@ const Tutorials = () => {

- +
); }; diff --git a/src/pages/tutorial/section/components/Leran.tsx b/src/pages/tutorial/section/components/Leran.tsx index e8b30ab..d1f6826 100644 --- a/src/pages/tutorial/section/components/Leran.tsx +++ b/src/pages/tutorial/section/components/Leran.tsx @@ -1,94 +1,83 @@ -import { SyntheticEvent, useEffect, useState } from "react"; import { LearnProps } from "../../../../types/props"; -import { BiLoaderAlt } from "react-icons/bi"; +import { useQuery } from "@tanstack/react-query"; +import useAxios from "../../../../hooks/useAxios"; +import Alert from "../../../../components/alert/Alert"; +import { MdErrorOutline } from "react-icons/md"; -const Learn = ({ activeTutorial, tutorialList }: LearnProps) => { - const tutorialImages = [ - { - id: 1, - images: [{ urlimg: "https://persain-game.com/front_end/img/v2ray.png" }], +const Learn = ({ activeTutorial }: LearnProps) => { + const axios = useAxios(); + const { data, isLoading, isFetching, error } = useQuery({ + queryKey: ["learn", activeTutorial], + queryFn: () => { + return axios.get(`/home/category/learning/${activeTutorial}`); }, - { - id: 2, - images: [ - { urlimg: "https://persain-game.com/front_end/img/1-eshterki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/2-eshteraki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/3-eshteraki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/4-eshteraki.jpg" }, - ], - }, - { - id: 3, - images: [ - { urlimg: "https://persain-game.com/front_end/img/1-eshterki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/2-eshteraki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/3-eshteraki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/4-eshteraki.jpg" }, - ], - }, - { - id: 4, - images: [ - { urlimg: "https://persain-game.com/front_end/img/1-eshterki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/2-eshteraki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/3-eshteraki.jpg" }, - { urlimg: "https://persain-game.com/front_end/img/4-eshteraki.jpg" }, - ], - }, - ]; - const [loading, setLoading] = useState(true); - const [list, setList] = useState( - tutorialList?.filter((id) => id.id === activeTutorial) - ); - const [tutorialImagesState, setTutorialImagesState] = useState( - tutorialImages?.filter((id) => id.id === activeTutorial) - ); - useEffect(() => { - setList(tutorialList?.filter((id) => id.id === activeTutorial)); - setTutorialImagesState( - tutorialImages?.filter((id) => id.id === activeTutorial) - ); - setLoading(true); - }, [activeTutorial]); - const handleLoadingImage = (e: SyntheticEvent) => { - if (e.type === "load") setLoading(false); - }; + }); return (
- {list?.map((i) => { - return ( -
+ - {i.name} - {loading && ( -
- + + + + +
+ ) : error ? ( + + {error.message} + + ) : data?.data?.result.length === 0 ? ( +
+ +

اموزشی وجود ندارد

+
+ ) : ( + data?.data?.result.map( + (i: { id: string; title: string; medias: string[] }) => { + return ( +
+ + {i.title} + +
+ {i.medias.map((medias, index) => { + return ( + images + ); + })} +
- )} -
- {tutorialImagesState?.map((i) => { - return ( -
- {i.images?.map((item, index) => { - return ( - images handleLoadingImage(e)} - /> - ); - })} -
- ); - })} -
-
- ); - })} + ); + } + ) + )}
); }; diff --git a/src/pages/tutorial/section/components/ListTutorial.tsx b/src/pages/tutorial/section/components/ListTutorial.tsx index 14f4305..164fcd3 100644 --- a/src/pages/tutorial/section/components/ListTutorial.tsx +++ b/src/pages/tutorial/section/components/ListTutorial.tsx @@ -1,10 +1,47 @@ +import { Skeleton } from "@mui/material"; import { ListTutorialsProps } from "../../../../types/props"; +import Alert from "../../../../components/alert/Alert"; +import Button from "../../../../components/button"; const ListTutorials = ({ tutorialList, activeTutorial, + isLoading, + isFetching, + error, setActiveTutorial, }: ListTutorialsProps) => { + if (isLoading || isFetching) { + return ( +
+ {Array(3) + .fill(null) + .map((_, i) => ( +
+ +
+ ))} +
+ ); + } + + if (error) { + return ( +
+ + {error.message} + +
+ ); + } + return (
    diff --git a/src/types/props.d.ts b/src/types/props.d.ts index 3b68506..b0fe967 100644 --- a/src/types/props.d.ts +++ b/src/types/props.d.ts @@ -5,6 +5,7 @@ export interface AlertProps { children: React.ReactNode; type?: "info" | "danger" | "success" | "warning" | "dark"; message?: string; + extra?: string; } // begin Button.tsx @@ -58,12 +59,16 @@ import React, { SetStateAction, } from "react"; import { FormikProps } from "formik"; +import { AxiosError } from "axios"; export type TutorialList = { id: number; name: string }[]; export interface ListTutorialsProps { tutorialList: TutorialList; activeTutorial: number; + isLoading: boolean; + isFetching: boolean; + error: Error | AxiosError | null; setActiveTutorial: SetStateAction; } @@ -79,7 +84,10 @@ export interface TypewriterProps { } export interface ButtonListProps { - ProductsList: { id: number; title: string }[]; + ProductsList: { id: number; name: string; label?: string }[]; + isLoading: boolean; + isFetching: boolean; + error: Error | AxiosError | null; activeId: number; setActiveId: SetStateAction; } @@ -110,6 +118,7 @@ export interface MuiModalProps { nameService?: string; submitText?: string; submitOnClick?: () => void; + disabled?: boolean; children: React.ReactNode; } @@ -117,6 +126,8 @@ export interface ConfigItemProps { dateBuy: string; configName: string; isDisabled: boolean; + isShowTraffic: boolean; + textCopy: string; } // نوع Item برای آیتم‌های داخل Dropdown @@ -147,3 +158,70 @@ export interface LoginFormValues { export interface LoginFromikProps { formik: FormikProps; } + +interface BuyResponse { + message: string; +} + +interface BuyError { + message: string; +} + +interface ModalBuyProps { + isOpen: boolean; + setIsOpen: Dispatch>; + // mutation: UseMutationResult< + // AxiosResponse, + // BuyError, + // BuyConfigData, + // unknown + // >; + configId: number; +} + +interface BuyConfigDataProps { + count?: number; + discount?: string; + status?: string; +} +// تعریف تایپ داده‌های واقعی پروفایل کاربر +type UserProfile = { + id: number; + name: string; + email: string; + mobile: string; +}; + +// تعریف تایپ پیکربندی‌ها +type Config = { + id: number; + title: string; + url: string; + created_at: string | null; + show_traffic: boolean; + max_traffic: number; + traffic: number; +}; + +// تعریف تایپ داده‌های برگشتی +type ProfileResponseData = { + result: { + user_profile: UserProfile; + enable_config: number; + disable_config: number; + configs: Config[]; + }; + status: boolean; + alert: string; +}; + +// تایپ خطا +type QueryError = Error | AxiosError | null; + +interface ProfileDetailsProps { + data: ProfileResponseData; + isLoading: boolean; + isFetching: boolean; + error: Error | AxiosError | null; + userTitle: string; +}