Compare commits
2 Commits
f5e0bebeb0
...
b873ac0bba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b873ac0bba | ||
|
|
a4c3459efa |
File diff suppressed because one or more lines are too long
14
index.html
14
index.html
|
|
@ -5,18 +5,8 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/App/Logo.png" />
|
<link rel="apple-touch-icon" sizes="180x180" href="/App/Logo.png" />
|
||||||
<link
|
<link rel="icon" type="image/png" sizes="32x32" href="/App/Logo.png" />
|
||||||
rel="icon"
|
<link rel="icon" type="image/png" sizes="16x16" href="/App/Logo.png" />
|
||||||
type="image/png"
|
|
||||||
sizes="32x32"
|
|
||||||
href="/App/Logo.png"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="icon"
|
|
||||||
type="image/png"
|
|
||||||
sizes="16x16"
|
|
||||||
href="/App/Logo.png"
|
|
||||||
/>
|
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "my-app",
|
"name": "my-app",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^5.3.7",
|
"@ant-design/icons": "^5.3.7",
|
||||||
|
|
|
||||||
7711
pnpm-lock.yaml
7711
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
17
src/App.tsx
17
src/App.tsx
|
|
@ -17,7 +17,7 @@ const App = () => {
|
||||||
const { changeLanguage } = useChangeLanguage();
|
const { changeLanguage } = useChangeLanguage();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { isAuthenticated } = useAuthState();
|
const { isAuthenticated } = useAuthState();
|
||||||
const [t] = useTranslation()
|
const [t] = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
|
|
@ -26,7 +26,14 @@ const App = () => {
|
||||||
}, [isAuthenticated, navigate]);
|
}, [isAuthenticated, navigate]);
|
||||||
|
|
||||||
const renderRouteElement = (route: any) => (
|
const renderRouteElement = (route: any) => (
|
||||||
<Suspense fallback={<Layout> <SpinContainer/> </Layout>}>
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<Layout>
|
||||||
|
{" "}
|
||||||
|
<SpinContainer />{" "}
|
||||||
|
</Layout>
|
||||||
|
}
|
||||||
|
>
|
||||||
{route.header ? (
|
{route.header ? (
|
||||||
<Layout>{route.element}</Layout>
|
<Layout>{route.element}</Layout>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -35,11 +42,11 @@ const App = () => {
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderRoutesRecursively = (routes:TMenuItem[]) =>
|
const renderRoutesRecursively = (routes: TMenuItem[]) =>
|
||||||
routes.map((route: TMenuItem) => {
|
routes.map((route: TMenuItem) => {
|
||||||
const useAbility = hasAbility(route.abilities, route.abilities_value);
|
const useAbility = hasAbility(route.abilities, route.abilities_value);
|
||||||
const tableHeader = t(`${route?.header}`);
|
const tableHeader = t(`${route?.header}`);
|
||||||
// useSetPage_title(tableHeader,route?.path);
|
// useSetPageTitle(tableHeader,route?.path);
|
||||||
|
|
||||||
if (useAbility) {
|
if (useAbility) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -80,7 +87,7 @@ const App = () => {
|
||||||
{CrudRoute.map((route) => {
|
{CrudRoute.map((route) => {
|
||||||
const useAbility = hasAbility(route.abilities, route.abilities_value);
|
const useAbility = hasAbility(route.abilities, route.abilities_value);
|
||||||
const tableHeader = t(`${route?.header}`);
|
const tableHeader = t(`${route?.header}`);
|
||||||
// useSetPage_title(tableHeader,route?.path);
|
// useSetPageTitle(tableHeader,route?.path);
|
||||||
|
|
||||||
if (!useAbility) {
|
if (!useAbility) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
|
||||||
import ReactApexChart from "react-apexcharts";
|
|
||||||
|
|
||||||
const AreaChart: React.FC = () => {
|
|
||||||
const chartRef = useRef<any>(null); // Ref for the chart component
|
|
||||||
const [options, setOptions] = useState<any>({
|
|
||||||
chart: {
|
|
||||||
type: "area",
|
|
||||||
toolbar: {
|
|
||||||
show: false, // Disable the toolbar
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dataLabels: {
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
stroke: {
|
|
||||||
curve: "smooth",
|
|
||||||
},
|
|
||||||
xaxis: {
|
|
||||||
type: "datetime",
|
|
||||||
categories: [
|
|
||||||
"2018-09-19T00:00:00.000Z",
|
|
||||||
"2018-09-19T01:30:00.000Z",
|
|
||||||
"2018-09-19T02:30:00.000Z",
|
|
||||||
"2018-09-19T03:30:00.000Z",
|
|
||||||
"2018-09-19T04:30:00.000Z",
|
|
||||||
"2018-09-19T05:30:00.000Z",
|
|
||||||
"2018-09-19T06:30:00.000Z",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
x: {
|
|
||||||
format: "dd/MM/yy HH:mm",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const [series, setSeries] = useState<any>([
|
|
||||||
{ name: "series1", data: [31, 40, 28, 51, 42, 109, 100], color: "#FCC43E" },
|
|
||||||
{ name: "series2", data: [11, 32, 45, 32, 34, 52, 41], color: "#FB7D5B" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="AreaChart">
|
|
||||||
<div id="chart">
|
|
||||||
<ReactApexChart
|
|
||||||
options={options}
|
|
||||||
series={series}
|
|
||||||
type="area"
|
|
||||||
className="ReactApexChartArea"
|
|
||||||
height={400}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div id="html-dist"></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AreaChart;
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
import { Radio, Select } from "antd";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import ReactApexChart from "react-apexcharts";
|
|
||||||
|
|
||||||
import { IoMdArrowDropdown } from "react-icons/io";
|
|
||||||
|
|
||||||
const ColumnChart: React.FC = () => {
|
|
||||||
const series = [
|
|
||||||
{
|
|
||||||
name: "غياب",
|
|
||||||
data: [44, 55, 57, 56, 61, 58],
|
|
||||||
color: "#FB7D5B",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "حضور",
|
|
||||||
data: [76, 85, 70, 98, 87, 80],
|
|
||||||
color: "#FCC43E",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const options: any = {
|
|
||||||
chart: {
|
|
||||||
type: "bar",
|
|
||||||
},
|
|
||||||
plotOptions: {
|
|
||||||
bar: {
|
|
||||||
horizontal: false,
|
|
||||||
columnWidth: "35%",
|
|
||||||
endingShape: "rounded",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dataLabels: {
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
xaxis: {
|
|
||||||
categories: ["Feb", "Mar", "Apr", "May", "Jun", "Jul"],
|
|
||||||
},
|
|
||||||
// yaxis: {
|
|
||||||
// title: {
|
|
||||||
// text: '$ (thousands)'
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
fill: {
|
|
||||||
opacity: 1,
|
|
||||||
colors: ["#FB7D5B", "#FCC43E"], // Red and Green colors
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
y: {
|
|
||||||
formatter: function (val: number) {
|
|
||||||
return val + " طالب";
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
show: false, // Hide the legend
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const [value, setValue] = useState(1);
|
|
||||||
|
|
||||||
const handleChangeSelect = (value: string) => {};
|
|
||||||
return (
|
|
||||||
<div className="ColumnChart">
|
|
||||||
<div className="ColumnChart_header">
|
|
||||||
<span>الغياب المتكرر</span>
|
|
||||||
|
|
||||||
<span className="Legend">
|
|
||||||
<div data-attr="red">غياب</div>
|
|
||||||
<div>حضور</div>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
defaultValue="هذا الأسبوع"
|
|
||||||
onChange={handleChangeSelect}
|
|
||||||
suffixIcon={<IoMdArrowDropdown size={30} />}
|
|
||||||
options={[
|
|
||||||
{ value: "هذا الأسبوع", label: "هذا الأسبوع" },
|
|
||||||
{ value: "هذا الأسبوع", label: "هذا الأسبوع" },
|
|
||||||
{ value: "هذا الأسبوع", label: "هذا الأسبوع" },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="ColumnChartWrapper" id="chart">
|
|
||||||
<ReactApexChart
|
|
||||||
options={options}
|
|
||||||
series={series}
|
|
||||||
type="bar"
|
|
||||||
height={"100%"}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div id="html-dist"></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ColumnChart;
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import Chart from "react-apexcharts";
|
|
||||||
|
|
||||||
const LineChart: React.FC = () => {
|
|
||||||
const series = [
|
|
||||||
{
|
|
||||||
name: "Desktops",
|
|
||||||
data: [10, 41, 35, 51, 49, 62, 69, 91, 148],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const options: any = {
|
|
||||||
chart: {
|
|
||||||
height: 350,
|
|
||||||
type: "line",
|
|
||||||
zoom: {
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dataLabels: {
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
stroke: {
|
|
||||||
curve: "straight",
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: "Product Trends by Month",
|
|
||||||
align: "left",
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
row: {
|
|
||||||
colors: ["#f3f3f3", "transparent"], // takes an array which will be repeated on columns
|
|
||||||
opacity: 0.5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
xaxis: {
|
|
||||||
categories: [
|
|
||||||
"Jan",
|
|
||||||
"Feb",
|
|
||||||
"Mar",
|
|
||||||
"Apr",
|
|
||||||
"May",
|
|
||||||
"Jun",
|
|
||||||
"Jul",
|
|
||||||
"Aug",
|
|
||||||
"Sep",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div id="chart">
|
|
||||||
<Chart options={options} series={series} type="line" height={350} />
|
|
||||||
</div>
|
|
||||||
<div id="html-dist"></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LineChart;
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import Chart from "react-apexcharts";
|
|
||||||
|
|
||||||
const PieChart = () => {
|
|
||||||
const series = [44, 55, 13] as any;
|
|
||||||
const options: any = {
|
|
||||||
series: [44, 55, 13],
|
|
||||||
chart: {
|
|
||||||
width: 380,
|
|
||||||
type: "pie",
|
|
||||||
},
|
|
||||||
labels: ["Team A", "Team B", "Team C", "Team D", "Team E"],
|
|
||||||
legend: {
|
|
||||||
position: "bottom",
|
|
||||||
},
|
|
||||||
responsive: [
|
|
||||||
{
|
|
||||||
breakpoint: 480,
|
|
||||||
options: {
|
|
||||||
chart: {
|
|
||||||
width: 200,
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
position: "bottom",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div id="chart">
|
|
||||||
<Chart options={options} series={series} type="pie" width={380} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PieChart;
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { Segmented } from "antd";
|
|
||||||
|
|
||||||
const ClassesSegmented: React.FC = () => (
|
|
||||||
<Segmented<string>
|
|
||||||
options={["الأحد", "اللإثنين", "الثلاثاء", "الأربعاء", "الخميس"]}
|
|
||||||
onChange={(value) => {}}
|
|
||||||
className="Segmented"
|
|
||||||
block
|
|
||||||
defaultChecked
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ClassesSegmented;
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import { FaPlus, FaUser } from "react-icons/fa";
|
|
||||||
import { IoMdArrowDropdown, IoMdArrowDropup } from "react-icons/io";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { Popover, Spin } from "antd";
|
|
||||||
import { CourseItem } from "../../types/Item";
|
|
||||||
import { ModalEnum } from "../../enums/Model";
|
|
||||||
import useModalHandler from "../../utils/useModalHandler";
|
|
||||||
import { FaEllipsis } from "react-icons/fa6";
|
|
||||||
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../../enums/abilities";
|
|
||||||
import { hasAbility } from "../../utils/hasAbility";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
const HeaderCardsSection = ({ data, isLoading }: any) => {
|
|
||||||
const [showAll, setShowAll] = useState<boolean>(false);
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
const toggleShowAll = () => {
|
|
||||||
setShowAll(!showAll);
|
|
||||||
};
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const index_eduClass_ability = hasAbility(
|
|
||||||
ABILITIES_ENUM?.EDUCATION_CLASS,
|
|
||||||
ABILITIES_VALUES_ENUM?.INDEX,
|
|
||||||
);
|
|
||||||
|
|
||||||
const handelnavigate = (item: CourseItem) => {
|
|
||||||
if (index_eduClass_ability) {
|
|
||||||
navigate(
|
|
||||||
`/${ABILITIES_ENUM?.COURSE}/${item?.id}/${ABILITIES_ENUM?.EDUCATION_CLASS}`,
|
|
||||||
);
|
|
||||||
// set_title(item?.name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const { handel_open_model } = useModalHandler();
|
|
||||||
const Courses = data?.data || [];
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <Spin />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PopoverContent = (
|
|
||||||
<div className="PopoverContent">
|
|
||||||
<p onClick={() => handel_open_model(ModalEnum?.COURSE_ADD)}>
|
|
||||||
{" "}
|
|
||||||
{t("practical.add")} {t("models.course")} <FaPlus />{" "}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const store_course_ability = hasAbility(
|
|
||||||
ABILITIES_ENUM?.COURSE,
|
|
||||||
ABILITIES_VALUES_ENUM?.STORE,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="header_cards_section">
|
|
||||||
<div className="CountCards">
|
|
||||||
{Courses?.length > 0 &&
|
|
||||||
Courses?.map((item: CourseItem, index: number) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onClick={() => handelnavigate(item)}
|
|
||||||
key={item?.id}
|
|
||||||
className={`CountCard ${!showAll && index >= 6 ? "hidden" : ""}`}
|
|
||||||
>
|
|
||||||
<i>
|
|
||||||
<FaUser />
|
|
||||||
</i>
|
|
||||||
<h4>{item?.name}</h4>
|
|
||||||
<h5>
|
|
||||||
{item?.student_count} {t("models.student")}{" "}
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
{Courses?.length > 4 &&
|
|
||||||
(showAll ? (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropup />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropdown />
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
{store_course_ability && (
|
|
||||||
<Popover
|
|
||||||
content={PopoverContent}
|
|
||||||
overlayClassName="Popover"
|
|
||||||
arrow={false}
|
|
||||||
placement="bottomRight"
|
|
||||||
trigger={"click"}
|
|
||||||
>
|
|
||||||
<FaEllipsis />
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HeaderCardsSection;
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useModalState } from "../../zustand/Modal";
|
|
||||||
import { ModalEnum } from "../../enums/Model";
|
|
||||||
import { FaMoneyBill } from "react-icons/fa";
|
|
||||||
import { IoMdArrowDropdown, IoMdArrowDropup } from "react-icons/io";
|
|
||||||
|
|
||||||
const DivisionsHeaderSection = () => {
|
|
||||||
const [showAll, setShowAll] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const toggleShowAll = () => {
|
|
||||||
setShowAll(!showAll);
|
|
||||||
};
|
|
||||||
|
|
||||||
const { isOpen, setIsOpen } = useModalState((state) => state);
|
|
||||||
|
|
||||||
const handelOpenModal = () => {
|
|
||||||
setIsOpen(ModalEnum?.DIVISION_ADD);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Define the interface for your data
|
|
||||||
interface Item {
|
|
||||||
icon: JSX.Element;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
const data: Item[] = [
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات" },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="Divisions_header_section">
|
|
||||||
<div className="CountCards">
|
|
||||||
{data?.map((item: Item, index: number) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`CountCard ${!showAll && index >= 5 ? "hidden" : ""}`}
|
|
||||||
>
|
|
||||||
<i>{item?.icon}</i>
|
|
||||||
<h4>{item?.name}</h4>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
{showAll ? (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropup />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropdown />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
<button className="Add_button" onClick={handelOpenModal}>
|
|
||||||
إضافة مادة
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DivisionsHeaderSection;
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import { ModalEnum } from "../../enums/Model";
|
|
||||||
import { FaPlus, FaUser } from "react-icons/fa";
|
|
||||||
import { IoMdArrowDropdown, IoMdArrowDropup } from "react-icons/io";
|
|
||||||
import { FaEllipsis } from "react-icons/fa6";
|
|
||||||
import { Popover, Spin } from "antd";
|
|
||||||
import { useGetAllEduClass } from "../../api/eduClass";
|
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
|
||||||
import { EduClassItem } from "../../types/Item";
|
|
||||||
import useModalHandler from "../../utils/useModalHandler";
|
|
||||||
import { usePage_titleState } from "../../zustand/PageTitleState";
|
|
||||||
import { hasAbility } from "../../utils/hasAbility";
|
|
||||||
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../../enums/abilities";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
const HeaderSection = () => {
|
|
||||||
const [showAll, setShowAll] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const toggleShowAll = () => {
|
|
||||||
setShowAll(!showAll);
|
|
||||||
};
|
|
||||||
const { course_id } = useParams();
|
|
||||||
const { data, isLoading } = useGetAllEduClass({ course_id: course_id });
|
|
||||||
const eduClass = data?.data || [];
|
|
||||||
const { set_title } = usePage_titleState((state) => state);
|
|
||||||
const { handel_open_model } = useModalHandler();
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const show_eduClass_ability = hasAbility(
|
|
||||||
ABILITIES_ENUM?.EDUCATION_CLASS,
|
|
||||||
ABILITIES_VALUES_ENUM?.SHOW,
|
|
||||||
);
|
|
||||||
|
|
||||||
const handelNavigate = (item: EduClassItem) => {
|
|
||||||
if (show_eduClass_ability) {
|
|
||||||
navigate(`${item?.id}`);
|
|
||||||
set_title(`${item?.name}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
const store_eduClass_ability = hasAbility(
|
|
||||||
ABILITIES_ENUM?.EDUCATION_CLASS,
|
|
||||||
ABILITIES_VALUES_ENUM?.STORE,
|
|
||||||
);
|
|
||||||
const delete_course_ability = hasAbility(
|
|
||||||
ABILITIES_ENUM?.COURSE,
|
|
||||||
ABILITIES_VALUES_ENUM?.DELETE,
|
|
||||||
);
|
|
||||||
const store_note_ability = hasAbility(
|
|
||||||
ABILITIES_ENUM?.NOTE,
|
|
||||||
ABILITIES_VALUES_ENUM?.STORE,
|
|
||||||
);
|
|
||||||
|
|
||||||
const PopoverContent = (
|
|
||||||
<div className="PopoverContent">
|
|
||||||
{store_eduClass_ability && (
|
|
||||||
<p onClick={() => handel_open_model(ModalEnum?.EDUClASS_ADD)}>
|
|
||||||
{" "}
|
|
||||||
{t("practical.add")} {t("models.education_class")} <FaPlus />{" "}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{store_note_ability && (
|
|
||||||
<p
|
|
||||||
onClick={() => handel_open_model(ModalEnum?.COURSE_SENDNOTIFICATION)}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
{t("practical.Send_Direct_Notification")}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{delete_course_ability && (
|
|
||||||
<p onClick={() => handel_open_model(ModalEnum?.COURSE_DELETE)}>
|
|
||||||
{" "}
|
|
||||||
{t("practical.delete")} {t("models.course")}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <Spin />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="header_cards_section">
|
|
||||||
<div className="CountCards">
|
|
||||||
{eduClass?.map((item: EduClassItem, index: number) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onClick={() => handelNavigate(item)}
|
|
||||||
key={index}
|
|
||||||
className={`CountCard ${!showAll && index >= 6 ? "hidden" : ""}`}
|
|
||||||
>
|
|
||||||
<i>
|
|
||||||
<FaUser />
|
|
||||||
</i>
|
|
||||||
<h4>{item?.name}</h4>
|
|
||||||
<h5>
|
|
||||||
{item?.students_count} {t("models.student")}{" "}
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
{eduClass?.length > 4 &&
|
|
||||||
(showAll ? (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropup />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropdown />
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
<Popover
|
|
||||||
content={PopoverContent}
|
|
||||||
overlayClassName="Popover"
|
|
||||||
arrow={false}
|
|
||||||
placement="bottomRight"
|
|
||||||
>
|
|
||||||
<FaEllipsis />
|
|
||||||
</Popover>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HeaderSection;
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import { ModalEnum } from "../../enums/Model";
|
|
||||||
import { FaUser } from "react-icons/fa";
|
|
||||||
import { IoMdArrowDropdown, IoMdArrowDropup } from "react-icons/io";
|
|
||||||
import { FaEllipsis } from "react-icons/fa6";
|
|
||||||
import { Popover } from "antd";
|
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
|
||||||
import { Item } from "../../types/Item";
|
|
||||||
import useModalHandler from "../../utils/useModalHandler";
|
|
||||||
import { useButtonState } from "../../zustand/ButtonState";
|
|
||||||
import { useObjectToEdit } from "../../zustand/ObjectToEditState";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { ABILITIES_VALUES_ENUM } from "../../enums/abilities";
|
|
||||||
// import useSetPage_title from "../../Hooks/useSetPageTitle";
|
|
||||||
import { EduClassComponents } from "../../Pages/EduClass/show/ActiveTable";
|
|
||||||
import { hasAbility } from "../../utils/hasAbility";
|
|
||||||
|
|
||||||
const HeaderSection = () => {
|
|
||||||
const [showAll, setShowAll] = useState<boolean>(true);
|
|
||||||
|
|
||||||
const toggleShowAll = () => {
|
|
||||||
setShowAll(!showAll);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
// useSetPage_title(
|
|
||||||
// `${t(ABILITIES_ENUM?.MAIN_PAGE)} / ${t(`models.${ABILITIES_ENUM.COURSE}`)} / ${t(`models.${ABILITIES_ENUM.EDUCATION_CLASS}`)} / ${t(`input.details`)}`,
|
|
||||||
// );
|
|
||||||
|
|
||||||
const { handel_open_model } = useModalHandler();
|
|
||||||
|
|
||||||
const filteredComponents = EduClassComponents?.filter((component) =>
|
|
||||||
hasAbility(component.abilities, ABILITIES_VALUES_ENUM.INDEX),
|
|
||||||
);
|
|
||||||
|
|
||||||
const PopoverContent = (
|
|
||||||
<div className="PopoverContent">
|
|
||||||
<p
|
|
||||||
onClick={() => handel_open_model(ModalEnum?.EDUClASS_SENDNOTIFICATION)}
|
|
||||||
>
|
|
||||||
{" "}
|
|
||||||
{t("practical.Send_Direct_Notification")}
|
|
||||||
</p>
|
|
||||||
<p onClick={() => handel_open_model(ModalEnum?.EDUClASS_DELETE)}>
|
|
||||||
{" "}
|
|
||||||
{t("practical.delete")} {t("models.education_class")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
const [, setActiveButton] = useState(0);
|
|
||||||
const { setActiveTab, ActiveTab } = useButtonState((state) => state);
|
|
||||||
const { setParamToSend } = useObjectToEdit();
|
|
||||||
const location = useLocation();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const handleButtonClick = (index: number) => {
|
|
||||||
setActiveButton(index);
|
|
||||||
setActiveTab(index);
|
|
||||||
setParamToSend({});
|
|
||||||
navigate(`${location.pathname}`);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className="header_cards_section">
|
|
||||||
<div className="CountCards">
|
|
||||||
{filteredComponents?.map((item: Item, index: number) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
onClick={() => handleButtonClick(index)}
|
|
||||||
className={`CountCard ${!showAll && index >= 6 ? "hidden" : ""} ${ActiveTab === index ? "active" : ""} `}
|
|
||||||
>
|
|
||||||
<i>
|
|
||||||
<FaUser />
|
|
||||||
</i>
|
|
||||||
<h4> {t(`education_class_actions.${item?.name}`)} </h4>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
{filteredComponents?.length > 4 &&
|
|
||||||
(showAll ? (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropup />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="Show_More_Button" onClick={toggleShowAll}>
|
|
||||||
<IoMdArrowDropdown />
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
<Popover
|
|
||||||
content={PopoverContent}
|
|
||||||
overlayClassName="Popover"
|
|
||||||
arrow={false}
|
|
||||||
placement="bottomRight"
|
|
||||||
>
|
|
||||||
<FaEllipsis />
|
|
||||||
</Popover>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HeaderSection;
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import { Col, Row } from "reactstrap";
|
|
||||||
import React from "react";
|
|
||||||
import ValidationField from "../../../../ValidationField/ValidationField";
|
|
||||||
|
|
||||||
const AttachmentsDetails = () => {
|
|
||||||
return (
|
|
||||||
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
|
||||||
<Col xs="6" sm="6">
|
|
||||||
<ValidationField
|
|
||||||
name="attachment1"
|
|
||||||
type="DropFile"
|
|
||||||
label="school_document"
|
|
||||||
/>
|
|
||||||
{/* <ValidationField name='attachment2' type='DropFile' label='الوثيقة'/> */}
|
|
||||||
</Col>
|
|
||||||
<Col xs="6" sm="6"></Col>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AttachmentsDetails;
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
import { Col, Row } from "reactstrap";
|
|
||||||
import React from "react";
|
|
||||||
import ValidationField from "../../../../ValidationField/ValidationField";
|
|
||||||
|
|
||||||
const ContactDetails = () => {
|
|
||||||
return (
|
|
||||||
<div className="bigRow">
|
|
||||||
<ValidationField
|
|
||||||
type="number"
|
|
||||||
name="phone_number_1"
|
|
||||||
label="phone_number"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
type="number"
|
|
||||||
name="phone_number_2"
|
|
||||||
label="additional_phone_number"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
type="TextArea"
|
|
||||||
name="address"
|
|
||||||
label="address"
|
|
||||||
placeholder="address"
|
|
||||||
/>
|
|
||||||
<ValidationField
|
|
||||||
type="TextArea"
|
|
||||||
name="notes"
|
|
||||||
label="note"
|
|
||||||
placeholder="note"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ContactDetails;
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import { Col, Row } from "reactstrap";
|
|
||||||
import React, { useRef } from "react";
|
|
||||||
import ValidationField from "../../../../ValidationField/ValidationField";
|
|
||||||
|
|
||||||
const ParentDetails = () => {
|
|
||||||
const handelClick = () => {};
|
|
||||||
return (
|
|
||||||
<div className="bigRow">
|
|
||||||
<ValidationField name="father_name" label="father_name" />
|
|
||||||
|
|
||||||
<ValidationField name="father_job" label="father_job" />
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
type="number"
|
|
||||||
name="father_phone_number"
|
|
||||||
label="father_phone_number"
|
|
||||||
/>
|
|
||||||
<ValidationField name="mother_name" label="mother_name" />
|
|
||||||
|
|
||||||
<ValidationField name="mother_job" label="mother_job" />
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
type="number"
|
|
||||||
name="mother_phone_number"
|
|
||||||
label="mother_phone_number"
|
|
||||||
/>
|
|
||||||
{/* <Col xs="8" sm="8">
|
|
||||||
|
|
||||||
</Col> */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ParentDetails;
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
import { Col, Row } from "reactstrap";
|
|
||||||
import React from "react";
|
|
||||||
import ValidationField from "../../../../ValidationField/ValidationField";
|
|
||||||
import {
|
|
||||||
Sex_Select_options_Student,
|
|
||||||
nationalities,
|
|
||||||
religion_Select_options,
|
|
||||||
} from "../../../../../types/App";
|
|
||||||
|
|
||||||
const PersonalDetails = () => {
|
|
||||||
return (
|
|
||||||
<Row>
|
|
||||||
<Col xs="8" sm="8">
|
|
||||||
<ValidationField name="email" label="email" />
|
|
||||||
<div className="TowValidationItems">
|
|
||||||
<ValidationField name="first_name" label="first_name" />
|
|
||||||
<ValidationField name="last_name" label="last_name" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="TowValidationItems">
|
|
||||||
<ValidationField name="username" label="username" />
|
|
||||||
|
|
||||||
<ValidationField name="password" label="password" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="TowValidationItems">
|
|
||||||
<ValidationField
|
|
||||||
name="nationality"
|
|
||||||
type="LocalSearch"
|
|
||||||
option={nationalities}
|
|
||||||
label="nationality"
|
|
||||||
placeholder="nationality"
|
|
||||||
/>
|
|
||||||
<ValidationField
|
|
||||||
name="religion"
|
|
||||||
type="Select"
|
|
||||||
option={religion_Select_options}
|
|
||||||
no_label
|
|
||||||
placeholder="religion"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="TowValidationItems">
|
|
||||||
<ValidationField
|
|
||||||
name="birthday"
|
|
||||||
type="Date"
|
|
||||||
label="birthday"
|
|
||||||
placeholder="birthday"
|
|
||||||
/>
|
|
||||||
<ValidationField
|
|
||||||
name="birth_place"
|
|
||||||
no_label
|
|
||||||
placeholder="birth_place"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ValidationField
|
|
||||||
name="sex"
|
|
||||||
label="sex"
|
|
||||||
type="Select"
|
|
||||||
option={Sex_Select_options_Student}
|
|
||||||
placeholder="sex"
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col xs="4" sm="4">
|
|
||||||
<ValidationField name="image" type="DropFile" label="image" />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PersonalDetails;
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import Image from "../../../../Ui/Image";
|
|
||||||
import { useModalTabsState } from "../../../../../zustand/ModalTabsState";
|
|
||||||
import { useModalState } from "../../../../../zustand/Modal";
|
|
||||||
import { useFormikContext } from "formik";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
const Successful = () => {
|
|
||||||
const { setActiveTab } = useModalTabsState((state) => state);
|
|
||||||
const { setIsOpen } = useModalState((state) => state);
|
|
||||||
const formik = useFormikContext<any>();
|
|
||||||
const [t] = useTranslation();
|
|
||||||
return (
|
|
||||||
<div className="AddedSuccessfully">
|
|
||||||
<Image src="/DataState/successfully.png" />
|
|
||||||
<h1> {t("header.Student_added_successfully")} </h1>
|
|
||||||
<p>
|
|
||||||
{t(
|
|
||||||
"header.the_student_has_been_added_Do_you_want_to_add_another_student",
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="TowButton">
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
setActiveTab(0);
|
|
||||||
formik?.resetForm();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("header.Add_a_new_student")}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
setIsOpen("");
|
|
||||||
setActiveTab(0);
|
|
||||||
formik?.resetForm();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("practical.skip")}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Successful;
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
import React, { useEffect } from "react";
|
|
||||||
import { Modal } from "antd";
|
|
||||||
import { useModalState } from "../../../../../zustand/Modal";
|
|
||||||
import FormikForm from "../../../../../Layout/Dashboard/FormikForm";
|
|
||||||
import ModelBody from "./ModelBody";
|
|
||||||
import TabsSubmite from "./TabsSubmite";
|
|
||||||
import { getInitialValues, getValidationSchema } from "./formUtil";
|
|
||||||
import { ModalEnum } from "../../../../../enums/Model";
|
|
||||||
import { useAddStudent } from "../../../../../api/student";
|
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
import { useModalTabsState } from "../../../../../zustand/ModalTabsState";
|
|
||||||
|
|
||||||
const ModalForm: React.FC = () => {
|
|
||||||
const { isOpen, setIsOpen } = useModalState((state) => state);
|
|
||||||
const { mutate, isSuccess, isLoading } = useAddStudent();
|
|
||||||
const { edu_class_id } = useParams();
|
|
||||||
const handleSubmit = (values: any) => {
|
|
||||||
const Data_To_Send = { ...values };
|
|
||||||
delete Data_To_Send["id"];
|
|
||||||
|
|
||||||
Data_To_Send.attachments = [];
|
|
||||||
if (Data_To_Send.attachment1 !== null) {
|
|
||||||
Data_To_Send.attachments.push({
|
|
||||||
name: "attachment1",
|
|
||||||
file: Data_To_Send.attachment1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Data_To_Send.attachment2 !== null) {
|
|
||||||
Data_To_Send.attachments.push({
|
|
||||||
name: "attachment2",
|
|
||||||
file: Data_To_Send.attachment2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Data_To_Send["edu_class_id"] = edu_class_id;
|
|
||||||
Data_To_Send["birthday"] = values.birthday?.format(
|
|
||||||
"YYYY-MM-DD HH:mm:ss.SSS",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!values?.attachment1) {
|
|
||||||
delete Data_To_Send["attachments"];
|
|
||||||
}
|
|
||||||
// console.log(Data_To_Send);
|
|
||||||
mutate(Data_To_Send);
|
|
||||||
};
|
|
||||||
const { setActiveTab } = useModalTabsState((state) => state);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isSuccess) {
|
|
||||||
setActiveTab(4);
|
|
||||||
getInitialValues([]);
|
|
||||||
}
|
|
||||||
}, [isSuccess, setActiveTab]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal
|
|
||||||
className="AddModalForm"
|
|
||||||
centered
|
|
||||||
width={"80vw"}
|
|
||||||
footer={null}
|
|
||||||
open={isOpen === ModalEnum.STUDENT_ADD}
|
|
||||||
onOk={() => setIsOpen("")}
|
|
||||||
onCancel={() => setIsOpen("")}
|
|
||||||
>
|
|
||||||
<FormikForm
|
|
||||||
handleSubmit={handleSubmit}
|
|
||||||
initialValues={getInitialValues([])}
|
|
||||||
validationSchema={getValidationSchema}
|
|
||||||
>
|
|
||||||
<ModelBody />
|
|
||||||
<TabsSubmite isLoading={isLoading} steps={4} />
|
|
||||||
</FormikForm>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModalForm;
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
import PersonalDetails from "../Form/PersonalDetails";
|
|
||||||
import TabsBar from "../../../../Layout/Tabs/TabsBar";
|
|
||||||
import ActiveTabs from "../../../../Layout/Tabs/ActiveTabs";
|
|
||||||
import { usePage_titleState } from "../../../../../zustand/PageTitleState";
|
|
||||||
import ParentDetails from "../Form/ParentDetails";
|
|
||||||
import ContactDetails from "../Form/ContactDetails";
|
|
||||||
import AttachmentsDetails from "../Form/AttachmentsDetails";
|
|
||||||
import Successful from "../Form/Successful";
|
|
||||||
import { useModalState } from "../../../../../zustand/Modal";
|
|
||||||
import { useFormikContext } from "formik";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
const ModelBody = () => {
|
|
||||||
const { title } = usePage_titleState((state) => state);
|
|
||||||
const [t] = useTranslation();
|
|
||||||
const steps = [
|
|
||||||
{
|
|
||||||
title: `${t(`practical.Step`)} 1`,
|
|
||||||
description: t("header.Student_Information"),
|
|
||||||
component: <PersonalDetails />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: `${t(`practical.Step`)} 2`,
|
|
||||||
description: t("header.Parent_Information"),
|
|
||||||
component: <ParentDetails />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: `${t(`practical.Step`)} 3`,
|
|
||||||
description: t("header.Contact_Information"),
|
|
||||||
component: <ContactDetails />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: `${t(`practical.Step`)} 4`,
|
|
||||||
description: t("header.Attachment_Images"),
|
|
||||||
component: <AttachmentsDetails />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "hidden",
|
|
||||||
description: "hidden",
|
|
||||||
hidden: true,
|
|
||||||
component: <Successful />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const { isOpen } = useModalState((state) => state);
|
|
||||||
const formik = useFormikContext();
|
|
||||||
useEffect(() => {
|
|
||||||
formik.setErrors({});
|
|
||||||
}, [isOpen === ""]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="ModelBody">
|
|
||||||
<TabsBar steps={steps} />
|
|
||||||
<div className="ModelBodyForm">
|
|
||||||
<header>
|
|
||||||
{" "}
|
|
||||||
{t("practical.add")} {t("models.student")}{" "}
|
|
||||||
{" " + title === null ? "" : title}{" "}
|
|
||||||
</header>
|
|
||||||
<ActiveTabs steps={steps} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModelBody;
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
import React, { useEffect } from "react";
|
|
||||||
import { useModalTabsState } from "../../../../../zustand/ModalTabsState";
|
|
||||||
import { useModalState } from "../../../../../zustand/Modal";
|
|
||||||
import { useFormikContext } from "formik";
|
|
||||||
import { toast } from "react-toastify";
|
|
||||||
import { Spin } from "antd";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
interface TabsSubmiteProps {
|
|
||||||
steps: number;
|
|
||||||
isLoading: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TabsSubmite: React.FC<TabsSubmiteProps> = ({ steps, isLoading }) => {
|
|
||||||
const { values, isValid, submitForm } = useFormikContext<any>();
|
|
||||||
|
|
||||||
const { ActiveTab, setActiveTab } = useModalTabsState((state) => state);
|
|
||||||
const IsSubmite = ActiveTab + 1 !== steps;
|
|
||||||
const {
|
|
||||||
first_name,
|
|
||||||
last_name,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
nationality,
|
|
||||||
religion,
|
|
||||||
birthday,
|
|
||||||
birth_place,
|
|
||||||
sex,
|
|
||||||
} = values;
|
|
||||||
|
|
||||||
const {
|
|
||||||
father_name,
|
|
||||||
father_job,
|
|
||||||
father_phone_number,
|
|
||||||
mother_name,
|
|
||||||
mother_job,
|
|
||||||
mother_phone_number,
|
|
||||||
} = values;
|
|
||||||
|
|
||||||
const { address, attachment1 } = values;
|
|
||||||
|
|
||||||
const is_1_valued =
|
|
||||||
first_name &&
|
|
||||||
username &&
|
|
||||||
last_name &&
|
|
||||||
password &&
|
|
||||||
nationality &&
|
|
||||||
religion &&
|
|
||||||
birthday &&
|
|
||||||
birth_place &&
|
|
||||||
sex;
|
|
||||||
const is_2_valued =
|
|
||||||
father_name &&
|
|
||||||
father_job &&
|
|
||||||
father_phone_number &&
|
|
||||||
mother_name &&
|
|
||||||
mother_job &&
|
|
||||||
mother_phone_number;
|
|
||||||
const is_3_valued = address;
|
|
||||||
const is_4_valued = attachment1;
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
|
||||||
function handelNext() {
|
|
||||||
// console.log("submited");
|
|
||||||
// console.log(isValid,"isValid");
|
|
||||||
|
|
||||||
if (!is_1_valued && Number(ActiveTab) === 0) {
|
|
||||||
toast.error(t("validation.pleas_fill_all_label"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!is_2_valued && Number(ActiveTab) === 1) {
|
|
||||||
toast.error(t("validation.pleas_fill_all_label"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!is_3_valued && Number(ActiveTab) === 2) {
|
|
||||||
toast.error(t("validation.pleas_fill_all_label"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!is_4_valued && Number(ActiveTab) === 3) {
|
|
||||||
toast.error(t("validation.pleas_fill_all_label"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Number(ActiveTab) >= steps) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setActiveTab(Number(ActiveTab) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handelPre() {
|
|
||||||
setActiveTab(Number(ActiveTab) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
if (isValid) {
|
|
||||||
submitForm();
|
|
||||||
} else {
|
|
||||||
submitForm();
|
|
||||||
// console.log('Validation errors:', formik.errors);
|
|
||||||
// setActiveTab(4)
|
|
||||||
toast.error(t("validation.pleas_fill_all_label"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// console.log(ActiveTab,"ActiveTab");
|
|
||||||
|
|
||||||
if (ActiveTab === steps) {
|
|
||||||
return <></>;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="SubmitButton">
|
|
||||||
<div onClick={handelPre}>
|
|
||||||
{ActiveTab > 0 ? "رجوع للخطوة السابقة" : ""}
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
onClick={isLoading ? undefined : IsSubmite ? handelNext : handleSubmit}
|
|
||||||
{...(!IsSubmite && !isLoading ? { type: "submit" } : {})}
|
|
||||||
>
|
|
||||||
{isLoading
|
|
||||||
? "جار الاضافة ...."
|
|
||||||
: IsSubmite
|
|
||||||
? "الخطوة التالية"
|
|
||||||
: "إضافة الطالب"}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TabsSubmite;
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
import * as Yup from "yup";
|
|
||||||
|
|
||||||
export const getInitialValues = (objectToEdit: any): any => {
|
|
||||||
return {
|
|
||||||
id: objectToEdit?.id ?? null,
|
|
||||||
// username:objectToEdit?.username ?? null ,
|
|
||||||
email: objectToEdit?.email ?? "",
|
|
||||||
username: objectToEdit?.username ?? null,
|
|
||||||
|
|
||||||
password: objectToEdit?.password ?? null,
|
|
||||||
notes: objectToEdit?.notes ?? null,
|
|
||||||
image: objectToEdit?.image ?? null,
|
|
||||||
nationality: objectToEdit?.nationality ?? null,
|
|
||||||
birth_place: objectToEdit?.birth_place ?? null,
|
|
||||||
birthday: objectToEdit?.birthday ?? null,
|
|
||||||
phone_number_2: objectToEdit?.phone_number_2 ?? null,
|
|
||||||
phone_number_1: objectToEdit?.phone_number_1 ?? null,
|
|
||||||
mother_name: objectToEdit?.mother_name ?? null,
|
|
||||||
father_name: objectToEdit?.father_name ?? null,
|
|
||||||
last_name: objectToEdit?.last_name ?? null,
|
|
||||||
first_name: objectToEdit?.first_name ?? null,
|
|
||||||
religion: objectToEdit?.religion ?? null,
|
|
||||||
attachments: objectToEdit?.attachments ?? null,
|
|
||||||
attachment1: objectToEdit?.attachment1 ?? null,
|
|
||||||
attachment2: objectToEdit?.attachment2 ?? null,
|
|
||||||
address: objectToEdit?.address ?? null,
|
|
||||||
|
|
||||||
father_job: objectToEdit?.father_job ?? null,
|
|
||||||
mother_phone_number: objectToEdit?.mother_phone_number ?? null,
|
|
||||||
father_phone_number: objectToEdit?.father_phone_number ?? null,
|
|
||||||
mother_job: objectToEdit?.mother_job ?? null,
|
|
||||||
edu_class_id: objectToEdit?.edu_class_id ?? null,
|
|
||||||
sex: objectToEdit?.sex ?? null,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getValidationSchema = () => {
|
|
||||||
return Yup.object().shape({
|
|
||||||
// username: Yup.string().required('Username is required'),
|
|
||||||
email: Yup.string().email("validation.Invalid_email"),
|
|
||||||
username: Yup.string().required("validation.required"),
|
|
||||||
// .required("validation.Email_is_required"),
|
|
||||||
password: Yup.string()
|
|
||||||
.required("validation.Password_is_required")
|
|
||||||
.min(8, "validation.Password_must_be_at_least_8_characters_long"),
|
|
||||||
// notes: Yup.string(),
|
|
||||||
// image: Yup.string().required(),
|
|
||||||
nationality: Yup.string().required("validation.Nationality_is_required"),
|
|
||||||
address: Yup.string().required("validation.Address_is_required"),
|
|
||||||
|
|
||||||
birth_place: Yup.string().required("validation.Place_of_birth_is_required"),
|
|
||||||
birthday: Yup.string().required("validation.Date_of_birth_is_required"),
|
|
||||||
// phone_number_2: Yup.number(),
|
|
||||||
// phone_number_1: Yup.number(),
|
|
||||||
mother_name: Yup.string().required("validation.Mother's_name_is_required"),
|
|
||||||
father_name: Yup.string().required("validation.Father's_name_is_required"),
|
|
||||||
last_name: Yup.string().required("validation.Last_name_is_required"),
|
|
||||||
first_name: Yup.string().required("validation.First_name_is_required"),
|
|
||||||
religion: Yup.string().required("validation.Religion_is_required"),
|
|
||||||
sex: Yup.string().required("validation.Gender_is_required"),
|
|
||||||
|
|
||||||
// attachments: Yup.string(),
|
|
||||||
// attachment1: Yup.string(),
|
|
||||||
// attachment2: Yup.string(),
|
|
||||||
// attachment1: Yup.string().required("validation.Attachment1_is_required"),
|
|
||||||
|
|
||||||
father_job: Yup.string().required("validation.Father's_job_is_required"),
|
|
||||||
// mother_phone_number: Yup.string().required(
|
|
||||||
// "validation.Mother's_phone_number_is_required",
|
|
||||||
// ),
|
|
||||||
father_phone_number: Yup.string().required(
|
|
||||||
"validation.Father's_phone_number_is_required",
|
|
||||||
),
|
|
||||||
// mother_job: Yup.string().required("validation.Mother's_job_is_required"),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import React, { useState, ReactNode } from "react";
|
|
||||||
import type { DrawerProps } from "antd";
|
|
||||||
import { Drawer, Space } from "antd";
|
|
||||||
|
|
||||||
interface WithDrawerProps {
|
|
||||||
button: React.ReactNode;
|
|
||||||
children: ReactNode;
|
|
||||||
title: string;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const WithDrawer: React.FC<WithDrawerProps> = ({
|
|
||||||
button,
|
|
||||||
children,
|
|
||||||
title = "Basic Drawer",
|
|
||||||
className,
|
|
||||||
}) => {
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const [placement, setPlacement] = useState<DrawerProps["placement"]>("right");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Space>
|
|
||||||
{React.cloneElement(button as React.ReactElement, {
|
|
||||||
onClick: () => setOpen(true),
|
|
||||||
})}
|
|
||||||
</Space>
|
|
||||||
<Drawer
|
|
||||||
title={title}
|
|
||||||
placement={placement}
|
|
||||||
closable={false}
|
|
||||||
onClose={() => setOpen(false)}
|
|
||||||
open={open}
|
|
||||||
key={placement}
|
|
||||||
>
|
|
||||||
<div className={className}>{children}</div>
|
|
||||||
</Drawer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WithDrawer;
|
|
||||||
|
|
||||||
// <WithDrawer
|
|
||||||
// button={<Button type="primary">Open</Button>}
|
|
||||||
// >
|
|
||||||
// {/* Your content goes here */}
|
|
||||||
// </WithDrawer>
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
import { Form, Formik } from "formik";
|
|
||||||
import React from "react";
|
|
||||||
import * as Yup from "yup";
|
|
||||||
|
|
||||||
const WithFormik = ({ children }: any) => {
|
|
||||||
const getInitialValues = () => {
|
|
||||||
return { name: "" };
|
|
||||||
};
|
|
||||||
const getValidationSchema = () => {
|
|
||||||
return Yup.object().shape({});
|
|
||||||
};
|
|
||||||
const handleSubmit = () => {};
|
|
||||||
return (
|
|
||||||
<div className="WithFormik">
|
|
||||||
{
|
|
||||||
<Formik
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
initialValues={getInitialValues}
|
|
||||||
validationSchema={getValidationSchema}
|
|
||||||
>
|
|
||||||
{(formik) => <Form>{children}</Form>}
|
|
||||||
</Formik>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WithFormik;
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
|
||||||
|
|
||||||
// This is your Layout Component
|
|
||||||
const Visibale = ({ children, ...props }: any) => {
|
|
||||||
const ref = useRef<any>();
|
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const observer = new IntersectionObserver(([entry]) => {
|
|
||||||
if (isVisible === false) {
|
|
||||||
setIsVisible(entry.isIntersecting);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (ref.current) {
|
|
||||||
observer.observe(ref.current);
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
if (ref.current) {
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
observer.unobserve(ref.current);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [isVisible]); // Empty array ensures effect is only run on mount and unmount
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={ref} {...props}>
|
|
||||||
{isVisible && children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Visibale;
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import Image from "../Ui/Image";
|
|
||||||
|
|
||||||
const ActivitySection = () => {
|
|
||||||
// Static fake data array
|
|
||||||
const ActivitysData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
image: "/Image/1.png",
|
|
||||||
info: "3 طالبات حصلوا على جائزة في مسابقة الشطرنج",
|
|
||||||
time: "منذ 3 ساعات",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
image: "/Image/1.png",
|
|
||||||
info: "3 طالبات حصلوا على جائزة في مسابقة الشطرنج",
|
|
||||||
time: "منذ 3 ساعات",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
image: "/Image/1.png",
|
|
||||||
info: "3 طالبات حصلوا على جائزة في مسابقة الشطرنج",
|
|
||||||
time: "منذ 3 ساعات",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
image: "/Image/1.png",
|
|
||||||
info: "3 طالبات حصلوا على جائزة في مسابقة الشطرنج",
|
|
||||||
time: "منذ 3 ساعات",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
image: "/Image/1.png",
|
|
||||||
info: "3 طالبات حصلوا على جائزة في مسابقة الشطرنج",
|
|
||||||
time: "منذ 3 ساعات",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="ActivitySection">
|
|
||||||
<header>
|
|
||||||
<h4>النشاط الطلابي </h4>
|
|
||||||
</header>
|
|
||||||
<div className="ActivityScrollerChanger">
|
|
||||||
<div className="Activitys">
|
|
||||||
{ActivitysData.map((Activity) => (
|
|
||||||
<article key={Activity.id}>
|
|
||||||
<Image src={Activity.image} />
|
|
||||||
<h5>{Activity.info}</h5>
|
|
||||||
<p>{Activity?.time}</p>
|
|
||||||
</article>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ActivitySection;
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import "dayjs/locale/zh-cn";
|
|
||||||
import type { Dayjs } from "dayjs";
|
|
||||||
import dayLocaleData from "dayjs/plugin/localeData";
|
|
||||||
import {
|
|
||||||
Calendar,
|
|
||||||
Col,
|
|
||||||
DatePicker,
|
|
||||||
Popover,
|
|
||||||
Radio,
|
|
||||||
Row,
|
|
||||||
Select,
|
|
||||||
Typography,
|
|
||||||
theme,
|
|
||||||
} from "antd";
|
|
||||||
import type { CalendarProps } from "antd";
|
|
||||||
import { IoMdArrowDropdown } from "react-icons/io";
|
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
|
||||||
import { RiDeleteBin6Fill } from "react-icons/ri";
|
|
||||||
|
|
||||||
dayjs.extend(dayLocaleData);
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
|
||||||
const [year, setYear] = useState<number>(dayjs().year());
|
|
||||||
const [month, setMonth] = useState<number>(dayjs().month());
|
|
||||||
const onChangeDatePicker = (value: any) => {
|
|
||||||
if (value) {
|
|
||||||
setYear(value.$y); // Extract year from the selected date and update the year state
|
|
||||||
setMonth(value.$M); // Extract month from the selected date and update the month state
|
|
||||||
} else {
|
|
||||||
const today = dayjs(); // Get the current date
|
|
||||||
setYear(today.year()); // Update the year state to the current year
|
|
||||||
setMonth(today.month());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const popoverDays = [
|
|
||||||
{
|
|
||||||
day: 10,
|
|
||||||
month: 3,
|
|
||||||
year: 2024,
|
|
||||||
title: "مسابقة الشطرنج الدولية",
|
|
||||||
time: "الساعة 11",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
day: 22,
|
|
||||||
month: 3,
|
|
||||||
year: 2024,
|
|
||||||
title: "مسابقة الشطرنج الدولية",
|
|
||||||
time: "الساعة 12",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [actionsVisible, setActionsVisible] = useState(0);
|
|
||||||
|
|
||||||
const toggleActionsVisibility = (day: number) => {
|
|
||||||
setActionsVisible(day);
|
|
||||||
};
|
|
||||||
const dateCellRender = (value: dayjs.Dayjs) => {
|
|
||||||
const day = value.date();
|
|
||||||
const month = value.month() + 1;
|
|
||||||
const year = value.year();
|
|
||||||
|
|
||||||
const matchingDay = popoverDays.find(
|
|
||||||
(date) => date.day === day && date.month === month && date.year === year,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (matchingDay) {
|
|
||||||
return (
|
|
||||||
<Popover
|
|
||||||
placement="top"
|
|
||||||
className="CalenderPop"
|
|
||||||
rootClassName="CalenderPop"
|
|
||||||
trigger="hover"
|
|
||||||
content={
|
|
||||||
<div
|
|
||||||
className="Calendar_Popover"
|
|
||||||
onClick={() => toggleActionsVisibility(day)}
|
|
||||||
>
|
|
||||||
<h5>{matchingDay.title}</h5>
|
|
||||||
<h6>{matchingDay.time}</h6>
|
|
||||||
{actionsVisible === day && ( // Only show actions if actionsVisible is true
|
|
||||||
<span className="Actions">
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
<RiDeleteBin6Fill size={22} style={{ color: "#C11313" }} />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
// open={true}
|
|
||||||
>
|
|
||||||
<div className="Calendar_ActiveDiv">{day}</div>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className="Calendar_Div">{day}</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={"CalendarSection"}>
|
|
||||||
<Calendar
|
|
||||||
fullscreen={false}
|
|
||||||
fullCellRender={dateCellRender}
|
|
||||||
value={dayjs(`${year}-${month + 1}-01`)}
|
|
||||||
headerRender={() => {
|
|
||||||
return (
|
|
||||||
<div className="CalendarHeader">
|
|
||||||
<h4>تقويم المدرسة</h4>
|
|
||||||
<DatePicker
|
|
||||||
suffixIcon={<IoMdArrowDropdown size={30} />}
|
|
||||||
onChange={(newDate: number) => onChangeDatePicker(newDate)}
|
|
||||||
picker="month"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { FaMoneyBill } from "react-icons/fa";
|
|
||||||
import Image from "../Ui/Image";
|
|
||||||
|
|
||||||
const CountSection = () => {
|
|
||||||
const data = [
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات", number: 900 },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات", number: 900 },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات", number: 900 },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات", number: 900 },
|
|
||||||
{ icon: <FaMoneyBill />, name: "الطالبات", number: 900 },
|
|
||||||
];
|
|
||||||
return (
|
|
||||||
<div className="CountSection">
|
|
||||||
<div className="CountCards">
|
|
||||||
{data?.map((item: any, index: any) => {
|
|
||||||
return (
|
|
||||||
<div key={index} className="CountCard">
|
|
||||||
<i>{item?.icon}</i>
|
|
||||||
<h4>{item?.name}</h4>
|
|
||||||
<h6>{item?.number}</h6>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<Image src="../Home/HomeCounter.png" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CountSection;
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { FaMoneyBill } from "react-icons/fa";
|
|
||||||
|
|
||||||
const NoteSection = () => {
|
|
||||||
// Static fake data array
|
|
||||||
const notesData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
icon: <FaMoneyBill />,
|
|
||||||
title: "ملاحظة مالية",
|
|
||||||
content: [
|
|
||||||
"الرسوم الدراسية: المبلغ المطلوب من الأهل 200000 ل.س",
|
|
||||||
"مبلغ أخر: المبلغ المطلوب من الأهل 300000 ل.س",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
icon: <FaMoneyBill />,
|
|
||||||
title: "ملاحظة مالية",
|
|
||||||
content: [
|
|
||||||
"الرسوم الدراسية: المبلغ المطلوب من الأهل 200000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
icon: <FaMoneyBill />,
|
|
||||||
title: "ملاحظة مالية",
|
|
||||||
content: [
|
|
||||||
"الرسوم الدراسية: المبلغ المطلوب من الأهل 200000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
icon: <FaMoneyBill />,
|
|
||||||
title: "ملاحظة مالية",
|
|
||||||
content: [
|
|
||||||
"الرسوم الدراسية: المبلغ المطلوب من الأهل 200000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
icon: <FaMoneyBill />,
|
|
||||||
title: "ملاحظة مالية",
|
|
||||||
content: [
|
|
||||||
"الرسوم الدراسية: المبلغ المطلوب من الأهل 200000 ل.س",
|
|
||||||
"تكلفة أخرى: المبلغ المطلوب من الأهل 150000 ل.س",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="NoteSection">
|
|
||||||
<header>
|
|
||||||
<h4>ملاحظات اليوم</h4> <h6>8/3/2021</h6>
|
|
||||||
</header>
|
|
||||||
<div className="NoteScrollerChanger">
|
|
||||||
<div className="Notes">
|
|
||||||
{notesData.map((note) => (
|
|
||||||
<article key={note.id}>
|
|
||||||
<div>
|
|
||||||
<i>{note.icon}</i>
|
|
||||||
<h5>{note.title}</h5>
|
|
||||||
</div>
|
|
||||||
{note.content.map((item, index) => (
|
|
||||||
<span key={index}>{item}</span>
|
|
||||||
))}
|
|
||||||
</article>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NoteSection;
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
import { Progress, Select } from "antd";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { FaLaptop } from "react-icons/fa";
|
|
||||||
import { IoMdArrowDropdown } from "react-icons/io";
|
|
||||||
import Image from "../Ui/Image";
|
|
||||||
|
|
||||||
const StudentSubjects = () => {
|
|
||||||
const [selectedOption, setSelectedOption] = useState("هذا الأسبوع");
|
|
||||||
const Options = [
|
|
||||||
{ value: "هذا الأسبوع", label: "هذا الأسبوع" },
|
|
||||||
{ value: "الأسبوع الماضي", label: "الأسبوع الماضي" },
|
|
||||||
{ value: "الشهر الماضي", label: "الشهر الماضي" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleChangeSelect = (value: any) => {
|
|
||||||
setSelectedOption(value);
|
|
||||||
// console.log(`Selected ${value}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
// Define static data
|
|
||||||
const staticData = [
|
|
||||||
{
|
|
||||||
SubjectImage: "/Subject/algebra.png",
|
|
||||||
SubjectName: "طالبات",
|
|
||||||
StudentSubjectsPercent: 50,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
SubjectImage: "/Subject/flask.png",
|
|
||||||
SubjectName: "طالبات",
|
|
||||||
StudentSubjectsPercent: 60,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
SubjectImage: "/Subject/koran.png",
|
|
||||||
SubjectName: "طالبات",
|
|
||||||
StudentSubjectsPercent: 70,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="StudentSubjects">
|
|
||||||
<header>
|
|
||||||
<h6>{t("عدد الطالبات")}</h6>
|
|
||||||
<Select
|
|
||||||
defaultValue={selectedOption}
|
|
||||||
onChange={handleChangeSelect}
|
|
||||||
suffixIcon={<IoMdArrowDropdown size={30} />}
|
|
||||||
options={Options}
|
|
||||||
/>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
{staticData.map((item, index) => (
|
|
||||||
<div key={index}>
|
|
||||||
<Progress
|
|
||||||
type="circle"
|
|
||||||
size={"small"}
|
|
||||||
strokeColor={"#0052B4"}
|
|
||||||
strokeWidth={7}
|
|
||||||
percent={item?.StudentSubjectsPercent}
|
|
||||||
/>
|
|
||||||
<h6>{item.SubjectName}</h6>
|
|
||||||
<Image src={item?.SubjectImage} />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StudentSubjects;
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { Spin } from 'antd'
|
import { Spin } from "antd";
|
||||||
|
|
||||||
const SpinContainer = () => {
|
const SpinContainer = () => {
|
||||||
return (
|
return (
|
||||||
<div className='SpinContainer'>
|
<div className="SpinContainer">
|
||||||
<Spin/>
|
<Spin />
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default SpinContainer
|
export default SpinContainer;
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import { Col, Row } from "reactstrap";
|
|
||||||
import React from "react";
|
|
||||||
import ValidationField from "../../../../Components/ValidationField/ValidationField";
|
|
||||||
|
|
||||||
const Form = () => {
|
|
||||||
return (
|
|
||||||
<Row>
|
|
||||||
<Col xs="8" sm="8">
|
|
||||||
{" "}
|
|
||||||
{/* This column will take up 8 units on extra small screens and 6 units on small screens */}
|
|
||||||
<ValidationField name="الجنس" />
|
|
||||||
<ValidationField name="الاسم الأول *" />
|
|
||||||
<ValidationField name="اسم العائلة" />
|
|
||||||
<div className="TowValidationItems">
|
|
||||||
<ValidationField name="اسم العائلة" />
|
|
||||||
<ValidationField name="اسم العائلة" no_label />
|
|
||||||
</div>
|
|
||||||
<div className="TowValidationItems">
|
|
||||||
<ValidationField name="اسم العائلة" type="Select" option={[]} />
|
|
||||||
<ValidationField name="اسم العائلة" />
|
|
||||||
</div>
|
|
||||||
{/* <div className='TowValidationItems'>
|
|
||||||
<ValidationField name='اسم العائلة'/>
|
|
||||||
<ValidationField name='اسم العائلة' no_label/>
|
|
||||||
</div>
|
|
||||||
<div className='TowValidationItems'>
|
|
||||||
<ValidationField name='اسم العائلة'/>
|
|
||||||
<ValidationField name='اسم العائلة' no_label/>
|
|
||||||
</div> */}
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col xs="4" sm="4">
|
|
||||||
{" "}
|
|
||||||
{/* This column will take up 4 units on extra small screens and 6 units on small screens */}
|
|
||||||
<ValidationField name="DropFile" type="DropFile" label="الصورة *" />
|
|
||||||
<ValidationField
|
|
||||||
name="DropFile"
|
|
||||||
type="DropFile"
|
|
||||||
label="الوثيقة المدرسية *"
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Form;
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import { Modal } from "antd";
|
|
||||||
import { useModalState } from "../../../../zustand/Modal";
|
|
||||||
import FormikForm from "../../../../Layout/Dashboard/FormikForm";
|
|
||||||
import * as Yup from "yup";
|
|
||||||
import ModelBody from "./ModelBody";
|
|
||||||
import TabsSubmite from "../../../../Components/Layout/Tabs/TabsSubmite";
|
|
||||||
import { getInitialValues, getValidationSchema } from "./formUtil";
|
|
||||||
import { ModalEnum } from "../../../../enums/Model";
|
|
||||||
|
|
||||||
const ModalForm: React.FC = () => {
|
|
||||||
const { isOpen, setIsOpen } = useModalState((state) => state);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal
|
|
||||||
className="AddModalForm"
|
|
||||||
centered
|
|
||||||
width={"80vw"}
|
|
||||||
footer={null}
|
|
||||||
open={isOpen === ModalEnum.STUDENT_ADD}
|
|
||||||
onOk={() => setIsOpen("")}
|
|
||||||
onCancel={() => setIsOpen("")}
|
|
||||||
>
|
|
||||||
<FormikForm
|
|
||||||
handleSubmit={() => {}}
|
|
||||||
initialValues={getInitialValues}
|
|
||||||
validationSchema={getValidationSchema}
|
|
||||||
>
|
|
||||||
<ModelBody />
|
|
||||||
{/* <TabsSubmite steps={5} /> */}
|
|
||||||
</FormikForm>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModalForm;
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
import { Divider, Steps } from "antd";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useTabsState } from "../../../../zustand/TabsState";
|
|
||||||
import { useModalTabsState } from "../../../../zustand/ModalTabsState";
|
|
||||||
import Form from "./Form";
|
|
||||||
import TabsBar from "../../../../Components/Layout/Tabs/TabsBar";
|
|
||||||
import ActiveTabs from "../../../../Components/Layout/Tabs/ActiveTabs";
|
|
||||||
|
|
||||||
const ModelBody = () => {
|
|
||||||
const { ActiveTab, setActiveTab } = useModalTabsState((state) => state);
|
|
||||||
function handelTabClick(index: number) {
|
|
||||||
setActiveTab(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
const steps = [
|
|
||||||
{
|
|
||||||
title: "الخطوة 1",
|
|
||||||
description: "التفاصيل الشخصية",
|
|
||||||
component: <Form />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "الخطوة 2",
|
|
||||||
description: "التفاصيل الشخصية",
|
|
||||||
component: <>H2</>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "الخطوة 3",
|
|
||||||
description: "التفاصيل الشخصية",
|
|
||||||
component: <>H2</>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "الخطوة 4",
|
|
||||||
description: "التفاصيل الشخصية",
|
|
||||||
component: <>H2</>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "الخطوة 5",
|
|
||||||
description: "التفاصيل الشخصية",
|
|
||||||
component: <>H2</>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "الخطوة 5",
|
|
||||||
description: "التفاصيل الشخصية",
|
|
||||||
component: <>H2</>,
|
|
||||||
hidden: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="ModelBody">
|
|
||||||
<TabsBar steps={steps} />
|
|
||||||
<div className="ModelBodyForm">
|
|
||||||
<header>إضافة طالب</header>
|
|
||||||
<ActiveTabs steps={steps} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModelBody;
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import * as Yup from "yup";
|
|
||||||
|
|
||||||
export const getInitialValues = (objectToEdit: any): any => {
|
|
||||||
return {
|
|
||||||
id: objectToEdit?.id ?? 0,
|
|
||||||
name: objectToEdit?.name ?? "",
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getValidationSchema = () => {
|
|
||||||
// validate input
|
|
||||||
return Yup.object().shape({
|
|
||||||
name: Yup.string().required("مطلوب"),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { FaMoneyBill } from "react-icons/fa";
|
|
||||||
import Image from "../Ui/Image";
|
|
||||||
|
|
||||||
const CountSection = () => {
|
|
||||||
return (
|
|
||||||
<div className="CountSection">
|
|
||||||
<div className="CountCards">
|
|
||||||
{[1, 2, 3, 4, 5]?.map((item: any, index: any) => {
|
|
||||||
return (
|
|
||||||
<div key={index} className="CountCard">
|
|
||||||
<i>
|
|
||||||
<FaMoneyBill />
|
|
||||||
</i>
|
|
||||||
<h4>الطالبات</h4>
|
|
||||||
<h6>932</h6>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
{/* <Image src='../Home/HomeCounter.png'/> */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CountSection;
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { FaChalkboardTeacher } from "react-icons/fa";
|
|
||||||
import { IoSchool } from "react-icons/io5";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
const DetailsCard = () => {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const handelclick = () => {
|
|
||||||
navigate("/student/add");
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className="DetailsCard" onClick={() => handelclick()}>
|
|
||||||
<h6>إضافة طالب</h6>
|
|
||||||
<div>
|
|
||||||
<IoSchool />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DetailsCard;
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
import { Select } from "antd";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { FaLaptop } from "react-icons/fa";
|
|
||||||
import { IoMdArrowDropdown } from "react-icons/io";
|
|
||||||
|
|
||||||
const StudentCount = () => {
|
|
||||||
const [selectedOption, setSelectedOption] = useState("هذا الأسبوع");
|
|
||||||
const Options = [
|
|
||||||
{ value: "هذا الأسبوع", label: "هذا الأسبوع" },
|
|
||||||
{ value: "الأسبوع الماضي", label: "الأسبوع الماضي" },
|
|
||||||
{ value: "الشهر الماضي", label: "الشهر الماضي" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleChangeSelect = (value: any) => {
|
|
||||||
setSelectedOption(value);
|
|
||||||
// console.log(`Selected ${value}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
// Define static data
|
|
||||||
const staticData = [
|
|
||||||
{ studentName: "طالبات الشعبة الأولى 1", studentCount: 50 },
|
|
||||||
{ studentName: "طالبات الشعبة الأولى 2", studentCount: 60 },
|
|
||||||
{ studentName: "طالبات الشعبة الأولى 3", studentCount: 70 },
|
|
||||||
{ studentName: "طالبات الشعبة الأولى 4", studentCount: 80 },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="StudentCount">
|
|
||||||
<header>
|
|
||||||
<h6>{t("عدد الطالبات")}</h6>
|
|
||||||
<Select
|
|
||||||
defaultValue={selectedOption}
|
|
||||||
onChange={handleChangeSelect}
|
|
||||||
suffixIcon={<IoMdArrowDropdown size={30} />}
|
|
||||||
options={Options}
|
|
||||||
/>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
{staticData.map((item, index) => (
|
|
||||||
<div key={index}>
|
|
||||||
<span>
|
|
||||||
<h6>{item.studentName}</h6>
|
|
||||||
<p>{item.studentCount} طالب</p>
|
|
||||||
</span>
|
|
||||||
<FaLaptop />
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StudentCount;
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { FaMoneyBill } from "react-icons/fa";
|
|
||||||
import Image from "../../Ui/Image";
|
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
|
||||||
import { useGetOverView } from "../../../api/payment";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { Currency } from "../../../config/AppKey";
|
|
||||||
import { formatNumber } from "../../../utils/formatNumber";
|
|
||||||
|
|
||||||
const MoneyState = () => {
|
|
||||||
const navigation = useNavigate();
|
|
||||||
const { student_id } = useParams();
|
|
||||||
const handelnavigate = () => {
|
|
||||||
navigation(`payment`);
|
|
||||||
};
|
|
||||||
const { data } = useGetOverView({
|
|
||||||
student_id: student_id,
|
|
||||||
});
|
|
||||||
const [t] = useTranslation();
|
|
||||||
const to_be_paid = Number(data?.data?.to_be_paid) || 0;
|
|
||||||
const paid = Number(data?.data?.paid) || 0;
|
|
||||||
|
|
||||||
const dues = formatNumber(to_be_paid - paid);
|
|
||||||
return (
|
|
||||||
<div className="MoneyState">
|
|
||||||
<header>{t("header.The_student_financial_situation")}</header>
|
|
||||||
<main>
|
|
||||||
<button>
|
|
||||||
{t("select.Payments.dues")} : {dues} {Currency}
|
|
||||||
</button>
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<FaMoneyBill />
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
<h6>{t("select.Payments.to_be_paid")}</h6>
|
|
||||||
<p>
|
|
||||||
{formatNumber(to_be_paid)} {Currency}
|
|
||||||
</p>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<article>
|
|
||||||
<span onClick={handelnavigate}>
|
|
||||||
<Image src="/Icon/cash.png" />
|
|
||||||
<h5>{t("models.payment")}</h5>
|
|
||||||
<button>{t("practical.details")}</button>
|
|
||||||
</span>
|
|
||||||
</article>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MoneyState;
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
|
|
||||||
function FakeIntegration() {
|
|
||||||
const [integrationInput, setIntegrationInput] = useState("");
|
|
||||||
const [integrationResult, setIntegrationResult] = useState("");
|
|
||||||
|
|
||||||
const handleSubmit = (event: any) => {
|
|
||||||
event.preventDefault();
|
|
||||||
// Simulated integration result
|
|
||||||
const fakeResult = "∫(x^2)dx = (1/3)x^3 + C";
|
|
||||||
setIntegrationResult(fakeResult);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={integrationInput}
|
|
||||||
onChange={(e) => setIntegrationInput(e.target.value)}
|
|
||||||
placeholder="Enter integration expression"
|
|
||||||
/>
|
|
||||||
<button type="submit">Calculate</button>
|
|
||||||
</form>
|
|
||||||
<div>
|
|
||||||
<h2>Integration Input:</h2>
|
|
||||||
<p>{integrationInput}</p>
|
|
||||||
<h2>Integration Result:</h2>
|
|
||||||
<p>{integrationResult}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default FakeIntegration;
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { DatePicker } from 'antd'
|
import { DatePicker } from "antd";
|
||||||
import React from 'react'
|
import React from "react";
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from "react-i18next";
|
||||||
import { useObjectToEdit } from '../../../zustand/ObjectToEditState';
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import type { DatePickerProps } from "antd";
|
import type { DatePickerProps } from "antd";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { DateEnum } from '../../../enums/Date';
|
import { DateEnum } from "../../../enums/Date";
|
||||||
|
|
||||||
const CustomDatePicker = () => {
|
const CustomDatePicker = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
@ -24,7 +24,6 @@ const CustomDatePicker = () => {
|
||||||
};
|
};
|
||||||
const Today = new Date() as any;
|
const Today = new Date() as any;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="CustomDatePicker">
|
<div className="CustomDatePicker">
|
||||||
<DatePicker
|
<DatePicker
|
||||||
|
|
@ -34,7 +33,7 @@ const CustomDatePicker = () => {
|
||||||
format={DateEnum?.FORMATE}
|
format={DateEnum?.FORMATE}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default CustomDatePicker
|
export default CustomDatePicker;
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
import React, { memo } from "react";
|
|
||||||
import type { MenuProps } from "antd";
|
|
||||||
import { Button, Dropdown, Space } from "antd";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { BsFillMoonStarsFill, BsFillSunFill } from "react-icons/bs";
|
|
||||||
import { useChangeTheme } from "../../Hooks/useChangeTheme";
|
|
||||||
|
|
||||||
const Theme: React.FC = () => {
|
|
||||||
const { currentTheme, changeTheme } = useChangeTheme();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const LightTheme = memo(() => (
|
|
||||||
<div className="MenuChange" onClick={lightThemeClickHandler}>
|
|
||||||
<BsFillSunFill />
|
|
||||||
{t("light")}
|
|
||||||
</div>
|
|
||||||
));
|
|
||||||
|
|
||||||
const DarkTheme = memo(() => (
|
|
||||||
<div className="MenuChange" onClick={darkThemeClickHandler}>
|
|
||||||
<BsFillMoonStarsFill />
|
|
||||||
{t("dark")}
|
|
||||||
</div>
|
|
||||||
));
|
|
||||||
|
|
||||||
const lightThemeClickHandler = React.useCallback(() => {
|
|
||||||
changeTheme("light");
|
|
||||||
}, [changeTheme]);
|
|
||||||
|
|
||||||
const darkThemeClickHandler = React.useCallback(() => {
|
|
||||||
changeTheme("dark");
|
|
||||||
}, [changeTheme]);
|
|
||||||
|
|
||||||
const items: MenuProps["items"] = [
|
|
||||||
{
|
|
||||||
key: "1",
|
|
||||||
label: <LightTheme />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "2",
|
|
||||||
label: <DarkTheme />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Space direction="vertical">
|
|
||||||
<Dropdown menu={{ items }} placement="top">
|
|
||||||
<Button>
|
|
||||||
{currentTheme === "dark" ? <DarkTheme /> : <LightTheme />}
|
|
||||||
</Button>
|
|
||||||
</Dropdown>
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Theme;
|
|
||||||
|
|
@ -31,11 +31,11 @@ const components: { [key: string]: React.FC<any> } = {
|
||||||
MaltyFile: MaltyFile,
|
MaltyFile: MaltyFile,
|
||||||
Checkbox: CheckboxField,
|
Checkbox: CheckboxField,
|
||||||
NumberFormate: NumberFormate,
|
NumberFormate: NumberFormate,
|
||||||
Number:NumberField
|
Number: NumberField,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ValidationField: React.FC<ValidationFieldProps> = React.memo(
|
const ValidationField: React.FC<ValidationFieldProps> = React.memo(
|
||||||
({ type, ...otherProps }:any) => {
|
({ type, ...otherProps }: any) => {
|
||||||
const Component = components[type as ValidationFieldType];
|
const Component = components[type as ValidationFieldType];
|
||||||
|
|
||||||
if (!Component) {
|
if (!Component) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { Checkbox, Form } from "antd";
|
import { Checkbox, Form } from "antd";
|
||||||
import {getNestedValue} from '../utils/getNestedValue'
|
import { getNestedValue } from "../utils/getNestedValue";
|
||||||
const CheckboxField = ({
|
const CheckboxField = ({
|
||||||
name,
|
name,
|
||||||
label,
|
label,
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,7 @@ const Default = ({
|
||||||
<label htmlFor={name} className="text">
|
<label htmlFor={name} className="text">
|
||||||
{label2}
|
{label2}
|
||||||
</label>
|
</label>
|
||||||
)
|
) : no_label ? (
|
||||||
|
|
||||||
:no_label ? (
|
|
||||||
<label htmlFor={name} className="text">
|
<label htmlFor={name} className="text">
|
||||||
<span>empty</span>
|
<span>empty</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -58,7 +56,6 @@ const Default = ({
|
||||||
name={name}
|
name={name}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
size="large"
|
size="large"
|
||||||
|
|
||||||
{...(type === "number" && { min: 0 })}
|
{...(type === "number" && { min: 0 })}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -12,27 +12,27 @@ const File = ({
|
||||||
className,
|
className,
|
||||||
props,
|
props,
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { formik, t, isError,errorMsg } = useFormField(name, props);
|
const { formik, t, isError, errorMsg } = useFormField(name, props);
|
||||||
let imageUrl = formik?.values?.[name] ?? null;
|
let imageUrl = formik?.values?.[name] ?? null;
|
||||||
console.log(imageUrl);
|
console.log(imageUrl);
|
||||||
console.log(typeof imageUrl === 'string');
|
console.log(typeof imageUrl === "string");
|
||||||
|
|
||||||
const fileList: UploadFile[] = useMemo(() => {
|
const fileList: UploadFile[] = useMemo(() => {
|
||||||
if (!imageUrl) return [];
|
if (!imageUrl) return [];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
typeof imageUrl === 'string'
|
typeof imageUrl === "string"
|
||||||
? {
|
? {
|
||||||
uid: '-1',
|
uid: "-1",
|
||||||
name: 'uploaded-image',
|
name: "uploaded-image",
|
||||||
status: 'done',
|
status: "done",
|
||||||
url: imageUrl,
|
url: imageUrl,
|
||||||
thumbUrl: imageUrl,
|
thumbUrl: imageUrl,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
uid: imageUrl.uid || '-1',
|
uid: imageUrl.uid || "-1",
|
||||||
name: imageUrl.name || 'uploaded-image',
|
name: imageUrl.name || "uploaded-image",
|
||||||
status: 'done',
|
status: "done",
|
||||||
originFileObj: imageUrl,
|
originFileObj: imageUrl,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
@ -70,7 +70,6 @@ const File = ({
|
||||||
icon={<UploadOutlined />}
|
icon={<UploadOutlined />}
|
||||||
>
|
>
|
||||||
{placholder ?? t("input.Click_to_upload_the_image")}
|
{placholder ?? t("input.Click_to_upload_the_image")}
|
||||||
|
|
||||||
</Button>
|
</Button>
|
||||||
<div className="Error_color"> {isError ? "required" : ""}</div>
|
<div className="Error_color"> {isError ? "required" : ""}</div>
|
||||||
{errorMsg}
|
{errorMsg}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ const NumberField = ({
|
||||||
label_icon,
|
label_icon,
|
||||||
...props
|
...props
|
||||||
}: ValidationFieldPropsInput) => {
|
}: ValidationFieldPropsInput) => {
|
||||||
const { errorMsg, isError, t ,formik} = useFormField(name, props);
|
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
||||||
|
|
||||||
const handleChange = (
|
const handleChange = (
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
) => {
|
) => {
|
||||||
console.log('Change:', e);
|
console.log("Change:", e);
|
||||||
formik.setFieldValue(name, e);
|
formik.setFieldValue(name, e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ const NumberFormate = ({
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
size="large"
|
size="large"
|
||||||
|
|
||||||
|
|
||||||
// onChange={onChange ? onChange : handleChange}
|
// onChange={onChange ? onChange : handleChange}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const SearchField = ({
|
||||||
props,
|
props,
|
||||||
no_label,
|
no_label,
|
||||||
label_icon,
|
label_icon,
|
||||||
isLoading
|
isLoading,
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
||||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||||
|
|
@ -78,8 +78,7 @@ const SearchField = ({
|
||||||
onChange={onChange || SelectableChange}
|
onChange={onChange || SelectableChange}
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
notFoundContent={isLoading ? <Spin/> : "لا يوجد" }
|
notFoundContent={isLoading ? <Spin /> : "لا يوجد"}
|
||||||
|
|
||||||
onSearch={SearchHandleChange}
|
onSearch={SearchHandleChange}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ const TextField = ({
|
||||||
props,
|
props,
|
||||||
no_label,
|
no_label,
|
||||||
label_icon,
|
label_icon,
|
||||||
className
|
className,
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { formik, isError, errorMsg, t } = useFormField(name, props);
|
const { formik, isError, errorMsg, t } = useFormField(name, props);
|
||||||
const TextFilehandleChange = (
|
const TextFilehandleChange = (
|
||||||
|
|
@ -33,13 +33,13 @@ const TextField = ({
|
||||||
) : label_icon ? (
|
) : label_icon ? (
|
||||||
<div className="LabelWithIcon">
|
<div className="LabelWithIcon">
|
||||||
<label htmlFor={name} className="text">
|
<label htmlFor={name} className="text">
|
||||||
{label2 ? label2 : t(`input.${label ? label : name}`) }
|
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
||||||
</label>
|
</label>
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<label htmlFor={name} className="text">
|
<label htmlFor={name} className="text">
|
||||||
{label2 ? label2 : t(`input.${label ? label : name}`) }
|
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -57,9 +57,7 @@ const TextField = ({
|
||||||
showCount
|
showCount
|
||||||
maxLength={1000}
|
maxLength={1000}
|
||||||
onChange={onChange || TextFilehandleChange}
|
onChange={onChange || TextFilehandleChange}
|
||||||
style={{height:120}}
|
style={{ height: 120 }}
|
||||||
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,8 @@
|
||||||
}
|
}
|
||||||
.Checkboxs {
|
.Checkboxs {
|
||||||
padding: 4%;
|
padding: 4%;
|
||||||
|
|
||||||
}
|
}
|
||||||
.ant-checkbox-wrapper{
|
.ant-checkbox-wrapper {
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
.SearchField {
|
.SearchField {
|
||||||
|
|
@ -203,27 +202,26 @@ input:-webkit-autofill:hover {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-checkbox-wrapper {
|
||||||
.ant-checkbox-wrapper{
|
|
||||||
margin-top: 25px !important;
|
margin-top: 25px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add_new_button{
|
.add_new_button {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
svg{
|
svg {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ValidationField:has(.input_number){
|
.ValidationField:has(.input_number) {
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
|
|
||||||
.input_number{
|
.input_number {
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex{
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 30px ;
|
gap: 30px;
|
||||||
max-width: 80% !important;
|
max-width: 80% !important;
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
|
export function getNestedValue(obj: any, path: any) {
|
||||||
|
|
||||||
export function getNestedValue(obj:any, path:any) {
|
|
||||||
return path
|
return path
|
||||||
.replace(/\?.\[|\]\[|\]\.?/g, '.') // Replace question mark and square brackets
|
.replace(/\?.\[|\]\[|\]\.?/g, ".") // Replace question mark and square brackets
|
||||||
.split('.') // Split by dots
|
.split(".") // Split by dots
|
||||||
.filter(Boolean) // Remove empty strings
|
.filter(Boolean) // Remove empty strings
|
||||||
.reduce((acc:any, key:any) => acc && acc[key], obj); // Access nested properties
|
.reduce((acc: any, key: any) => acc && acc[key], obj); // Access nested properties
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ export interface ValidationFieldPropsSearch {
|
||||||
option: any[];
|
option: any[];
|
||||||
isMulti?: boolean;
|
isMulti?: boolean;
|
||||||
searchBy: string;
|
searchBy: string;
|
||||||
isLoading?:any
|
isLoading?: any;
|
||||||
}
|
}
|
||||||
export interface ValidationFieldPropsDataRange {
|
export interface ValidationFieldPropsDataRange {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -151,7 +151,7 @@ export interface ValidationFieldPropstext {
|
||||||
| "TextArea"
|
| "TextArea"
|
||||||
| "NumberFormate";
|
| "NumberFormate";
|
||||||
label?: string;
|
label?: string;
|
||||||
label2?:string;
|
label2?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
|
|
@ -161,31 +161,26 @@ export interface ValidationFieldPropstext {
|
||||||
[key: string]: any; // Index signature to allow any additional props
|
[key: string]: any; // Index signature to allow any additional props
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///// new
|
///// new
|
||||||
export interface BaseField {
|
export interface BaseField {
|
||||||
name: string;
|
name: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
}
|
}
|
||||||
export type OmitBaseType = 'placeholder' | 'name' | 'label' | 'type';
|
export type OmitBaseType = "placeholder" | "name" | "label" | "type";
|
||||||
|
|
||||||
export type OmitPicker = OmitBaseType | 'format';
|
export type OmitPicker = OmitBaseType | "format";
|
||||||
|
|
||||||
export interface ValidationFieldPropsInput
|
export interface ValidationFieldPropsInput
|
||||||
extends Omit<InputProps, OmitBaseType>,
|
extends Omit<InputProps, OmitBaseType>,
|
||||||
BaseField {
|
BaseField {
|
||||||
type: 'text' | 'number' | 'password' | 'email' | "Number";
|
type: "text" | "number" | "password" | "email" | "Number";
|
||||||
isDisabled?:boolean
|
isDisabled?: boolean;
|
||||||
no_label?:string
|
no_label?: string;
|
||||||
label_icon?:string
|
label_icon?: string;
|
||||||
label2?:string
|
label2?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type ValidationFieldProps =
|
export type ValidationFieldProps =
|
||||||
| ValidationFieldPropsInput
|
| ValidationFieldPropsInput
|
||||||
| ValidationFieldPropsSelect
|
| ValidationFieldPropsSelect
|
||||||
|
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
import Image from "../Ui/Image";
|
|
||||||
import { Student } from "../../types/Item";
|
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
|
||||||
import { useGetStudent } from "../../api/student";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
const StudentBehavior = () => {
|
|
||||||
const { student_id } = useParams();
|
|
||||||
const { data: studentData } = useGetStudent({
|
|
||||||
show: student_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
const userData: Student | {} = studentData?.data ?? {};
|
|
||||||
|
|
||||||
const { positiveNote, warningNote, alertNote } = userData as Student;
|
|
||||||
const [t] = useTranslation();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const handelnavigate = () => {
|
|
||||||
navigate(`note`);
|
|
||||||
};
|
|
||||||
const Data = [
|
|
||||||
{
|
|
||||||
icon: "/Icon/medal.png",
|
|
||||||
title: t("array.UserInfo.appreciation"),
|
|
||||||
value: positiveNote,
|
|
||||||
buttonText: t("practical.show"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "/Icon/warning.png",
|
|
||||||
title: t("array.UserInfo.warning"),
|
|
||||||
value: warningNote,
|
|
||||||
buttonText: t("practical.show"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "/Icon/Error.png",
|
|
||||||
title: t("array.UserInfo.alert"),
|
|
||||||
value: alertNote,
|
|
||||||
buttonText: t("practical.show"),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return (
|
|
||||||
<div className="StudentBehavior">
|
|
||||||
<header>{t("header.Student_classroom_behavior")}</header>
|
|
||||||
<main>
|
|
||||||
{Data.map((item, index) => (
|
|
||||||
<article key={index} onClick={handelnavigate}>
|
|
||||||
<Image src={item.icon} />
|
|
||||||
<div>
|
|
||||||
<h6>{item.title}</h6>
|
|
||||||
<p>{item.value}</p>
|
|
||||||
</div>
|
|
||||||
<button>{item.buttonText}</button>
|
|
||||||
</article>
|
|
||||||
))}
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StudentBehavior;
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { getColorName } from "../../Hooks/usePercentage";
|
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
|
||||||
import { useGetStudent } from "../../api/student";
|
|
||||||
import { Student } from "../../types/Item";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
interface StudentTimeData {
|
|
||||||
id: number;
|
|
||||||
absences: number;
|
|
||||||
justified: number;
|
|
||||||
unjustified: number;
|
|
||||||
totalDays: number;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const StudentsTime = () => {
|
|
||||||
const { student_id } = useParams();
|
|
||||||
const { data: studentData } = useGetStudent({
|
|
||||||
show: student_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
const userData: Student | {} = studentData?.data ?? {};
|
|
||||||
|
|
||||||
const { ealryDeparture, absence, lateArrival } = userData as Student;
|
|
||||||
const [t] = useTranslation();
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
name: t("models.absence"),
|
|
||||||
id: 1,
|
|
||||||
absences: absence?.justified + absence?.not_justified,
|
|
||||||
justified: absence?.justified,
|
|
||||||
unjustified: absence?.not_justified,
|
|
||||||
totalDays: absence?.total,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: t("models.late_arrival"),
|
|
||||||
id: 2,
|
|
||||||
absences: lateArrival?.justified + lateArrival?.not_justified,
|
|
||||||
justified: lateArrival?.justified,
|
|
||||||
unjustified: lateArrival?.not_justified,
|
|
||||||
totalDays: lateArrival?.total,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: t("models.earlyDeparture"),
|
|
||||||
id: 3,
|
|
||||||
absences: ealryDeparture?.justified + ealryDeparture?.not_justified,
|
|
||||||
justified: ealryDeparture?.justified,
|
|
||||||
unjustified: ealryDeparture?.not_justified,
|
|
||||||
totalDays: ealryDeparture?.total,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const handel_naviagate = () => {
|
|
||||||
navigate(`status`);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className="StudentsTime">
|
|
||||||
<header>{t("header.student_status")}</header>
|
|
||||||
<main>
|
|
||||||
{data?.length > 0 &&
|
|
||||||
data.map((item: StudentTimeData, index: number) => {
|
|
||||||
return (
|
|
||||||
<article key={item.id} onClick={handel_naviagate}>
|
|
||||||
<span>
|
|
||||||
<h6>{item?.name}</h6>
|
|
||||||
<p data-color={getColorName(item.absences)}>
|
|
||||||
{item.absences}
|
|
||||||
</p>
|
|
||||||
</span>
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
<div>
|
|
||||||
{t("select.Student_Type.justified")}
|
|
||||||
<span>{item.justified}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{t("select.Student_Type.not_justified")}
|
|
||||||
<span>{item.unjustified}</span>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<div className="StudentsTimeTotal">المجموع</div>
|
|
||||||
<p>
|
|
||||||
{item.absences} من {item.totalDays} يوم
|
|
||||||
</p>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StudentsTime;
|
|
||||||
|
|
@ -1,28 +1,26 @@
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from "formik";
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from "react-i18next";
|
||||||
import { GoArrowSwitch } from 'react-icons/go';
|
import { GoArrowSwitch } from "react-icons/go";
|
||||||
import { useObjectToEdit } from '../../zustand/ObjectToEditState';
|
import { useObjectToEdit } from "../../zustand/ObjectToEditState";
|
||||||
import { QUESTION_OBJECT_KEY } from '../../config/AppKey';
|
import { QUESTION_OBJECT_KEY } from "../../config/AppKey";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const { values, setFieldValue,setValues } = useFormikContext<any>();
|
const { values, setFieldValue, setValues } = useFormikContext<any>();
|
||||||
const {isBseQuestion,setIsBseQuestion} = useObjectToEdit()
|
const { isBseQuestion, setIsBseQuestion } = useObjectToEdit();
|
||||||
const {setSavedQuestionData} = useObjectToEdit()
|
const { setSavedQuestionData } = useObjectToEdit();
|
||||||
const handleChange = () => {
|
const handleChange = () => {
|
||||||
setSavedQuestionData(null)
|
setSavedQuestionData(null);
|
||||||
localStorage.removeItem(QUESTION_OBJECT_KEY)
|
localStorage.removeItem(QUESTION_OBJECT_KEY);
|
||||||
if (isBseQuestion) {
|
if (isBseQuestion) {
|
||||||
setIsBseQuestion(false)
|
setIsBseQuestion(false);
|
||||||
setValues(null)
|
setValues(null);
|
||||||
setFieldValue("isBase",0)
|
setFieldValue("isBase", 0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
setIsBseQuestion(true);
|
||||||
setIsBseQuestion(true)
|
setValues(null);
|
||||||
setValues(null)
|
setFieldValue("isBase", 1);
|
||||||
setFieldValue("isBase",1)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -33,7 +31,9 @@ const Header = () => {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<GoArrowSwitch onClick={handleChange} className="m-2" />
|
<GoArrowSwitch onClick={handleChange} className="m-2" />
|
||||||
{isBseQuestion || values?.isBase === 1 ? t("header.malty_exercise") :t("header.exercise") }
|
{isBseQuestion || values?.isBase === 1
|
||||||
|
? t("header.malty_exercise")
|
||||||
|
: t("header.exercise")}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
|
||||||
import katex from 'katex';
|
|
||||||
import 'katex/dist/katex.min.css';
|
|
||||||
|
|
||||||
const MathInput: React.FC = () => {
|
|
||||||
const [latex, setLatex] = useState<string>('f(x) = \\frac{1}{1+e^{-x}}');
|
|
||||||
const displayRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
renderLatex();
|
|
||||||
}, [latex]);
|
|
||||||
//// tow input show and edit
|
|
||||||
const renderLatex = () => {
|
|
||||||
if (displayRef.current) {
|
|
||||||
try {
|
|
||||||
katex.render(latex, displayRef.current, {
|
|
||||||
throwOnError: false,
|
|
||||||
displayMode: true,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('KaTeX rendering error:', error);
|
|
||||||
displayRef.current.textContent = 'Error rendering LaTeX';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setLatex(event.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{ padding: '20px' }}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={latex}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '10px',
|
|
||||||
fontSize: '16px',
|
|
||||||
border: '1px solid #ccc',
|
|
||||||
borderRadius: '4px',
|
|
||||||
fontFamily: 'monospace',
|
|
||||||
marginBottom: '10px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
ref={displayRef}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '10px',
|
|
||||||
fontSize: '16px',
|
|
||||||
border: '1px solid #ccc',
|
|
||||||
borderRadius: '4px',
|
|
||||||
minHeight: '40px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MathInput;
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
|
||||||
import katex from 'katex';
|
|
||||||
import 'katex/dist/katex.min.css';
|
|
||||||
|
|
||||||
const MathInput: React.FC = () => {
|
|
||||||
const [latex, setLatex] = useState<string>('f(x) = \\frac{1}{1+e^{-x}}');
|
|
||||||
const inputRef = useRef<HTMLDivElement>(null);
|
|
||||||
const [isEditing, setIsEditing] = useState<boolean>(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
renderLatex();
|
|
||||||
}, [latex, isEditing]);
|
|
||||||
|
|
||||||
const renderLatex = () => {
|
|
||||||
if (inputRef.current && !isEditing) {
|
|
||||||
try {
|
|
||||||
katex.render(latex, inputRef.current, {
|
|
||||||
throwOnError: false,
|
|
||||||
displayMode: true,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('KaTeX rendering error:', error);
|
|
||||||
inputRef.current.textContent = 'Error rendering LaTeX';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInput = () => {
|
|
||||||
if (inputRef.current) {
|
|
||||||
setLatex(inputRef.current.textContent || '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFocus = () => {
|
|
||||||
setIsEditing(true);
|
|
||||||
if (inputRef.current) {
|
|
||||||
inputRef.current.textContent = latex;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBlur = () => {
|
|
||||||
setIsEditing(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{ padding: '20px' }}>
|
|
||||||
<div
|
|
||||||
ref={inputRef}
|
|
||||||
contentEditable
|
|
||||||
onInput={handleInput}
|
|
||||||
onFocus={handleFocus}
|
|
||||||
onBlur={handleBlur}
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
padding: '10px',
|
|
||||||
fontSize: '16px',
|
|
||||||
border: '1px solid #ccc',
|
|
||||||
borderRadius: '4px',
|
|
||||||
minHeight: '40px',
|
|
||||||
fontFamily: isEditing ? 'monospace' : 'inherit',
|
|
||||||
cursor: 'text',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MathInput;
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
export const useAddKeyToData = (dataSource: any, identifier = "id") => {
|
export const useAddKeyToData = (dataSource: any, identifier = "id") => {
|
||||||
if (!dataSource || !Array.isArray(dataSource)) {
|
if (!dataSource || !Array.isArray(dataSource)) {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
import { useCallback, useEffect, useState } from "react";
|
|
||||||
|
|
||||||
export const useChangeTheme = () => {
|
|
||||||
const [currentTheme, setCurrentTheme] = useState(
|
|
||||||
localStorage.getItem("theme") ?? "light",
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (currentTheme === "dark") {
|
|
||||||
document.body.classList.add("dark");
|
|
||||||
} else {
|
|
||||||
document.body.classList.remove("dark");
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem("theme", currentTheme);
|
|
||||||
}, [currentTheme]);
|
|
||||||
|
|
||||||
const changeTheme = useCallback((newTheme: any) => {
|
|
||||||
setCurrentTheme(newTheme);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return { currentTheme, changeTheme };
|
|
||||||
};
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
const useDifferenceData = (values: any, data: any) => {
|
|
||||||
const [newData, setNewData] = useState({});
|
|
||||||
|
|
||||||
for (const key in data) {
|
|
||||||
if (values[key] !== data[key]) {
|
|
||||||
setNewData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
[key]: values[key],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newData;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useDifferenceData;
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
const useDisableShortcutsAndRightClick = () => {
|
|
||||||
useEffect(() => {
|
|
||||||
const disableShortcutsAndRightClick = (event: Event) => {
|
|
||||||
// Check for Ctrl+Shift+C or F12
|
|
||||||
if (
|
|
||||||
(event as KeyboardEvent).ctrlKey &&
|
|
||||||
(event as KeyboardEvent).shiftKey &&
|
|
||||||
((event as KeyboardEvent).key === "C" ||
|
|
||||||
(event as KeyboardEvent).key === "c" ||
|
|
||||||
(event as KeyboardEvent).keyCode === 123) /* F12 key code */
|
|
||||||
) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const disableRightClick = (event: MouseEvent) => {
|
|
||||||
event.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("keydown", disableShortcutsAndRightClick);
|
|
||||||
document.addEventListener("contextmenu", disableRightClick);
|
|
||||||
|
|
||||||
// Attempt to prevent F12 key default behavior
|
|
||||||
document.addEventListener("keydown", (event) => {
|
|
||||||
if (event.key === "F12" || event.keyCode === 123) {
|
|
||||||
event.preventDefault();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("keydown", disableShortcutsAndRightClick);
|
|
||||||
document.removeEventListener("contextmenu", disableRightClick);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useDisableShortcutsAndRightClick;
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from "react";
|
||||||
|
|
||||||
type ModifierKey = 'ctrlKey' | 'shiftKey' | 'altKey' | 'metaKey';
|
type ModifierKey = "ctrlKey" | "shiftKey" | "altKey" | "metaKey";
|
||||||
|
|
||||||
const useKeyPress = (targetKey: string, modifierKey: ModifierKey, callback:any) => {
|
const useKeyPress = (
|
||||||
|
targetKey: string,
|
||||||
|
modifierKey: ModifierKey,
|
||||||
|
callback: any,
|
||||||
|
) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if (event[modifierKey] && event.key === targetKey) {
|
if (event[modifierKey] && event.key === targetKey) {
|
||||||
|
|
@ -11,10 +15,10 @@ const useKeyPress = (targetKey: string, modifierKey: ModifierKey, callback:any)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('keydown', handleKeyDown);
|
document.addEventListener("keydown", handleKeyDown);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', handleKeyDown);
|
document.removeEventListener("keydown", handleKeyDown);
|
||||||
};
|
};
|
||||||
}, [targetKey, modifierKey, callback]);
|
}, [targetKey, modifierKey, callback]);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
|
|
||||||
function useLoadingState(
|
|
||||||
initialValue: boolean,
|
|
||||||
duration: number,
|
|
||||||
): [boolean, () => void] {
|
|
||||||
const [loading, setLoading] = useState<boolean>(initialValue);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const timeoutId = setTimeout(() => {
|
|
||||||
setLoading(false);
|
|
||||||
}, duration);
|
|
||||||
|
|
||||||
return () => clearTimeout(timeoutId);
|
|
||||||
}, [duration]);
|
|
||||||
|
|
||||||
const resetLoading = () => {
|
|
||||||
setLoading(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return [loading, resetLoading];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useLoadingState;
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
import { Pagination } from "antd";
|
|
||||||
import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
|
|
||||||
|
|
||||||
export const PaginationBody = ({ data, no_label, label_icon }: any) => {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const location = useLocation();
|
|
||||||
const pagination = location?.search || "";
|
|
||||||
const currentPage = parseInt(
|
|
||||||
new URLSearchParams(location.search).get("page") || "1",
|
|
||||||
10,
|
|
||||||
);
|
|
||||||
const pageSize = parseInt(
|
|
||||||
new URLSearchParams(location.search).get("per_page") || "8",
|
|
||||||
10,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
|
||||||
const onChange = (page: number, pageSize?: number) => {
|
|
||||||
navigate(
|
|
||||||
`?page=${page}&per_page=${pageSize || data?.per_page}&search=${searchParams.get("search")}`,
|
|
||||||
{ replace: true },
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onShowSizeChange = (current: number, pageSize: number) => {
|
|
||||||
navigate(
|
|
||||||
`?page=${current}&per_page=${pageSize}&search=${searchParams.get("search")}`,
|
|
||||||
{ replace: true },
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Pagination
|
|
||||||
className="text-center mt-3 paginateStyle"
|
|
||||||
total={data}
|
|
||||||
showTotal={(total: any) => `Total ${total} items`}
|
|
||||||
pageSize={pageSize}
|
|
||||||
pageSizeOptions={[8, 16, 24, 32, 40]}
|
|
||||||
defaultCurrent={currentPage}
|
|
||||||
current={currentPage} // Adding this line will set the current page correctly
|
|
||||||
onChange={onChange}
|
|
||||||
onShowSizeChange={onShowSizeChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
import { RiArrowLeftDownLine, RiArrowRightUpLine } from "react-icons/ri";
|
|
||||||
|
|
||||||
export const PercentageImageSrc = (percentage: number) => {
|
|
||||||
if (percentage >= 90) {
|
|
||||||
return "../ArrowType/90.png";
|
|
||||||
} else if (percentage >= 80) {
|
|
||||||
return "../ArrowType/80.png";
|
|
||||||
} else if (percentage >= 60) {
|
|
||||||
return "../ArrowType/60.png";
|
|
||||||
} else if (percentage >= 40) {
|
|
||||||
return "../ArrowType/40.png";
|
|
||||||
} else if (percentage >= 20) {
|
|
||||||
return "../ArrowType/20.png";
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getColorName = (percentage: number) => {
|
|
||||||
if (percentage >= 6) {
|
|
||||||
return "Red";
|
|
||||||
} else if (percentage >= 4) {
|
|
||||||
return "Orange";
|
|
||||||
} else if (percentage >= 2) {
|
|
||||||
return "Green";
|
|
||||||
} else {
|
|
||||||
return "Green";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getStrokeColor = (percentage: number) => {
|
|
||||||
if (percentage >= 90) {
|
|
||||||
return "#87d068"; // Green color
|
|
||||||
} else if (percentage >= 80) {
|
|
||||||
return "#87d068"; // Blue color
|
|
||||||
} else if (percentage >= 60) {
|
|
||||||
return "#ffec3d"; // Yellow color
|
|
||||||
} else if (percentage >= 40) {
|
|
||||||
return "#faad14"; // Orange color
|
|
||||||
} else if (percentage >= 20) {
|
|
||||||
return "#f5222d"; // Red color
|
|
||||||
} else {
|
|
||||||
return "#f5222d"; // Red color
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getPercentageIcon = (percentage: number) => {
|
|
||||||
if (percentage >= 60) {
|
|
||||||
return <RiArrowRightUpLine />;
|
|
||||||
} else if (percentage >= 40) {
|
|
||||||
return <></>;
|
|
||||||
} else {
|
|
||||||
return <RiArrowLeftDownLine />;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getPercentageText = (percentage: number) => {
|
|
||||||
if (percentage >= 60) {
|
|
||||||
return "مرتفع";
|
|
||||||
} else if (percentage >= 40) {
|
|
||||||
return "متوسط";
|
|
||||||
} else {
|
|
||||||
return "منخفض";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
{
|
|
||||||
/* <RiArrowRightUpLine /> */
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
/* <RiArrowLeftDownLine /> */
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
const usePreviousPath = () => {
|
|
||||||
const location = useLocation();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const [previousPath, setPreviousPath] = useState(null);
|
|
||||||
console.log(previousPath);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Update the previous path whenever the location changes
|
|
||||||
const currentPath = location.pathname as any;
|
|
||||||
setPreviousPath(currentPath);
|
|
||||||
|
|
||||||
// Clean up
|
|
||||||
return () => {
|
|
||||||
setPreviousPath(null);
|
|
||||||
};
|
|
||||||
}, [location]);
|
|
||||||
|
|
||||||
const navigateToPreviousPath = () => {
|
|
||||||
if (previousPath) {
|
|
||||||
navigate(previousPath);
|
|
||||||
} else {
|
|
||||||
navigate(-1); // Fallback to default behavior
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return { navigateToPreviousPath };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default usePreviousPath;
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
|
|
||||||
interface ResponsiveHookProps {
|
|
||||||
initialState: boolean;
|
|
||||||
setIs: any;
|
|
||||||
widthThreshold: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const useResponsive = ({
|
|
||||||
initialState,
|
|
||||||
setIs,
|
|
||||||
widthThreshold,
|
|
||||||
}: ResponsiveHookProps) => {
|
|
||||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
|
||||||
const [isBoolean, setIsBoolean] = useState<boolean>(initialState);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleResize = () => {
|
|
||||||
setWindowWidth(window.innerWidth);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener("resize", handleResize);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("resize", handleResize);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (windowWidth < widthThreshold && isBoolean) {
|
|
||||||
setIs(false);
|
|
||||||
setIsBoolean(false);
|
|
||||||
} else if (windowWidth >= widthThreshold && !isBoolean) {
|
|
||||||
setIs(true);
|
|
||||||
setIsBoolean(true);
|
|
||||||
}
|
|
||||||
}, [windowWidth, isBoolean, setIs, widthThreshold]);
|
|
||||||
|
|
||||||
return { windowWidth, isBoolean, setIsBoolean };
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useResponsive;
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from "react";
|
||||||
import { setLocalStorageQuestions } from '../utils/setLocalStorageQuestions';
|
import { setLocalStorageQuestions } from "../utils/setLocalStorageQuestions";
|
||||||
import { setLocalStorageBaseQuestions } from '../utils/setLocalStorageBaseQuestions';
|
|
||||||
|
|
||||||
const useSaveOnDisconnect = (noChange: boolean, QUESTION_OBJECT_KEY: string, SavedQuestionData: any) => {
|
const useSaveOnDisconnect = (
|
||||||
|
noChange: boolean,
|
||||||
|
QUESTION_OBJECT_KEY: string,
|
||||||
|
SavedQuestionData: any,
|
||||||
|
) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||||
console.log("disconnect");
|
console.log("disconnect");
|
||||||
if (noChange) {
|
if (noChange) {
|
||||||
if(SavedQuestionData?.isBase ===1){
|
if (SavedQuestionData?.isBase === 1) {
|
||||||
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
} else {
|
||||||
}else{
|
|
||||||
|
|
||||||
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,24 +21,22 @@ const useSaveOnDisconnect = (noChange: boolean, QUESTION_OBJECT_KEY: string, Sav
|
||||||
const handleOffline = () => {
|
const handleOffline = () => {
|
||||||
console.log("disconnect");
|
console.log("disconnect");
|
||||||
if (noChange) {
|
if (noChange) {
|
||||||
if(SavedQuestionData?.isBase ===1){
|
if (SavedQuestionData?.isBase === 1) {
|
||||||
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
} else {
|
||||||
}else{
|
|
||||||
|
|
||||||
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add event listeners
|
// Add event listeners
|
||||||
window.addEventListener('beforeunload', handleBeforeUnload);
|
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||||
window.addEventListener('offline', handleOffline);
|
window.addEventListener("offline", handleOffline);
|
||||||
|
|
||||||
// Cleanup function
|
// Cleanup function
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('beforeunload', handleBeforeUnload);
|
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||||
window.removeEventListener('offline', handleOffline);
|
window.removeEventListener("offline", handleOffline);
|
||||||
};
|
};
|
||||||
}, [noChange, QUESTION_OBJECT_KEY, SavedQuestionData]); // Add dependencies to the hook
|
}, [noChange, QUESTION_OBJECT_KEY, SavedQuestionData]); // Add dependencies to the hook
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
const useSearchResults = (data: any[] | undefined, query: string | null) => {
|
|
||||||
const [results, setResults] = useState<any[]>([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const filteredResults =
|
|
||||||
data?.filter((item: any) =>
|
|
||||||
item?.toLowerCase()?.includes(query?.toLowerCase()),
|
|
||||||
) ?? [];
|
|
||||||
|
|
||||||
setResults(filteredResults);
|
|
||||||
|
|
||||||
if (results?.length === 0 && query != null && query?.length > 1) {
|
|
||||||
}
|
|
||||||
}, [query]);
|
|
||||||
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useSearchResults;
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { usePage_titleState } from "../zustand/PageTitleState";
|
import { usePage_titleState } from "../zustand/PageTitleState";
|
||||||
|
|
||||||
const useSetPage_title = (title: any) => {
|
const useSetPageTitle = (title: any) => {
|
||||||
const setPage_title = usePage_titleState((state) => state.setPage_title);
|
const setPage_title = usePage_titleState((state) => state.setPage_title);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -9,4 +9,4 @@ const useSetPage_title = (title: any) => {
|
||||||
}, [title, setPage_title]);
|
}, [title, setPage_title]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useSetPage_title;
|
export default useSetPageTitle;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { AppRoutes, CrudRoutes } from "../Routes";
|
import { AppRoutes, CrudRoutes } from "../Routes";
|
||||||
import { PROJECT_NAME } from "../config/AppKey";
|
import { PROJECT_NAME } from "../config/AppKey";
|
||||||
|
|
||||||
export const usegetTitleFromRoute = (path: any) => {
|
export const useGetTitleFromRoute = (path: any) => {
|
||||||
if (AppRoutes[path]) {
|
if (AppRoutes[path]) {
|
||||||
return `${PROJECT_NAME} | ${AppRoutes[path]}`;
|
return `${PROJECT_NAME} | ${AppRoutes[path]}`;
|
||||||
} else if (CrudRoutes[path]) {
|
} else if (CrudRoutes[path]) {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
|
||||||
>
|
>
|
||||||
{(formik) => {
|
{(formik) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -43,7 +42,6 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
|
||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
|
|
||||||
return <Form className="w-100">{children}</Form>;
|
return <Form className="w-100">{children}</Form>;
|
||||||
}}
|
}}
|
||||||
</Formik>
|
</Formik>
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,12 @@ import { useTranslation } from "react-i18next";
|
||||||
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../../enums/abilities";
|
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../../enums/abilities";
|
||||||
import { hasAbility } from "../../utils/hasAbility";
|
import { hasAbility } from "../../utils/hasAbility";
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
SearchField,
|
SearchField,
|
||||||
useModalHandler,
|
useModalHandler,
|
||||||
ModalEnum,
|
ModalEnum,
|
||||||
useTranslation,
|
useTranslation,
|
||||||
ABILITIES_ENUM,
|
ABILITIES_ENUM,
|
||||||
ABILITIES_VALUES_ENUM,
|
ABILITIES_VALUES_ENUM,
|
||||||
hasAbility
|
hasAbility,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { usegetTitleFromRoute } from "../../Hooks/usegetTitleFromRoute";
|
import { useGetTitleFromRoute } from "../../Hooks/useGetTitleFromRoute";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import NavBar from "./NavBar";
|
import NavBar from "./NavBar";
|
||||||
|
|
@ -18,7 +18,7 @@ const Layout = ({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{usegetTitleFromRoute(location.pathname)}</title>
|
<title>{useGetTitleFromRoute(location.pathname)}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="Layout">
|
<div className="Layout">
|
||||||
<main className={`${className} Layout_Body`}>
|
<main className={`${className} Layout_Body`}>
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,8 @@ const SideBar = () => {
|
||||||
<div className="side_bar">
|
<div className="side_bar">
|
||||||
<h1>
|
<h1>
|
||||||
{/* {t("sidebar.dashboard")} */}
|
{/* {t("sidebar.dashboard")} */}
|
||||||
{branch_name} </h1>
|
{branch_name}{" "}
|
||||||
|
</h1>
|
||||||
<Divider />
|
<Divider />
|
||||||
<div className="side_bar_links">
|
<div className="side_bar_links">
|
||||||
{menuItems.map((item, index) => {
|
{menuItems.map((item, index) => {
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,11 @@ type FormFieldType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const FormField = ({ isLoading }: FormFieldType) => {
|
const FormField = ({ isLoading }: FormFieldType) => {
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Form className="AuthForm">
|
<Form className="AuthForm">
|
||||||
<Image src="../App/Logo.png" />
|
<Image src="../App/Logo.png" />
|
||||||
|
|
||||||
|
|
||||||
<div className="AuthInput">
|
<div className="AuthInput">
|
||||||
<label className="form-label" htmlFor="username">
|
<label className="form-label" htmlFor="username">
|
||||||
{t("input.Username")}
|
{t("input.Username")}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ const LoginForm = () => {
|
||||||
const { mutate, isLoading, isSuccess, data } = useLoginAdmin();
|
const { mutate, isLoading, isSuccess, data } = useLoginAdmin();
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const handelSubmit = (values: FormValues) => {
|
const handelSubmit = (values: FormValues) => {
|
||||||
|
|
||||||
mutate(values);
|
mutate(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ import React from "react";
|
||||||
import Image from "../../Components/Ui/Image";
|
import Image from "../../Components/Ui/Image";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ABILITIES_ENUM } from "../../enums/abilities";
|
import { ABILITIES_ENUM } from "../../enums/abilities";
|
||||||
import useSetPage_title from "../../Hooks/useSetPageTitle";
|
import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
||||||
|
|
||||||
const Dummy = () => {
|
const Dummy = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
useSetPage_title(`${t(ABILITIES_ENUM?.MAIN_PAGE)} / ${t("dashboard")}`);
|
useSetPageTitle(`${t(ABILITIES_ENUM?.MAIN_PAGE)} / ${t("dashboard")}`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="DammyHomePage">
|
<div className="DummyHomePage">
|
||||||
<Image src="/App/SyriaLogo.webp" />
|
<Image src="/App/SyriaLogo.webp" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
import ChartSection from "./Section/ChartSection";
|
|
||||||
import NoteSections from "./Section/NoteSections";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { ABILITIES_ENUM } from "../../enums/abilities";
|
|
||||||
// import useSetPage_title from "../../Hooks/useSetPageTitle";
|
|
||||||
|
|
||||||
const Page = () => {
|
|
||||||
const [t] = useTranslation();
|
|
||||||
// useSetPage_title(`${t(ABILITIES_ENUM?.MAIN_PAGE)} / ${t("dashboard")}`);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="HomePage">
|
|
||||||
<ChartSection />
|
|
||||||
<NoteSections />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Page;
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import CountSection from "../../../Components/Home/CountSection";
|
|
||||||
import ColumnChart from "../../../Components/Chart/ColumnChart";
|
|
||||||
import AreaChart from "../../../Components/Chart/AreaChart";
|
|
||||||
import StudentSubjects from "../../../Components/Home/StudentSubjects";
|
|
||||||
import CalendarSection from "../../../Components/Home/CalendarSection";
|
|
||||||
|
|
||||||
const ChartSection = () => {
|
|
||||||
return (
|
|
||||||
<div className="ChartSection">
|
|
||||||
<CountSection />
|
|
||||||
<div className="TowItem">
|
|
||||||
<ColumnChart />
|
|
||||||
<CalendarSection />
|
|
||||||
</div>
|
|
||||||
<AreaChart />
|
|
||||||
|
|
||||||
<div className="TowItem">
|
|
||||||
<StudentSubjects />
|
|
||||||
<ColumnChart />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ChartSection;
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import NoteSection from "../../../Components/Home/NoteSection";
|
|
||||||
import ActivitySection from "../../../Components/Home/ActivitySection";
|
|
||||||
|
|
||||||
const NoteSections = () => {
|
|
||||||
return (
|
|
||||||
<div className="NoteSections">
|
|
||||||
<NoteSection />
|
|
||||||
<ActivitySection />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NoteSections;
|
|
||||||
|
|
@ -24,9 +24,7 @@ const Form = () => {
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
</Col>
|
</Col>
|
||||||
<div>
|
<div>
|
||||||
<DynamicTags/>
|
<DynamicTags />
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,8 @@ const ModalForm: React.FC = () => {
|
||||||
}, [setIsOpen, isSuccess]);
|
}, [setIsOpen, isSuccess]);
|
||||||
|
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
|
|
||||||
mutate({
|
mutate({
|
||||||
...values
|
...values,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,13 @@ import { useEffect } from "react";
|
||||||
import DynamicTags from "../synonyms/DynamicTags";
|
import DynamicTags from "../synonyms/DynamicTags";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="w-100">
|
<Row className="w-100">
|
||||||
<Col>
|
<Col>
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
</Col>
|
</Col>
|
||||||
<div>
|
<div>
|
||||||
<DynamicTags/>
|
<DynamicTags />
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ import ModelButtons from "../../../Components/models/ModelButtons";
|
||||||
|
|
||||||
const ModalForm: React.FC = () => {
|
const ModalForm: React.FC = () => {
|
||||||
const { isOpen, setIsOpen } = useModalState((state) => state);
|
const { isOpen, setIsOpen } = useModalState((state) => state);
|
||||||
const { objectToEdit, setObjectToEdit } = useObjectToEdit(
|
const { objectToEdit, setObjectToEdit } = useObjectToEdit((state) => state);
|
||||||
(state) => state,
|
|
||||||
);
|
|
||||||
const { mutate, isSuccess, isLoading } = useUpdateTag();
|
const { mutate, isSuccess, isLoading } = useUpdateTag();
|
||||||
// console.log(objectToEdit,"objectToEdit");
|
// console.log(objectToEdit,"objectToEdit");
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
|
|
@ -22,7 +20,7 @@ const ModalForm: React.FC = () => {
|
||||||
// phone_number: values?.number
|
// phone_number: values?.number
|
||||||
// });
|
// });
|
||||||
mutate({
|
mutate({
|
||||||
...values
|
...values,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
|
@ -58,7 +56,6 @@ const ModalForm: React.FC = () => {
|
||||||
<main className="main_modal w-100">
|
<main className="main_modal w-100">
|
||||||
<ModelBody />
|
<ModelBody />
|
||||||
<ModelButtons isLoading={isLoading} />
|
<ModelButtons isLoading={isLoading} />
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
</FormikForm>
|
</FormikForm>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,35 @@
|
||||||
import { FaPlus } from "react-icons/fa";
|
import { FaPlus } from "react-icons/fa";
|
||||||
|
|
||||||
import useModalHandler from "../../utils/useModalHandler";
|
import useModalHandler from "../../utils/useModalHandler";
|
||||||
import { ModalEnum } from "../../enums/Model";
|
import { ModalEnum } from "../../enums/Model";
|
||||||
|
|
||||||
// import useSetPage_title from "../../Hooks/useSetPageTitle";
|
// import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { lazy, Suspense } from 'react';
|
import { lazy, Suspense } from "react";
|
||||||
import { Spin } from "antd";
|
import { Spin } from "antd";
|
||||||
import { canAddTags } from "../../utils/hasAbilityFn";
|
import { canAddTags } from "../../utils/hasAbilityFn";
|
||||||
import useSetPage_title from "../../Hooks/useSetPageTitle";
|
import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
||||||
const Table = lazy(() => import('./Table'));
|
const Table = lazy(() => import("./Table"));
|
||||||
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
const AddModalForm = lazy(() => import("./Model/AddModel"));
|
||||||
const EditModalForm = lazy(() => import('./Model/EditModel'));
|
const EditModalForm = lazy(() => import("./Model/EditModel"));
|
||||||
const DeleteModalForm = lazy(() => import('./Model/Delete'));
|
const DeleteModalForm = lazy(() => import("./Model/Delete"));
|
||||||
const SearchField = lazy(() => import('../../Components/DataTable/SearchField'));
|
const SearchField = lazy(
|
||||||
|
() => import("../../Components/DataTable/SearchField"),
|
||||||
|
);
|
||||||
|
|
||||||
const TableHeader = () => {
|
const TableHeader = () => {
|
||||||
const { handel_open_model } = useModalHandler();
|
const { handel_open_model } = useModalHandler();
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
useSetPage_title(
|
useSetPageTitle(t(`page_header.tags`));
|
||||||
t(`page_header.tags`),
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
|
<Suspense fallback={<Spin />}>
|
||||||
<Suspense fallback={<Spin/>}>
|
|
||||||
<header className="d-flex justify-content-between">
|
<header className="d-flex justify-content-between">
|
||||||
<SearchField searchBy="name" placeholder={t("practical.search_here")} />
|
<SearchField
|
||||||
|
searchBy="name"
|
||||||
|
placeholder={t("practical.search_here")}
|
||||||
|
/>
|
||||||
|
|
||||||
{canAddTags && (
|
{canAddTags && (
|
||||||
<div className="Selects">
|
<div className="Selects">
|
||||||
|
|
@ -42,7 +43,6 @@ const TableHeader = () => {
|
||||||
)}
|
)}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
||||||
<Table />
|
<Table />
|
||||||
<DeleteModalForm />
|
<DeleteModalForm />
|
||||||
<AddModalForm />
|
<AddModalForm />
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,5 @@ export {
|
||||||
AddModalForm,
|
AddModalForm,
|
||||||
EditModalForm,
|
EditModalForm,
|
||||||
DeleteModalForm,
|
DeleteModalForm,
|
||||||
FaPlus
|
FaPlus,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
import { useFormikContext } from 'formik'
|
import { useFormikContext } from "formik";
|
||||||
import React from 'react'
|
import React from "react";
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from "react-i18next";
|
||||||
import { FaCirclePlus } from 'react-icons/fa6'
|
import { FaCirclePlus } from "react-icons/fa6";
|
||||||
import Tag from './Tag'
|
import Tag from "./Tag";
|
||||||
|
|
||||||
const DynamicTags = () => {
|
const DynamicTags = () => {
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
const formik = useFormikContext<any>()
|
const [t] = useTranslation();
|
||||||
const [t] = useTranslation()
|
|
||||||
|
|
||||||
|
|
||||||
console.log(formik?.values?.synonyms);
|
console.log(formik?.values?.synonyms);
|
||||||
|
|
||||||
|
|
@ -16,55 +14,43 @@ const DynamicTags = () => {
|
||||||
const length = formik?.values?.synonyms.length;
|
const length = formik?.values?.synonyms.length;
|
||||||
const lastElement = formik?.values?.synonyms[length - 1];
|
const lastElement = formik?.values?.synonyms[length - 1];
|
||||||
|
|
||||||
if(lastElement !== ""){
|
if (lastElement !== "") {
|
||||||
formik.setFieldValue('synonyms', [...(formik?.values as any)?.synonyms as any[],""])
|
formik.setFieldValue("synonyms", [
|
||||||
}else{
|
...((formik?.values as any)?.synonyms as any[]),
|
||||||
|
"",
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
// console.log(formik?.values);
|
||||||
}
|
// console.log(currentTag);
|
||||||
// console.log(formik?.values);
|
|
||||||
// console.log(currentTag);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='DynamicTags'>
|
<div className="DynamicTags">
|
||||||
{formik?.values?.synonyms?.length < 1 &&
|
{formik?.values?.synonyms?.length < 1 && (
|
||||||
|
<p className="add_new_button">
|
||||||
<p className="add_new_button" >
|
<FaCirclePlus size={23} onClick={handleAddChoice} />{" "}
|
||||||
<FaCirclePlus size={23} onClick={handleAddChoice} /> {t("header.add_synonyms")}
|
{t("header.add_synonyms")}
|
||||||
</p>
|
</p>
|
||||||
}
|
)}
|
||||||
|
|
||||||
<div className="tag_container">
|
<div className="tag_container">
|
||||||
<div className="tags">
|
<div className="tags">
|
||||||
|
{(((formik?.values as any)?.synonyms as any[]) || []).map(
|
||||||
{
|
(item: any, index: number) => {
|
||||||
(((formik?.values as any)?.synonyms as any[])||[]) .map((item:any,index:number)=>{
|
return <Tag key={index} index={index} data={item} />;
|
||||||
|
},
|
||||||
return (
|
)}
|
||||||
<Tag key={index} index={index} data={item}/>
|
|
||||||
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{formik?.values?.synonyms?.length > 0 &&
|
{formik?.values?.synonyms?.length > 0 && (
|
||||||
|
<p className="add_new_button">
|
||||||
<p className="add_new_button" >
|
|
||||||
<FaCirclePlus onClick={handleAddChoice} size={20} />
|
<FaCirclePlus onClick={handleAddChoice} size={20} />
|
||||||
</p>
|
</p>
|
||||||
|
)}
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default DynamicTags
|
export default DynamicTags;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from "formik";
|
||||||
import React, { useRef, useEffect } from 'react';
|
import React, { useRef, useEffect } from "react";
|
||||||
import { useObjectToEdit } from '../../../zustand/ObjectToEditState';
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { FaTrash } from 'react-icons/fa';
|
import { FaTrash } from "react-icons/fa";
|
||||||
|
|
||||||
const Tag = ({ data, index }: { data: any, index: number }) => {
|
const Tag = ({ data, index }: { data: any; index: number }) => {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const { setTagsSearch ,setCurrentTag} = useObjectToEdit();
|
const { setTagsSearch, setCurrentTag } = useObjectToEdit();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (inputRef.current) {
|
if (inputRef.current) {
|
||||||
|
|
@ -16,13 +16,11 @@ const Tag = ({ data, index }: { data: any, index: number }) => {
|
||||||
console.log(formik?.values?.synonyms);
|
console.log(formik?.values?.synonyms);
|
||||||
console.log(index);
|
console.log(index);
|
||||||
|
|
||||||
|
|
||||||
const handleEditInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleEditInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
// console.log(e.target.value);
|
// console.log(e.target.value);
|
||||||
formik.setFieldValue(`synonyms[${index}]`, e.target.value);
|
formik.setFieldValue(`synonyms[${index}]`, e.target.value);
|
||||||
setTagsSearch(e.target.value)
|
setTagsSearch(e.target.value);
|
||||||
setCurrentTag(index)
|
setCurrentTag(index);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInputBlur = () => {
|
const handleInputBlur = () => {
|
||||||
|
|
@ -38,14 +36,14 @@ const Tag = ({ data, index }: { data: any, index: number }) => {
|
||||||
console.log(currentTags); // Log the updated tags array
|
console.log(currentTags); // Log the updated tags array
|
||||||
|
|
||||||
// Update formik field value with the updated tags array
|
// Update formik field value with the updated tags array
|
||||||
formik.setFieldValue('synonyms', currentTags);
|
formik.setFieldValue("synonyms", currentTags);
|
||||||
|
|
||||||
// Reset search state if needed
|
// Reset search state if needed
|
||||||
setTagsSearch(null);
|
setTagsSearch(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='tag'>
|
<div className="tag">
|
||||||
<input
|
<input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="tagInput"
|
className="tagInput"
|
||||||
|
|
@ -53,14 +51,10 @@ const Tag = ({ data, index }: { data: any, index: number }) => {
|
||||||
value={formik?.values?.synonyms[index]}
|
value={formik?.values?.synonyms[index]}
|
||||||
onChange={handleEditInputChange}
|
onChange={handleEditInputChange}
|
||||||
onBlur={handleInputBlur}
|
onBlur={handleInputBlur}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<FaTrash onClick={handleDeleteChoice}/>
|
<FaTrash onClick={handleDeleteChoice} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Tag;
|
export default Tag;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ export const useColumns = () => {
|
||||||
};
|
};
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const columns: TableColumnsType<tags> = [
|
const columns: TableColumnsType<tags> = [
|
||||||
{
|
{
|
||||||
title: t("columns.id"),
|
title: t("columns.id"),
|
||||||
|
|
@ -57,16 +55,10 @@ export const useColumns = () => {
|
||||||
placement="top"
|
placement="top"
|
||||||
title={t("practical.edit")}
|
title={t("practical.edit")}
|
||||||
color="#E0E0E0"
|
color="#E0E0E0"
|
||||||
|
|
||||||
>
|
>
|
||||||
<span onClick={() => handleEdit(record)}>
|
<span onClick={() => handleEdit(record)}>
|
||||||
<MdOutlineEdit
|
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
||||||
size={22}
|
|
||||||
style={{ color: "#A098AE" }}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,42 @@
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { lazy, Suspense } from 'react';
|
import { lazy, Suspense } from "react";
|
||||||
import { Spin } from "antd";
|
import { Spin } from "antd";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../enums/params";
|
import { ParamsEnum } from "../../enums/params";
|
||||||
import { useGetAllSubject } from "../../api/subject";
|
import { useGetAllSubject } from "../../api/subject";
|
||||||
import useSetPage_title from "../../Hooks/useSetPageTitle";
|
import useSetPageTitle from "../../Hooks/useSetPageTitle";
|
||||||
|
|
||||||
const Table = lazy(() => import('./Table'));
|
const Table = lazy(() => import("./Table"));
|
||||||
const AddModalForm = lazy(() => import('./Model/AddModel'));
|
const AddModalForm = lazy(() => import("./Model/AddModel"));
|
||||||
const EditModalForm = lazy(() => import('./Model/EditModel'));
|
const EditModalForm = lazy(() => import("./Model/EditModel"));
|
||||||
const DeleteModels = lazy(() => import('./Model/Delete'));
|
const DeleteModels = lazy(() => import("./Model/Delete"));
|
||||||
|
|
||||||
const TableHeader = () => {
|
const TableHeader = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const { subject_id} = useParams<ParamsEnum>();
|
const { subject_id } = useParams<ParamsEnum>();
|
||||||
|
|
||||||
const { data: Subject } = useGetAllSubject({
|
const { data: Subject } = useGetAllSubject({
|
||||||
show:subject_id
|
show: subject_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const SubjectName = Subject?.data?.name ?? "";
|
const SubjectName = Subject?.data?.name ?? "";
|
||||||
|
|
||||||
useSetPage_title(
|
useSetPageTitle(t(`page_header.subject`) + "/" + t(`${SubjectName}`));
|
||||||
t(`page_header.subject`) +
|
|
||||||
"/" +
|
|
||||||
t(`${SubjectName}`),
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
<Suspense fallback={<Spin/>}>
|
<Suspense fallback={<Spin />}>
|
||||||
<header>
|
<header>
|
||||||
<h6>
|
<h6>
|
||||||
{t("models.units")} {SubjectName}
|
{t("models.units")} {SubjectName}
|
||||||
</h6>
|
</h6>
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
<Table />
|
<Table />
|
||||||
<AddModalForm />
|
<AddModalForm />
|
||||||
<EditModalForm />
|
<EditModalForm />
|
||||||
<DeleteModels />
|
<DeleteModels />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../enums/params";
|
import { ParamsEnum } from "../../enums/params";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const {subject_id} = useParams<ParamsEnum>()
|
const { subject_id } = useParams<ParamsEnum>();
|
||||||
const response = useGetAllUnit({subject_id:subject_id, pagination: true});
|
const response = useGetAllUnit({ subject_id: subject_id, pagination: true });
|
||||||
console.log(response?.data?.data,"response?.data");
|
console.log(response?.data?.data, "response?.data");
|
||||||
|
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,20 +10,23 @@ import { useTranslation } from "react-i18next";
|
||||||
import { ABILITIES_ENUM } from "../../enums/abilities";
|
import { ABILITIES_ENUM } from "../../enums/abilities";
|
||||||
import { BsEyeFill } from "react-icons/bs";
|
import { BsEyeFill } from "react-icons/bs";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { canAddUnit, canDeleteUnit, canEditUnit, canShowUnit } from "../../utils/hasAbilityFn";
|
import {
|
||||||
|
canAddUnit,
|
||||||
|
canDeleteUnit,
|
||||||
|
canEditUnit,
|
||||||
|
canShowUnit,
|
||||||
|
} from "../../utils/hasAbilityFn";
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const { handel_open_model } = useModalHandler();
|
const { handel_open_model } = useModalHandler();
|
||||||
|
|
||||||
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handelShow = (record: any) => {
|
const handelShow = (record: any) => {
|
||||||
navigate(`${ABILITIES_ENUM?.UNIT}/${record?.id}`);
|
navigate(`${ABILITIES_ENUM?.UNIT}/${record?.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handelDelete = (data: any) => {
|
const handelDelete = (data: any) => {
|
||||||
setObjectToEdit(data);
|
setObjectToEdit(data);
|
||||||
handel_open_model(ModalEnum?.UNIT_DELETE);
|
handel_open_model(ModalEnum?.UNIT_DELETE);
|
||||||
|
|
@ -86,11 +89,7 @@ export const useColumns = () => {
|
||||||
color="#E0E0E0"
|
color="#E0E0E0"
|
||||||
>
|
>
|
||||||
<span onClick={() => handleEdit(record)}>
|
<span onClick={() => handleEdit(record)}>
|
||||||
<MdOutlineEdit
|
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
||||||
size={22}
|
|
||||||
style={{ color: "#A098AE" }}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|
@ -102,15 +101,12 @@ export const useColumns = () => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{canShowUnit && (
|
{canShowUnit && (
|
||||||
|
|
||||||
<BsEyeFill
|
<BsEyeFill
|
||||||
onClick={() => handelShow(record)}
|
onClick={() => handelShow(record)}
|
||||||
size={22}
|
size={22}
|
||||||
style={{ color: "green" }}
|
style={{ color: "green" }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ const Form = () => {
|
||||||
<Col>
|
<Col>
|
||||||
<ValidationField name="name" label="name" />
|
<ValidationField name="name" label="name" />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const ModalForm: React.FC = () => {
|
||||||
|
|
||||||
const { mutate, isSuccess, isLoading } = useAddLesson();
|
const { mutate, isSuccess, isLoading } = useAddLesson();
|
||||||
|
|
||||||
const {unit_id} = useParams<ParamsEnum>()
|
const { unit_id } = useParams<ParamsEnum>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
setIsOpen("");
|
setIsOpen("");
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const ModalForm: React.FC = () => {
|
||||||
const [inputValue, setInputValue] = useState("");
|
const [inputValue, setInputValue] = useState("");
|
||||||
|
|
||||||
const { mutate, isSuccess, isLoading } = useDeleteLesson();
|
const { mutate, isSuccess, isLoading } = useDeleteLesson();
|
||||||
const { objectToEdit,setObjectToEdit } = useObjectToEdit((state) => state);
|
const { objectToEdit, setObjectToEdit } = useObjectToEdit((state) => state);
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user