Compare commits

..

2 Commits

  1. 13
      src/App.js
  2. 68
      src/components/AdminNav.js
  3. 1
      src/components/Table/Layouts/Main/components/Table.js
  4. 2
      src/components/Table/Layouts/Toolbar/index.js
  5. 12
      src/components/Table/components/Columns/index.js
  6. 4
      src/redux/actions/book.js
  7. 8
      src/redux/actions/exam.js
  8. 10
      src/redux/reducers/book.js
  9. 8
      src/redux/reducers/exam2.js
  10. 118
      src/view/Exam2/Exam.js
  11. 30
      src/view/Exam2/Header.js
  12. 55
      src/view/Exam2/Questions.js
  13. 2
      src/view/addExam/components/addQuestion.js
  14. 2
      src/view/addExam/index.js
  15. 1
      src/view/addExam/views/AddDescription.js
  16. 106
      src/view/school management/index.js
  17. 202
      src/view/school management/layouts/Editor.js

@ -45,6 +45,8 @@ import MyServices from "./view/my-services/MyServices";
import MobileMyServices from "./view/my-services/mobile/MyServices"; import MobileMyServices from "./view/my-services/mobile/MyServices";
import Exam from "./view/Exam2/Exam"; import Exam from "./view/Exam2/Exam";
import UserManagement from "./view/user-management"; import UserManagement from "./view/user-management";
import AdminNav from "./components/AdminNav";
import SchoolManagement from "./view/school management";
let data = [ let data = [
{ {
@ -682,13 +684,17 @@ function App() {
console.log("hhhhhhhh--------------------"); console.log("hhhhhhhh--------------------");
console.log(location.split("/")); console.log(location.split("/"));
return ( return (
<Provider store={store}> <Provider store={store}>
<div> <div>
<Router> <Router>
<div className="App"> <div className="App">
{LOGIN && !dontShowNav && <Header logOut={logOut} />} {LOGIN && !dontShowNav && <Header logOut={logOut} />}
{LOGIN && !dontShowNav && <Nav />} {LOGIN && !dontShowNav && !location.includes("adminpanel") && (
<Nav />
)}
{location.includes("adminpanel") && <AdminNav />}
<Routes> <Routes>
<Route <Route
path="/" path="/"
@ -745,7 +751,10 @@ function App() {
path="/adminpanel/user-management" path="/adminpanel/user-management"
element={<UserManagement />} element={<UserManagement />}
/> />
<Route
path="/adminpanel/schools"
element={<SchoolManagement/>}
/>
<Route <Route
path="/register" path="/register"
element={<Register activeLogin={activeLogin} />} element={<Register activeLogin={activeLogin} />}

@ -0,0 +1,68 @@
import React from "react";
import { useState } from "react";
import { Link } from "react-router-dom";
let data = [
{
name: "داشبورد",
link: "/",
},
{
name: "مدارس",
link: "schools",
},
{
name: "محصولات",
link: "products",
},
{
name: "کد تخفیف",
link: "discount_codes",
},
{
name: "اضافه کردن آزمون",
link: "add-exam",
},
{
name: "خروج",
link: "#",
},
];
let location = window.location.pathname;
let intial = 0;
if (location.includes("schools")) {
intial = 1;
} else if (location.includes("products")) {
intial = 2;
} else if (location.includes("discount_codes")) {
intial = 3;
} else if (location.includes("add-exam")) {
intial = 4;
}
const AdminNav = () => {
const [activeNav, setActiveNav] = useState(intial);
const changeNav = (index) => {
setActiveNav(index);
};
return (
<div className="w-[120px] h-screen fixed flex flex-col top-0 right-0 bg-white z-[10] border-l border-[#e5e5e5]">
{data?.map((item, index) => (
<Link
to={`/adminpanel/${item.link}`}
className="w-full flex-1 flex items-center justify-center text-sm cursor-pointer"
style={
index === activeNav
? { backgroundColor: "#df1452", color: "#fff" }
: null
}
onClick={() => changeNav(index)}
>
{item?.name}
</Link>
))}
</div>
);
};
export default AdminNav;

@ -126,6 +126,7 @@ const Table = ({
// className={isEven(idx) ? "bg-gray-600" : "bg-white"} // className={isEven(idx) ? "bg-gray-600" : "bg-white"}
> >
{row.cells.map((cell, index) => { {row.cells.map((cell, index) => {
// {console.log(cell)}
return ( return (
<td <td
key={index} key={index}

@ -39,7 +39,7 @@ export const Toolbar = ({
activeOtherTab={activeOtherTab} activeOtherTab={activeOtherTab}
setActiveOtherTab={setActiveOtherTab} setActiveOtherTab={setActiveOtherTab}
/> />
<div className="flex py-2 bg-[#df145277] items-center gap-2 px-2 bg-sky-200"> <div className="flex py-2 bg-[#df145277] items-center gap-2 px-2">
<TableSearch <TableSearch
globalFilter={globalFilter} globalFilter={globalFilter}
setGlobalFilter={setGlobalFilter} setGlobalFilter={setGlobalFilter}

@ -14,9 +14,7 @@ const Components = {
date: ({ value }) => { date: ({ value }) => {
// return format(new Date(value), "dd/MM/yyyy"); // return format(new Date(value), "dd/MM/yyyy");
// return moment(value).locale("fa").format("YYYY-MM-DD") // return moment(value).locale("fa").format("YYYY-MM-DD")
return moment(value, "YYYY/MM/DD") return moment(value, "YYYY/MM/DD").locale("fa").format("YYYY/MM/DD");
.locale("fa")
.format("YYYY/MM/DD")
}, },
OrderStatus, OrderStatus,
OrderLevel, OrderLevel,
@ -28,7 +26,7 @@ const Components = {
const Filters = { const Filters = {
SliderColumnFilter: SliderColumnFilter, SliderColumnFilter: SliderColumnFilter,
SelectFilter: SelectFilter, SelectFilter: SelectFilter,
ColumnSrarch:ColumnSearch ColumnSrarch: ColumnSearch,
}; };
export const COLUMNS = ({ export const COLUMNS = ({
@ -44,10 +42,10 @@ export const COLUMNS = ({
activeOtherTab, activeOtherTab,
}) => [ }) => [
...schema.map((e) => ({ ...schema.map((e) => ({
accessor: e?.name, accessor: e?.name || e?.foreignKey || "id",
Header: e?.description, Header: e?.description,
// Cell: e.renderer ? Components[e.renderer] : Components["text"], // Cell: e.renderer ? Components[e.renderer] : Components["text"],
Cell: e?.type ? Components[e.type] : Components["text"], Cell: e?.type ? Components[e.Component || e.type] : Components["text"],
Filter: e?.filter ? Filters[e.filter] : Filters["ColumnSrarch"], Filter: e?.filter ? Filters[e.filter] : Filters["ColumnSrarch"],
disableSortBy: e?.sort == false, disableSortBy: e?.sort == false,
Footer: "ستون " + e.description, Footer: "ستون " + e.description,
@ -80,8 +78,6 @@ export const COLUMNS = ({
}, },
]; ];
// Cell: ({ row }) => // Cell: ({ row }) =>
// Buttons({ // Buttons({
// row, // row,

@ -8,6 +8,10 @@ const book = {
(data = {}) => (data = {}) =>
async (dispatch) => async (dispatch) =>
await proxy.get("product/schoolUsers", data, { dispatch }), await proxy.get("product/schoolUsers", data, { dispatch }),
schoolList:
(data = {}) =>
async (dispatch) =>
await proxy.get("product/schoolList", data, { dispatch }),
info: info:
(data = {}) => (data = {}) =>
async (dispatch) => async (dispatch) =>

@ -25,6 +25,14 @@ const exam = {
(data = {}) => (data = {}) =>
async (dispatch) => async (dispatch) =>
await proxy.get("exam/start", data, { dispatch }), await proxy.get("exam/start", data, { dispatch }),
end:
(data = {}) =>
async (dispatch) =>
await proxy.post("exam/end", data, { dispatch }),
setAnswer:
(data = {}) =>
async (dispatch) =>
await proxy.post("exam/set/answer", data, { dispatch }),
emptySubexamList: (data = {}) => { emptySubexamList: (data = {}) => {
return (dispatch) => { return (dispatch) => {
dispatch({ dispatch({

@ -4,7 +4,7 @@ const initialState = {
loading: false, loading: false,
error: null, error: null,
list: [], list: [],
schoolUserList :[], schoolUserList: [],
info: null, info: null,
searchResult: [], searchResult: [],
filterResult: [], filterResult: [],
@ -16,6 +16,8 @@ const initialState = {
sortFilterCourse: null, sortFilterCourse: null,
selectedGrade: null, selectedGrade: null,
selectedSort: "پربازدید ترین ها", selectedSort: "پربازدید ترین ها",
schoolList: [],
schema: [],
}; };
const grades = [ const grades = [
@ -62,9 +64,11 @@ export default function book(state = initialState, action) {
}; };
case "product/info": case "product/info":
return { ...state, loading: false, info: data, error: null }; return { ...state, loading: false, info: data, error: null };
case "product/schoolList":
return { ...state, loading: false, schoolList: data,schema: schema, error: null };
case "product/schoolUsers": case "product/schoolUsers":
console.log("{{{{{{-..-}}}}}}}") console.log("{{{{{{-..-}}}}}}}");
console.log(action) console.log(action);
return { return {
...state, ...state,
loading: false, loading: false,

@ -11,7 +11,9 @@ const initialState = {
subExamList: [], subExamList: [],
lastSubExamAdd:null, lastSubExamAdd:null,
list:null, list:null,
confirm:null confirm:null,
lastAnswer:null,
end:null
}; };
export default function exam2(state = initialState, action) { export default function exam2(state = initialState, action) {
let { type, data } = action; let { type, data } = action;
@ -20,6 +22,8 @@ export default function exam2(state = initialState, action) {
return { ...state, loading: false, info: data, error: null }; return { ...state, loading: false, info: data, error: null };
case "exam/preview": case "exam/preview":
return { ...state, loading: false, preview: data, error: null }; return { ...state, loading: false, preview: data, error: null };
case "exam/set/answer":
return { ...state, loading: false, lastAnswer: data, error: null };
case "exam/confirm": case "exam/confirm":
toast.success("درخواست با موفقیت انجام شد"); toast.success("درخواست با موفقیت انجام شد");
return { ...state, loading: false, confirm: data, error: null }; return { ...state, loading: false, confirm: data, error: null };
@ -28,6 +32,8 @@ export default function exam2(state = initialState, action) {
return { ...state, loading: false, error: null, lastExamAdd: data.id }; return { ...state, loading: false, error: null, lastExamAdd: data.id };
case "exam/start": case "exam/start":
return { ...state, loading: false, list: data, error: null }; return { ...state, loading: false, list: data, error: null };
case "exam/end":
return { ...state, loading: false, end: data, error: null };
case "exam/subexamAdd": case "exam/subexamAdd":
toast.success("درخواست با موفقیت انجام شد"); toast.success("درخواست با موفقیت انجام شد");
return { return {

@ -2,29 +2,131 @@ import Header from "./Header";
import Questions from "./Questions"; import Questions from "./Questions";
import "./index.css"; import "./index.css";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { exam } from "../../redux/actions";
import { Link, useParams } from "react-router-dom";
import { useEffect } from "react";
import { useState } from "react";
let loadingCondition = false;
const Exam = ({
const Exam = ({ examData }) => { examData,
setAnswer,
endExam,
startExam,
examLoading,
end,
}) => {
const { id } = useParams();
console.log("Exam render=========================");
console.log("||||||||||||||||||||||||||||"); console.log("||||||||||||||||||||||||||||");
console.log(examData); console.log(examData);
const [endBox, setEndBox] = useState(false);
//getData after refresh-------------------------------------------
useEffect(() => {
console.log(examData);
if (!examData) {
// alert("hooo");
startExam({
examId: id,
});
}
}, []);
//active endBox================================
useEffect(() => {
if(end){
setEndBox(true);
}
}, [end]);
return ( return (
<div <div
className="Exam w-[100vw] px-28 pt-16 pb-8 relative" className="Exam w-[100vw] min-h-screen px-28 pt-16 pb-8 relative z-[200] bg-[#fff]"
style={{ width: "calc(100vw - 5px)" }} style={{ width: "calc(100vw - 5px)" }}
> >
<Header /> {examData && <Header info={examData?.exam} examData={examData} />}
<Questions questions={examData?.questions} /> {examData && examData (
<Questions
questions={examData?.questions}
setAnswer={setAnswer}
endExam={endExam}
info={examData?.exam}
/>
)}
{examLoading && !examData && (
<div className="w-full text-center text-xl rtl mt-8">
در حال گرفتن اطلاعات..
</div>
)}
{endBox && (
<div className="w-screen h-screen flex items-center justify-center fixed top-0 left-0 backdrop-blur-xl bg-[#ffffff20] z-[300] p-3 overflow-hidden">
<div className="w-3/4 h-2/3 rounded-lg bg-white border border-[#c9c9c9]">
<div className="w-full h-1/5 flex items-center justify-center text-center text-xl rtl bg-green-600 text-white rounded-t">
جواب های شما با موفقیت ثبت شد.
</div>
<div className="w-full h-1/5 flex items-center justify-center text-center text-xl rtl">
نتیجه اولیه:
</div>
<div className="w-full h-2/5 px-6">
<div className="w-full h-1/3 flex rtl bg-red52 rounded-t">
<div className="flex-1 h-full flex items-center justify-center px-1 text-xs text-white">
تعداد گزینه صحیح
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 text-xs text-white">
تعداد گزینه غلط
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 text-xs text-white">
تعداد گزینه بدون جواب
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 text-xs text-white">
درصد
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 text-xs text-white">
نمره ({end?.totalPoint})
</div>
</div>
<div className="w-full h-1/3 flex rtl border border-red52 rounded-b bg-white">
<div className="flex-1 h-full flex items-center justify-center px-1 text-sm">
{end?.correct}
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 rtl text-sm">
{end?.incorrect}
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 rtl text-sm">
{end?.notAnswerd}
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 ltr text-sm">
{end?.percent}
</div>
<div className="flex-1 h-full flex items-center justify-center px-1 ltr text-sm">
{end?.point}
</div>
</div>
</div>
<div className="w-full h-1/5 flex items-center justify-center">
<Link
to="/services"
className="p-4 text-base text-white bg-red52 rounded cursor-pointer"
>
خروج از آزمون
</Link>
</div>
</div>
</div>
)}
</div> </div>
); );
}; };
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
examData : state.exam2.list examData: state.exam2.list,
examLoading: state.exam2.loading,
end: state.exam2.end,
}); });
const mapDispatchToProps = { const mapDispatchToProps = {
setAnswer: exam.setAnswer,
endExam: exam.end,
startExam: exam.start,
}; };
export default connect(mapStateToProps, mapDispatchToProps)(Exam); export default connect(mapStateToProps, mapDispatchToProps)(Exam);

@ -1,9 +1,18 @@
import { useState } from "react"; import { useEffect, useState } from "react";
import { RiTimerLine } from "react-icons/ri"; import { RiTimerLine } from "react-icons/ri";
import './index.css'; import './index.css';
const Header=()=>{ const Header = ({ info, examData }) => {
console.log("header render===================");
const [timer, setTimer] = useState(null);
useEffect(() => {
if (info?.duration === info?.remainingTime) {
setTimer(info?.duration);
} else {
setTimer(info?.remainingTime +1);
}
}, [info]);
return ( return (
<div className="Header w-full h-14 fixed top-2 left-0 px-28 bg-white"> <div className="Header w-full h-14 fixed top-2 left-0 px-28 bg-white">
<div className="w-full h-full flex flex-row-reverse items-center justify-between rounded-lg border border-[#ECECEC] px-6"> <div className="w-full h-full flex flex-row-reverse items-center justify-between rounded-lg border border-[#ECECEC] px-6">
@ -11,25 +20,28 @@ const Header=()=>{
className="text-right text-sm text-right" className="text-right text-sm text-right"
style={{ width: "calc(100% - 220px)" }} style={{ width: "calc(100% - 220px)" }}
> >
آزمون تیزهوشان درس تاریخ باستان {info?.name}
</div> </div>
<div className="w-52 flex items-center gap-x-2"> <div className="w-52 flex items-center gap-x-2">
<div className="w-[30%]"> <div className="w-[30%]">
<Timer/> {timer && <Timer timer={timer} />}
</div>
<div className="text-sm" style={{ direction: "rtl" }}>
زمان باقیمانده :
</div> </div>
<div className="text-sm" style={{direction:'rtl'}}>زمان باقیمانده :</div>
<RiTimerLine className="text-xl text-[#DF1452]" /> <RiTimerLine className="text-xl text-[#DF1452]" />
</div> </div>
</div> </div>
</div> </div>
); );
} };
export default Header; export default Header;
const Timer = ({ cellphone }) => { const Timer = ({ timer }) => {
const [min, setMin] = useState(10); console.log(timer);
const [sec, setSec] = useState(30); const [min, setMin] = useState(timer);
const [sec, setSec] = useState(0);
const [showBtn, setShowbtn] = useState(false); const [showBtn, setShowbtn] = useState(false);
setTimeout(() => { setTimeout(() => {

@ -1,6 +1,6 @@
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { RiErrorWarningLine } from "react-icons/ri"; import { RiErrorWarningLine } from "react-icons/ri";
import './index.css'; import "./index.css";
import img1 from "../../assets/img/4bea9a991c6b23d3dcaf231513ee94bd.jpg"; import img1 from "../../assets/img/4bea9a991c6b23d3dcaf231513ee94bd.jpg";
// let data = [ // let data = [
@ -76,17 +76,17 @@ import img1 from "../../assets/img/4bea9a991c6b23d3dcaf231513ee94bd.jpg";
// ]; // ];
//badgeList------------- //badgeList-------------
let badgeList = ["الف", "ب", "ج", "د","هـ","ز"]; let badgeList = ["الف", "ب", "ج", "د", "هـ", "ز"];
const Questions = ({questions}) => { const Questions = ({ questions, setAnswer, endExam ,info}) => {
const [Data, setData] = useState(null); const [Data, setData] = useState(null);
console.log("exam render-----------------") console.log("Questions render-----------------");
console.log(Data); console.log(Data);
const [fake, setFake] = useState(0); const [fake, setFake] = useState(0);
const [layoutTrigger,setLayoutTrigger]=useState(0); const [layoutTrigger, setLayoutTrigger] = useState(0);
const [answerList, setAnswerList] = useState([]); const [answerList, setAnswerList] = useState([]);
//create local data from api data ------------------------------------- //create local data from api data -------------------------------------
const createChoices=(item)=>{ const createChoices = (item) => {
let list = []; let list = [];
let options = [ let options = [
item["question.option1"], item["question.option1"],
@ -98,14 +98,14 @@ const Questions = ({questions}) => {
for (let i = 0; i < item["question.type"]; i++) { for (let i = 0; i < item["question.type"]; i++) {
list.push(options[i]); list.push(options[i]);
} }
return(list) return list;
} };
useEffect(() => { useEffect(() => {
let newList =[]; let newList = [];
console.log("create data useEffect------------------------"); console.log("create data useEffect------------------------");
for (let i = 0; i < questions?.length; i++) { for (let i = 0; i < questions?.length; i++) {
newList.push({ newList.push({
id: questions[i]["question.id"], id: questions[i].id,
text: questions[i]["question.text"], text: questions[i]["question.text"],
fileId: questions[i]["question.fileId"], fileId: questions[i]["question.fileId"],
choices: createChoices(questions[i]), choices: createChoices(questions[i]),
@ -114,10 +114,12 @@ const Questions = ({questions}) => {
choiceHeight: null, choiceHeight: null,
}); });
} }
setData(newList);
console.log("created data-----------------------"); console.log("created data-----------------------");
console.log(newList); console.log(newList);
setFake(Math.random()*10000); if(newList.length>0){
setData(newList);
}
setFake(Math.random() * 10000);
setLayoutTrigger(Math.random() * 10000); setLayoutTrigger(Math.random() * 10000);
}, [questions]); }, [questions]);
//-------------------------------------------------- //--------------------------------------------------
@ -128,6 +130,7 @@ const Questions = ({questions}) => {
); );
console.log(Data); console.log(Data);
if (Data) { if (Data) {
console.log("layout setting start----------");
let newData = Data; let newData = Data;
let data = Data; let data = Data;
let defaultAnswers = []; let defaultAnswers = [];
@ -179,9 +182,12 @@ const Questions = ({questions}) => {
newData[i].choiceWidth = "full"; newData[i].choiceWidth = "full";
} }
} }
console.log(newData);
setData(newData); setData(newData);
setAnswerList(defaultAnswers); setAnswerList(defaultAnswers);
setFake(fake + 1); setFake(fake + 1);
}else{
// setLayoutTrigger(Math.random() * 10000);
} }
}, [questions, layoutTrigger]); }, [questions, layoutTrigger]);
@ -202,6 +208,21 @@ const Questions = ({questions}) => {
setFake(fake + 1); setFake(fake + 1);
}; };
//submit answer ===================================
const submitAnswer = (id, answer) => {
setAnswer({
userAnswerId: id,
answer: answer,
});
};
//end exam ============================
const endExamHandler =()=>{
endExam({
userExamId: info.id,
});
}
return ( return (
<div className="Questions w-full mt-10"> <div className="Questions w-full mt-10">
{Data?.map((item, index) => ( {Data?.map((item, index) => (
@ -248,7 +269,10 @@ const Questions = ({questions}) => {
? { width: `${item.choiceWidth}%` } ? { width: `${item.choiceWidth}%` }
: null : null
} }
onClick={() => chooseHandler(index, INDEX)} onClick={() => {
chooseHandler(index, INDEX);
submitAnswer(item.id, choice);
}}
> >
<div <div
className="w-14 py-4 flex items-center justify-center text-sm rounded-r-md bg-[#D5DEEA]" className="w-14 py-4 flex items-center justify-center text-sm rounded-r-md bg-[#D5DEEA]"
@ -308,7 +332,10 @@ const Questions = ({questions}) => {
کلیک کنید کلیک کنید
</div> </div>
</div> </div>
<div className="w-full h-12 rounded-md flex items-center justify-center bg-[#DF1452] text-white cursor-pointer mt-6"> <div
className="w-full h-12 rounded-md flex items-center justify-center bg-[#DF1452] text-white cursor-pointer mt-6"
onClick={endExamHandler}
>
ثبت پاسخها و اتمام آزمون ثبت پاسخها و اتمام آزمون
</div> </div>
</div> </div>

@ -128,7 +128,7 @@ const AddQuestionPopUp = ({
</button> </button>
<button <button
className=" bg-green-500 text-xl text-white border-green-500 w-full ml-0 mx-3 h-12 rounded-md border" className=" bg-green-500 text-xs text-white border-green-500 w-full ml-0 mx-3 h-12 rounded-md border "
onClick={submitOnClick} onClick={submitOnClick}
> >
ثبت سوال ثبت سوال

@ -64,7 +64,7 @@ const AddExam = () => {
] ]
return( return(
<div className='flex flex-col w-[96%] overflow-scroll overflow-x-hidden py-[4%] bg-grayFD rtl' style={{height: '100vh'}}> <div className='flex flex-col overflow-scroll overflow-x-hidden py-[4%] bg-grayFD rtl' style={{height: '100vh',width:"calc(100vw - 120px)"}}>
<div className='flex w-full items-center py-2 pb-5 px-10 border-b border-gray-300'> <div className='flex w-full items-center py-2 pb-5 px-10 border-b border-gray-300'>
<h1 className="text-blue3A text-lg font-bold w-1/5 text-right px-4 border-r-4 border-blue65"> <h1 className="text-blue3A text-lg font-bold w-1/5 text-right px-4 border-r-4 border-blue65">
ساخت آزمون جدید ساخت آزمون جدید

@ -106,6 +106,7 @@ const AddExamDescription = ({
parentAdd({ parentAdd({
name: name, name: name,
description: description, description: description,
gradeId: addExamState.grade,
// startDate: moment( // startDate: moment(
// `${addExamState.startDate?.year}/${addExamState.startDate?.month}/${addExamState.startDate?.day} ${addExamState.startDate?.hour}:${addExamState.startDate?.minute}` // `${addExamState.startDate?.year}/${addExamState.startDate?.month}/${addExamState.startDate?.day} ${addExamState.startDate?.hour}:${addExamState.startDate?.minute}`
// ) // )

@ -0,0 +1,106 @@
import React, { useMemo, useState } from "react";
import { useEffect } from "react";
import { connect } from "react-redux";
import Table from "../../components/Table";
import * as actions from "../../redux/actions";
import Editor from "./layouts/Editor";
const source = "book";
const title = " مدیریت کاربران";
const SchoolMangement = ({
info,
getData,
tabs,
setTabs,
add,
update,
getSchoolList,
schoolList,
schoolUserList,
schema,
}) => {
useMemo(() => {
// getData({ num: 1000 });
getSchoolList();
}, []);
// console.log(info);
console.log("SchoolManagement render---------------------------------");
console.log(schoolList);
console.log(schema);
console.log(info);
// console.log("==============^tabs^==============");
// console.log(tabs);
useEffect(() => {
setTabs([
{
id: 0,
name: title,
isActive: true,
element: "table",
},
]);
}, []);
// console.log(tabs);
// const [tabs, setTabs] = useState([
// {
// id: 0,
// name: title,
// isActive: true,
// },
// ]);
const [activeOtherTab, setActiveOtherTab] = useState(false);
const [fake, setFake] = useState(0);
const [schoolId, setSchoolId] = useState(null);
const [setp, setStep] = useState(1);
const submitHandler = () => {
getData({ id: schoolId });
setStep(2);
};
return (
<div
className="UserManagement w-[95.5%] h-screen max-h-screen bg-[#F8F8F8] overflow-y-auto rtl relative"
// style={{ width: "calc(100% - 4.5%)" }}
>
<div className="flex flex-1 w-full pt-12 pb-4">
<Table
// data={schoolList || []}
data={[]}
schema={schema || []}
Editor={Editor}
add={add}
update={update}
getData={getData}
title={title}
tabs={tabs}
setTabs={setTabs}
fake={fake}
setFake={setFake}
activeOtherTab={activeOtherTab}
setActiveOtherTab={setActiveOtherTab}
/>
</div>
</div>
);
};
const mapStateToProps = (state) => ({
info: state[source],
tabs: state.table.tabs,
schoolList: state.book.schoolList,
schoolUserList: state.book.schoolUserList,
schema:state.book.schema
});
const mapDispatchToProps = {
// getData: actions[source].list,
getData: actions[source].schoolUser,
setTabs: actions.table.setTab,
update: actions[source].update,
add: actions[source].add,
getSchoolList: actions.book.schoolList,
};
export default connect(mapStateToProps, mapDispatchToProps)(SchoolMangement);

@ -0,0 +1,202 @@
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { file } from "../../../redux/actions";
import loadingGiff from "../../../assets/img/Rolling-1s-200px.gif";
import SimpleDatePicker from "../../../components/SimpleDatePicker";
import moment from "jalali-moment";
const baseUrl = "https://light.barnamenegar.com/api/v1";
const components = (props) => ({
text: (
<input
type="text"
className="table-edit-input w-full py-3 px-2 rounded-md border border-[#D5DEEA]"
{...props}
/>
),
string: (
<textarea
type="text"
className="table-edit-input w-full py-3 px-2 rounded-md border border-[#D5DEEA]"
{...props}
/>
),
number: (
<input
type="number"
className="table-edit-input w-full py-3 px-2 rounded-md border border-[#D5DEEA]"
{...props}
/>
),
select: (
<select
type="text"
className="table-edit-input w-full py-3 px-2 rounded-md border border-[#D5DEEA]"
{...props}
>
{Object.entries(props?.options || {}).map(([v, k]) => (
<option value={v} key={v}>
{k}
</option>
))}
</select>
),
file: (
<div className="table-edit-input w-full py-3 px-2 rounded-md border border-[#D5DEEA] flex justify-between bg-[#fff]">
<div className="w-full flex items-center">
<div
className="w-fit w-24 text-center py-1 rounded bg-[#111] text-white text-sm cursor-pointer"
onClick={props.chooseFile}
>
انتخاب فایل
</div>
{/* <div className="text-xs mt-2 text-right">{props.fileNmae}</div> */}
{props.fileNmae && !props.loading && (
<div
className="w-fit w-24 py-1 rounded bg-[#65A9FF] text-white text-sm mr-2 cursor-pointer"
onClick={props.uploadHandler}
>
آپلود
</div>
)}
{props.loading && (
<img src={loadingGiff} alt="loadingGiff" className="h-10 mr-2" />
)}
<input
className="edit-file-input w-0 h-0 hidden"
id="edit-file-input"
type={"file"}
// onChange={(e) => {
// props.setFileName(e.target.value);
// }}
onChange={(e) => props.fileInputHandler(e)}
/>
</div>
{props.defaultValue && !props?.fileNmae ? (
<img
src={baseUrl + "/file/" + props.defaultValue}
className="edit-file-img-placeholder h-10"
/>
) : null}
{props?.fileNmae && (
<img src={props?.fileNmae} className="edit-file-img-placeholder h-10" />
)}
</div>
),
date: (
<div className="w-full">
<SimpleDatePicker returnValue={props.setDateInfo} mode={props.mode} />
</div>
),
});
const Filed = (props) => {
return components(props)[props.type] || <div>{props.type}</div>;
};
const Editor = ({ data, schema, update, add, loading,lastUpload,uploadFile }) => {
const [info, setInfo] = useState(data ? { id: data?.original?.id } : {});
const changeInputHandler = (e, key) => {
setInfo({ ...info, [key]: e.target.value });
};
useEffect(() => {
if (lastUpload) {
setInfo({ ...info, fileId: String(lastUpload) });
}
}, [lastUpload]);
const submitHandler = () => {
if (data) update(info);
else add(info);
console.log(info);
};
const [fileNmae, setFileName] = useState(null);
const chooseFile = () => {
document.querySelector(".edit-file-input").click();
};
const fileInputHandler = (e) => {
console.log(e.target.value);
if (e.target.files && e.target.files[0]) {
var reader = new FileReader();
reader.onload = function (event) {
setFileName(event.target.result);
};
reader.readAsDataURL(e.target.files[0]);
}
};
const uploadHandler=()=>{
uploadFile({
file: document.querySelector("#edit-file-input").files[0],
});
}
const [dateInfo,setDateInfo]=useState(null);
const datehandler=(value,mode)=>{
setDateInfo({ ...value,mode});
}
useEffect(() => {
console.log("::::::::::::::::::::::::::::::::::::::::::::-")
console.log(dateInfo);
if(dateInfo?.day){
setInfo({
...info,
[dateInfo.mode]: moment(
`${dateInfo?.year}/${dateInfo?.month}/${dateInfo?.day}`
)
.locale("en")
.format("YYYY-MM-DD"),
});
}
}, [dateInfo]);
return (
<div className="w-full py-3" key={data?.id || 0}>
{console.log({ data })}
<div className="w-full flex rtl flex-wrap items-center justify-between gap-y-6">
{schema?.map((item, index) => (
<div key={index} className="w-1/2 shrink-0 flex items-center ">
<div className="w-1/6 text-sm ml-2">{item?.description}:</div>
<Filed
type={
item?.options
? "select"
: item.name == "fileId"
? "file"
: item?.type
}
options={item?.options}
defaultValue={data?.original[item?.name]}
onChange={(e) => changeInputHandler(e, item?.name)}
fileNmae={fileNmae}
setFileName={setFileName}
chooseFile={chooseFile}
fileInputHandler={fileInputHandler}
uploadHandler={uploadHandler}
loading={loading}
setDateInfo={datehandler}
mode={item?.name}
/>
</div>
))}
</div>
<div
className="px-6 py-4 w-fit rounded-md bg-[#df1452] text-[#fff] text-base cursor-pointer mx-auto mt-6"
onClick={submitHandler}
>
{data ? "ثبت تغییرات" : "ثبت ردیف"}
</div>
</div>
);
};
const mapStateToProps = (state) => ({
loading: state.file.loading,
lastUpload: state.file.lastUpload,
});
const mapDispatchToProps = {
uploadFile : file.upload
};
export default connect(mapStateToProps, mapDispatchToProps)(Editor);
Loading…
Cancel
Save