parent
98b14196a4
commit
613b6156f2
17 changed files with 595 additions and 50 deletions
@ -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; |
@ -0,0 +1,105 @@ |
||||
|
||||
|
||||
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 || []} |
||||
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…
Reference in new issue