So Many Changes

Calendar Component Changed For This Project
MyExamList Component Made
MyExam Carousel Made
Dashboard Completed
main
Pedram Keshavarzi 3 years ago
parent b3794beafa
commit 534b0946cd
  1. 11
      package-lock.json
  2. 1
      package.json
  3. 13
      src/App.js
  4. 9
      src/assets/img/stickynote.svg
  5. 4
      src/assets/img/vuesax-linear-direct-left.svg
  6. 341
      src/components/Calendar/CalendarComponents/Calendar.js
  7. 672
      src/components/Calendar/CalendarComponents/DatePicker.css
  8. 203
      src/components/Calendar/CalendarComponents/DatePicker.js
  9. 93
      src/components/Calendar/CalendarComponents/DatePickerInput.js
  10. 399
      src/components/Calendar/CalendarComponents/components/DaysList.js
  11. 168
      src/components/Calendar/CalendarComponents/components/Header.js
  12. 74
      src/components/Calendar/CalendarComponents/components/MonthSelector.js
  13. 99
      src/components/Calendar/CalendarComponents/components/YearSelector.js
  14. 4
      src/components/Calendar/CalendarComponents/components/index.js
  15. 187
      src/components/Calendar/CalendarComponents/dateBox.css
  16. 3
      src/components/Calendar/CalendarComponents/index.js
  17. 104
      src/components/Calendar/CalendarComponents/shared/constants.js
  18. 69
      src/components/Calendar/CalendarComponents/shared/generalUtils.js
  19. 10
      src/components/Calendar/CalendarComponents/shared/hooks.js
  20. 44
      src/components/Calendar/CalendarComponents/shared/keyboardNavigation.js
  21. 85
      src/components/Calendar/CalendarComponents/shared/localeLanguages.js
  22. 61
      src/components/Calendar/CalendarComponents/shared/localeUtils.js
  23. 33
      src/components/Calendar/CalendarComponents/shared/sliderHelpers.js
  24. 817
      src/components/Calendar/index.css
  25. 117
      src/components/Calendar/index.js
  26. 298
      src/components/exam/Carousel/index.css
  27. 355
      src/components/exam/Carousel/index.js
  28. 470
      src/components/exam/Carousel/state.js
  29. 22
      src/components/exam/carousel-item/index.js
  30. 202
      src/components/exam/resault/index.css
  31. 163
      src/components/exam/resault/index.js
  32. 2
      src/components/header/Header.js
  33. 2
      src/components/nav/Nav.js
  34. 31
      src/view/dashboard/Dashboard.js
  35. 97
      src/view/dashboard/LastActivity.js
  36. 4
      src/view/messages/Messages.js
  37. 5
      yarn.lock

11
package-lock.json generated

@ -12,6 +12,7 @@
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"axios": "^0.25.0",
"jalaali-js": "^1.2.3",
"jalali-moment": "^3.3.10",
"lord-icon-element": "^3.3.3",
"lottie-web": "^5.8.1",
@ -9402,6 +9403,11 @@
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
},
"node_modules/jalaali-js": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.3.tgz",
"integrity": "sha512-irl0pXL59Xl0Oz6jyOiJed/NxrVeS6fSx6a8atQOH/LsPWPZwBCxwe5XVEIqjnwt69FRxvnCCwQn5dTMxwbazQ=="
},
"node_modules/jalali-moment": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/jalali-moment/-/jalali-moment-3.3.11.tgz",
@ -24081,6 +24087,11 @@
}
}
},
"jalaali-js": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.3.tgz",
"integrity": "sha512-irl0pXL59Xl0Oz6jyOiJed/NxrVeS6fSx6a8atQOH/LsPWPZwBCxwe5XVEIqjnwt69FRxvnCCwQn5dTMxwbazQ=="
},
"jalali-moment": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/jalali-moment/-/jalali-moment-3.3.11.tgz",

@ -7,6 +7,7 @@
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"axios": "^0.25.0",
"jalaali-js": "^1.2.3",
"jalali-moment": "^3.3.10",
"lord-icon-element": "^3.3.3",
"lottie-web": "^5.8.1",

@ -652,7 +652,14 @@ function App() {
{LOGIN && <Header />}
{LOGIN && <Nav logOut={logOut} />}
<Routes>
<Route path="/" element={<LoginSignUp activeLogin={activeLogin}/>} />
<Route path="/" element={LOGIN ?
<Dashboard
ActiveUserFullInfo={ActiveUserFullInfo}
UserFullInfoData={UserFullInfoData}
showUserFullInfo={showUserFullInfo}
hideUserFullInfo={hideUserFullInfo}
/>
: <LoginSignUp activeLogin={activeLogin}/>} />
<Route
path="/login"
element={
@ -674,12 +681,12 @@ function App() {
<Route path="/accounting" element={<Accounting />} />
<Route path="/messages" element={<Messages />} />
<Route path="/services" element={<Services />} />
<Route path="/dashboard" element={ <Dashboard
{/* <Route path="/dashboard" element={ <Dashboard
ActiveUserFullInfo={ActiveUserFullInfo}
UserFullInfoData={UserFullInfoData}
showUserFullInfo={showUserFullInfo}
hideUserFullInfo={hideUserFullInfo}
/>} />
/>} /> */}
<Route path='/contacts' element={<ContactUs />} />
</Routes>
</div>

@ -0,0 +1,9 @@
<svg id="stickynote" xmlns="http://www.w3.org/2000/svg" width="24.591" height="24" viewBox="0 0 24.591 24">
<path id="Vector" d="M0,0V3" transform="translate(16.394 2)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-2" data-name="Vector" d="M0,0V3" transform="translate(8.197 2)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-3" data-name="Vector" d="M8,0H0" transform="translate(9.332 11)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-4" data-name="Vector" d="M5,0H0" transform="translate(12.373 15)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-5" data-name="Vector" d="M6.2,18.5h6.2c5.164,0,6.2-2.06,6.2-6.18V6.15c0-4.7-1.725-5.96-5.164-6.15H5.164C1.725.18,0,1.45,0,6.15V12.5" transform="translate(3 3.5)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-6" data-name="Vector" d="M0,0,6,6V3A2.652,2.652,0,0,0,3,0Z" transform="translate(3 16)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"/>
<path id="Vector-7" data-name="Vector" d="M24.591,0H0V24H24.591Z" fill="none" opacity="0"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40.245" height="40.245" viewBox="0 0 40.245 40.245">
<g id="vuesax_linear_direct-left" data-name="vuesax/linear/direct-left" transform="translate(-364 -252)">
<g id="direct-left" transform="translate(364 252)">
<path id="Vector" d="M2.867,10.872,22.3.644A5.362,5.362,0,0,1,29.6,7.787L26.88,13.22a5.363,5.363,0,0,0,0,4.8L29.6,23.449A5.364,5.364,0,0,1,22.3,30.593L2.867,20.364A5.361,5.361,0,0,1,2.867,10.872Z" transform="translate(5.031 4.504)" fill="#267de9"/>
<path id="Vector-2" data-name="Vector" d="M0,0H40.245V40.245H0Z" transform="translate(40.245 40.245) rotate(180)" fill="#267de9" opacity="0"/>
<path id="Vector" d="M2.867,10.872,22.3.644A5.362,5.362,0,0,1,29.6,7.787L26.88,13.22a5.363,5.363,0,0,0,0,4.8L29.6,23.449A5.364,5.364,0,0,1,22.3,30.593L2.867,20.364A5.361,5.361,0,0,1,2.867,10.872Z" transform="translate(5.031 4.504)" fill="#df1452"/>
<path id="Vector-2" data-name="Vector" d="M0,0H40.245V40.245H0Z" transform="translate(40.245 40.245) rotate(180)" fill="#df1452" opacity="0"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 691 B

After

Width:  |  Height:  |  Size: 691 B

@ -0,0 +1,341 @@
import React, { useState, useRef, useEffect } from 'react';
import moment from "jalali-moment";
import './dateBox.css'
import {
getDateAccordingToMonth,
shallowClone,
getValueType,
} from './shared/generalUtils';
import {
TYPE_SINGLE_DATE,
TYPE_RANGE,
TYPE_MUTLI_DATE,
} from './shared/constants';
import { useLocaleUtils, useLocaleLanguage } from './shared/hooks';
import { Header, MonthSelector, YearSelector, DaysList } from './components';
import { VscCircleFilled } from "react-icons/vsc";
import { GoPrimitiveDot } from "react-icons/go";
// import { IoDocumentTextOutline } from "react-icons/io";
// import Exam from '../azmoon-list/Exam';
import { IoDocumentTextOutline } from "react-icons/io5";
const Clock = () => {
let today = new Date();
let h = today.getHours();
let m = today.getMinutes();
// const [h,setH]=useState(today.getHours());
// const [m, setM] = useState(today.getMinutes());
// const [s, setS] = useState(today.getSeconds());
const [counter, setCounter] = useState(0);
setTimeout(() => {
setCounter(counter + 1);
}, 1000);
return (
<div
className="header-date-and-time-time text-color2 text-sm"
style={{ fontFamily: "IRANSansXFaNum-Regular" }}
>
<span className="header-date-and-time-number text-red52 ml-2"> ساعت </span>
{h < 10 ? "0" + h : h}:{m < 10 ? "0" + m : m}
</div>
);
}
var today = new Date();
// var time = today.getHours() + ":" + today.getMinutes();
let m = moment();
// -------get-date--------------------
let date = m.jDate();
//----------get-day-and month------------------
let day = m.jDay();
let monthNum = m.jMonth() + 1;
//create-week---------------------------
let date_list;
let active_list;
const Calendar = ({
value,
onChange,
onDisabledDayError,
calendarClassName,
calendarTodayClassName,
calendarSelectedDayClassName,
calendarRangeStartClassName,
calendarRangeBetweenClassName,
calendarRangeEndClassName,
disabledDays,
colorPrimary,
colorPrimaryLight,
slideAnimationDuration,
minimumDate,
maximumDate,
selectorStartingYear,
selectorEndingYear,
locale,
shouldHighlightWeekends,
renderFooter,
customDaysClassName,
events,
renderEvents,
type
}) => {
const calendarElement = useRef(null);
const [mainState, setMainState] = useState({
activeDate: null,
monthChangeDirection: '',
isMonthSelectorOpen: false,
isYearSelectorOpen: false,
});
const [eventInFooter, setEventInFooter] = useState(null);
useEffect(() => {
const handleKeyUp = ({ key }) => {
/* istanbul ignore else */
if (key === 'Tab')
calendarElement.current.classList.remove('-noFocusOutline');
};
calendarElement.current.addEventListener('keyup', handleKeyUp, false);
return () => {
// calendarElement.current.removeEventListener('keyup', handleKeyUp, false);
};
});
const { getToday } = useLocaleUtils(locale);
const { weekDays: weekDaysList, isRtl } = useLocaleLanguage(locale);
const today = getToday();
const createStateToggler = (property) => () => {
setMainState({ ...mainState, [property]: !mainState[property] });
};
const toggleMonthSelector = createStateToggler('isMonthSelectorOpen');
const toggleYearSelector = createStateToggler('isYearSelectorOpen');
const getComputedActiveDate = () => {
const valueType = getValueType(value);
if (valueType === TYPE_MUTLI_DATE && value.length)
return shallowClone(value[0]);
if (valueType === TYPE_SINGLE_DATE && value) return shallowClone(value);
if (valueType === TYPE_RANGE && value.from) return shallowClone(value.from);
return shallowClone(today);
};
const activeDate = mainState.activeDate
? shallowClone(mainState.activeDate)
: getComputedActiveDate();
const weekdays = weekDaysList.map((weekDay) => (
<abbr key={weekDay.name} title={weekDay.name} className={`Calendar__weekDay ${type}`}>
{ type == 'dashboard' ? weekDay.name : weekDay.short}
</abbr>
));
const handleMonthChange = (direction) => {
setMainState({
...mainState,
monthChangeDirection: direction,
});
};
const updateDate = () => {
setMainState({
...mainState,
activeDate: getDateAccordingToMonth(
activeDate,
mainState.monthChangeDirection
),
monthChangeDirection: '',
});
};
const selectMonth = (newMonthNumber) => {
setMainState({
...mainState,
activeDate: { ...activeDate, month: newMonthNumber },
isMonthSelectorOpen: false,
});
};
const selectYear = (year) => {
setMainState({
...mainState,
activeDate: { ...activeDate, year },
isYearSelectorOpen: false,
});
};
let year = m.jYear();
// ------get---month---------
// let monthNum = m.jMonth()+1;
let month;
switch (monthNum) {
case 1:
month = "فروردین";
break;
case 2:
month = "اردیبهشت";
break;
case 3:
month = "خرداد";
break;
case 4:
month = "تیر";
break;
case 5:
month = "مرداد";
break;
case 6:
month = "شهریور";
break;
case 7:
month = "مهر";
break;
case 8:
month = "آبان";
break;
case 9:
month = "آذر";
break;
case 10:
month = "دی";
break;
case 11:
month = "بهمن";
break;
case 12:
month = "اسفند";
break;
default:
month = "فروردین";
break;
}
// console.log("oooo"+m.jDay());
// const SetTime =()=>{
// setTimeout(()=>{
// set_time(today.getHours() + ":" + today.getMinutes());
// },1000);
// SetTime();
// // console.log("tic");
// }
return (
<div
className={`Calendar ${type} -noFocusOutline ${calendarClassName} -${isRtl ? 'rtl' : 'ltr'
}`}
role="grid"
style={{
'--cl-color-primary': colorPrimary,
'--cl-color-primary-light': colorPrimaryLight,
'--animation-duration': slideAnimationDuration,
}}
ref={calendarElement}
>
{/* <Header
maximumDate={maximumDate}
minimumDate={minimumDate}
activeDate={activeDate}
onMonthChange={handleMonthChange}
onMonthSelect={toggleMonthSelector}
onYearSelect={toggleYearSelector}
monthChangeDirection={mainState.monthChangeDirection}
isMonthSelectorOpen={mainState.isMonthSelectorOpen}
isYearSelectorOpen={mainState.isYearSelectorOpen}
locale={locale}
type={type}
/> */}
<div className="date-box-p1">
<div className="date-box-p1-year-and-month">
<div className="dbp1-month">{month}</div>،
<div className="dbp1-year">{year}</div>
</div>
<div className="date-box-p1-time">
<Clock />
</div>
</div>
<MonthSelector
isOpen={mainState.isMonthSelectorOpen}
activeDate={activeDate}
onMonthSelect={selectMonth}
maximumDate={maximumDate}
minimumDate={minimumDate}
locale={locale}
/>
<YearSelector
isOpen={mainState.isYearSelectorOpen}
activeDate={activeDate}
onYearSelect={selectYear}
selectorStartingYear={selectorStartingYear}
selectorEndingYear={selectorEndingYear}
maximumDate={maximumDate}
minimumDate={minimumDate}
locale={locale}
/>
<div className={`Calendar__weekDays ${type}`}>{weekdays}</div>
<DaysList
activeDate={activeDate}
value={value}
monthChangeDirection={mainState.monthChangeDirection}
onSlideChange={updateDate}
disabledDays={disabledDays}
onDisabledDayError={onDisabledDayError}
minimumDate={minimumDate}
maximumDate={maximumDate}
onChange={onChange}
calendarTodayClassName={calendarTodayClassName}
calendarSelectedDayClassName={calendarSelectedDayClassName}
calendarRangeStartClassName={calendarRangeStartClassName}
calendarRangeEndClassName={calendarRangeEndClassName}
calendarRangeBetweenClassName={calendarRangeBetweenClassName}
locale={locale}
shouldHighlightWeekends={shouldHighlightWeekends}
customDaysClassName={customDaysClassName}
events={events}
renderFooter={renderFooter}
renderEvents={renderEvents}
isQuickSelectorOpen={
mainState.isYearSelectorOpen || mainState.isMonthSelectorOpen
}
showEvent={event => setEventInFooter(event)}
type={type}
/>
<div className="Calendar__footer">
{/* <div className={`footer__Events ${type}`}>
{
type == 'dashboard' ? <><div className='text-xl font-black text-blue-400'>رویداد ها: </div><p className='text-blue-300 font-bold'>{eventInFooter ? eventInFooter : 'رویدادی در این روز وجود ندارد!'}</p></> : eventInFooter
}
</div>
{renderFooter()} */}
</div>
</div>
);
};
Calendar.defaultProps = {
minimumDate: null,
maximumDate: null,
colorPrimary: '#0eca2d',
colorPrimaryLight: '#cff4d5',
slideAnimationDuration: '0.4s',
calendarClassName: '',
locale: 'en',
value: null,
renderFooter: () => null,
renderEvents : () => null,
customDaysClassName: [],
events: [],
};
export default Calendar;

@ -0,0 +1,672 @@
.DatePicker {
position: relative;
display: inline-block;
z-index: 100;
}
.DatePicker__input {
background: #fff;
border: 1px solid #ddd;
padding: 0.4em 0.8em;
font-family: inherit;
text-align: center;
font-size: 12px;
}
.DatePicker__input.-rtl {
direction: rtl;
}
.DatePicker__input::placeholder {
color: #979797;
}
.DatePicker__calendarContainer.-top + .DatePicker__calendarArrow {
top: auto;
bottom: calc(100% + 10px);
transform: translateY(-2.5rem) rotate(180deg);
animation: fadeArrowFlipped 0.3s forwards;
}
.DatePicker__calendarContainer {
position: absolute;
top: calc(100% + 20px);
left: 50%;
transform: translateX(-50%);
}
.DatePicker__calendarContainer.-top {
top: auto;
bottom: calc(100% + 20px);
}
.Calendar,
.Calendar * {
margin: 0;
padding: 0;
box-sizing: border-box;
direction: ltr;
}
.Calendar,
.Calendar.-rtl * {
direction: rtl;
}
.DatePicker__calendarArrow {
position: absolute;
width: 0;
height: 0;
top: calc(100% + 10px);
left: 0;
right: 0;
margin: 0 auto;
border-style: solid;
z-index: 10;
border-width: 0 10px 10px 10px;
border-color: transparent transparent #fff transparent;
}
.Calendar {
--cl-color-black: #444444;
--cl-color-disabled: #d4d4d4;
--cl-color-error: #ff2929;
font-size: 10px;
background: #fff;
box-shadow: 0 1em 4em rgba(0, 0, 0, 0.07);
border-radius: 1em;
position: relative;
user-select: none;
padding-top: 1.2em;
display: flex;
flex-direction: column;
width: 33em;
z-index: 10;
max-width: 90vw;
min-height: 36.7em;
}
.DatePicker .Calendar,
.DatePicker__calendarArrow {
transform: translateY(2.5em);
opacity: 0;
animation: fadeCalendar 0.3s forwards;
}
.DatePicker__calendarContainer.-top .Calendar {
transform: translateY(-2.5em);
}
.Calendar.-noFocusOutline *:focus {
outline: none !important;
}
.Calendar > :not(.Calendar__footer) button {
font-family: inherit;
background: transparent;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
outline: none;
}
.Calendar__header {
display: flex;
color: var(--cl-color-black);
padding: 2em 2.9em;
align-items: center;
overflow: hidden;
}
.Calendar__monthArrowWrapper {
line-height: 0;
font-size: 1em;
padding: 3px;
position: relative;
border: none;
z-index: 1;
opacity: 1;
transition: 0.2s;
}
.Calendar__monthArrowWrapper:focus {
outline: 1px dashed rgba(0, 0, 0, 0.4);
outline-offset: 2px;
}
.Calendar__monthArrowWrapper:disabled,
.Calendar__monthArrowWrapper.-hidden {
opacity: 0;
pointer-events: none;
}
.Calendar__monthArrowWrapper.-left {
transform: rotate(90deg);
}
.Calendar.-rtl .Calendar__monthArrowWrapper.-left {
transform: rotate(-90deg);
}
.Calendar__monthArrowWrapper.-right {
transform: rotate(-90deg);
}
.Calendar.-rtl .Calendar__monthArrowWrapper.-right {
transform: rotate(90deg);
}
.Calendar__monthArrowWrapper:active .Calendar__monthArrow {
transform: scale(0.7);
}
.Calendar__monthArrow {
border-radius: 50%;
transition: var(--animation-duration) transform;
pointer-events: none;
background-repeat: no-repeat;
display: block;
width: 1.7em;
height: 1.7em;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cg class='nc-icon-wrapper' fill='%23000000'%3E%3Cdefs stroke='none'%3E%3C/defs%3E%3Cpath class='cls-1' d='M12 23.25V.75' fill='none' stroke='%23000000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5px'%3E%3C/path%3E%3Cpath class='cls-2' d='M22.5 11.25L12 .75 1.5 11.25' fill='none' stroke='%23000000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5px' fill-rule='evenodd'%3E%3C/path%3E%3C/g%3E%3C/svg%3E");
background-size: 100% 100%;
}
.Calendar__monthYearContainer {
flex: 1;
position: relative;
}
.Calendar__monthYear {
font-size: 1.6em;
font-weight: 500;
display: flex;
align-items: center;
position: absolute;
top: 0;
bottom: 0;
left: 50%;
will-change: transform, opacity;
backface-visibility: hidden;
transform: translateZ(0);
transition: var(--animation-duration);
line-height: 1;
}
.Calendar__monthYear.-hiddenNext {
opacity: 0;
transform: translateX(50%);
}
.Calendar.-rtl .Calendar__monthYear.-hiddenNext {
transform: translateX(-150%);
}
.Calendar__monthYear.-hiddenPrevious {
opacity: 0;
transform: translateX(-150%);
}
.Calendar.-rtl .Calendar__monthYear.-hiddenPrevious {
transform: translateX(50%);
}
.Calendar__monthYear.-shown {
opacity: 1;
margin-top: auto;
margin-bottom: auto;
transform: translateX(-50%);
}
.Calendar__monthYear.-shownAnimated {
animation: var(--animation-duration) fadeTextToCenter forwards;
}
.Calendar__monthYear > * {
padding: 0.2em 0.5em;
border: 1px solid transparent;
transition: var(--animation-duration);
font-size: 1.05em;
display: flex;
justify-content: center;
align-items: center;
transform: translateX(0) scale(0.95);
will-change: transform;
border-radius: 5px;
}
.Calendar__monthYear:not(.-shown) > *,
.Calendar__monthYear > *.-hidden {
cursor: default;
pointer-events: none;
}
.Calendar__monthText {
margin-left: -0.3em;
}
.Calendar__yearText:last-child {
margin-right: -0.3em;
}
.Calendar__monthYear.-shown > *:hover,
.Calendar:not(.-noFocusOutline) .Calendar__monthYear.-shown > *:focus,
.Calendar__monthYear > *.-activeBackground {
background: #f5f5f5;
}
.Calendar__monthText:hover {
transform: translateX(-0.2em) scale(0.95);
}
.Calendar.-rtl .Calendar__monthText:hover {
transform: translateX(0.2em) scale(0.95);
}
.Calendar__yearText:hover {
transform: translateX(0.2em) scale(0.95);
}
.Calendar.-rtl .Calendar__yearText:hover {
transform: translateX(-0.2em) scale(0.95);
}
.Calendar__monthYear .Calendar__yearText.-hidden {
transform: translateX(50%);
opacity: 0;
}
.Calendar.-rtl .Calendar__monthYear .Calendar__yearText.-hidden {
transform: translateX(-50%);
}
.Calendar__monthYear .Calendar__monthText.-hidden {
transform: translateX(-50%);
opacity: 0;
}
.Calendar.-rtl .Calendar__monthYear .Calendar__monthText.-hidden {
transform: translateX(50%);
}
.Calendar__monthYear:not(.-shown) > * {
pointer-events: none;
}
.Calendar__monthSelectorAnimationWrapper,
.Calendar__yearSelectorAnimationWrapper {
position: absolute;
width: 100%;
height: 80%;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.Calendar__monthSelectorWrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.Calendar__monthSelector {
padding: 0 2.5em;
align-content: center;
padding-bottom: 2em;
}
.Calendar__monthSelector,
.Calendar__yearSelector {
display: flex;
flex-wrap: wrap;
position: relative;
z-index: 2;
background-color: #fff;
transform: translateY(-150%);
will-change: transform;
transition: 0.6s;
height: 100%;
}
.Calendar__yearSelectorWrapper {
width: 100%;
height: 100%;
}
.Calendar__yearSelectorWrapper::after,
.Calendar__yearSelectorWrapper::before {
content: '';
width: 100%;
height: 5em;
position: absolute;
left: 0;
opacity: 0;
transition: 0.4s;
transition-delay: 0.2s;
}
.Calendar__yearSelectorWrapper::after {
background-image: linear-gradient(to bottom, #fff, #fff 10%, rgba(245, 245, 245, 0));
top: -0.1em;
}
.Calendar__yearSelectorWrapper::before {
background-image: linear-gradient(to top, #fff, #fff 10%, rgba(245, 245, 245, 0));
bottom: 0;
}
.Calendar__yearSelectorWrapper.-faded::after,
.Calendar__yearSelectorWrapper.-faded::before {
opacity: 1;
z-index: 3;
}
.Calendar__yearSelector {
align-content: flex-start;
scrollbar-width: 0;
overflow: scroll;
position: relative;
width: 100%;
padding: 5em 2em;
-ms-overflow-style: none;
}
.Calendar__yearSelector::-webkit-scrollbar {
display: none;
}
.Calendar__yearSelectorItem {
width: 25%;
display: flex;
justify-content: center;
}
.Calendar__yearSelectorItem:not(:nth-child(-n + 4)) {
margin-top: 1.5em;
}
.Calendar__yearSelectorText {
border: none;
font-size: 1.4em;
min-width: 85%;
padding: 0.2em 0.5em;
border-radius: 8.5px;
}
.Calendar__monthSelector.-open,
.Calendar__yearSelector.-open {
transform: translateY(0);
}
.Calendar__yearSelectorText:focus,
.Calendar__monthSelectorItemText:focus {
outline: 1px dashed rgba(0, 0, 0, 0.4);
outline-offset: 2px;
}
.Calendar__monthSelectorItem {
width: calc(100% / 3);
display: flex;
justify-content: center;
}
.Calendar__monthSelectorItem:not(:nth-child(-n + 3)) {
margin-top: 2em;
}
.Calendar__monthSelectorItemText {
border: none;
padding: 0.4em 0.4em;
border-radius: 8.5px;
font-size: 1.3em;
min-width: 70%;
transition: 0.3s;
}
.Calendar__monthSelectorItem:not(.-active) .Calendar__monthSelectorItemText:not(:disabled):hover,
.Calendar__yearSelectorItem:not(.-active) .Calendar__yearSelectorText:not(:disabled):hover {
background: #f5f5f5;
}
.Calendar__monthSelectorItemText:disabled,
.Calendar__yearSelectorText:disabled {
opacity: 0.5;
cursor: default;
}
.Calendar__monthSelectorItem.-active .Calendar__monthSelectorItemText,
.Calendar__yearSelectorItem.-active .Calendar__yearSelectorText {
background-color: var(--cl-color-primary);
color: #fff;
}
.Calendar__weekDays {
display: flex;
justify-content: space-between;
color: var(--cl-color-disabled);
font-size: 1.2em;
margin-bottom: 0.7em;
padding: 0 2.6em;
position: relative;
}
.Calendar__weekDay {
display: block;
width: calc(100% / 7);
text-align: center;
text-decoration: none;
}
.Calendar__sectionWrapper {
position: relative;
min-height: 25.8em;
overflow: hidden;
}
.Calendar__section {
display: flex;
flex-direction: column;
padding: 0 3.2em;
position: absolute;
color: var(--cl-color-black);
top: 0;
padding-top: 0.5em;
left: 0;
width: 100%;
will-change: transform, opacity;
transform: translateZ(0);
backface-visibility: hidden;
transition: var(--animation-duration);
}
.Calendar__section.-hiddenPrevious {
opacity: 0.5;
transform: translateX(-90%);
}
.Calendar.-rtl .Calendar__section.-hiddenPrevious {
transform: translateX(90%);
}
.Calendar__section.-hiddenNext {
opacity: 0.5;
transform: translateX(90%);
}
.Calendar.-rtl .Calendar__section.-hiddenNext {
transform: translateX(-90%);
}
.Calendar__section.-shown {
opacity: 1;
transform: translateX(0);
}
.Calendar__section.-shownAnimated {
animation: var(--animation-duration) FadeContentToCenter forwards;
}
.Calendar__weekRow {
display: flex;
width: 100%;
}
.Calendar__day {
display: block;
width: calc(100% / 7);
text-align: center;
padding: calc(0.25em - 1px) 0;
font-size: 1.6em;
border-radius: 50%;
transition: 0.2s;
border: 1px solid transparent;
margin-bottom: 0.3em;
color: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.Calendar__day:focus {
outline: 1px dashed rgba(0, 0, 0, 0.4);
outline-offset: 2px;
}
.Calendar__day.-ltr {
min-height: 2.6em;
font-size: 1.45em;
}
.Calendar__day.-rtl {
font-size: 1.55em;
height: 2.45em;
}
.Calendar__day:not(.-blank):not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween):not(.-selected):hover {
background: #eaeaea;
border-radius: 50%;
color: var(--cl-color-black);
border-color: transparent;
}
.Calendar__day.-selected,
.Calendar__day.-selectedStart,
.Calendar__day.-selectedEnd {
background: var(--cl-color-primary);
color: #fff;
}
.Calendar__day.-ltr.-selectedStart {
border-radius: 0;
border-top-left-radius: 100em;
border-bottom-left-radius: 100em;
}
.Calendar__day.-rtl.-selectedStart {
border-radius: 0;
border-top-right-radius: 100em;
border-bottom-right-radius: 100em;
}
.Calendar__day.-selectedBetween {
background: var(--cl-color-primary-light);
color: var(--cl-color-primary);
border-radius: 0;
}
.Calendar__day.-ltr.-selectedEnd {
border-top-right-radius: 100em;
border-bottom-right-radius: 100em;
}
.Calendar__day.-rtl.-selectedEnd {
border-top-left-radius: 100em;
border-bottom-left-radius: 100em;
}
.Calendar__day.-weekend:not(.-selected):not(.-blank):not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween) {
color: var(--cl-color-error);
}
.Calendar__day.-weekend.-today:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween)::after {
background: var(--cl-color-error);
}
.Calendar__day.-disabled {
color: var(--cl-color-disabled) !important;
background: transparent !important;
cursor: default !important;
}
.Calendar__day.-selected {
border-radius: 50%;
}
.Calendar__day.-today:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween) {
font-weight: 600;
color: var(--cl-color-black);
color: #000;
position: relative;
}
.Calendar__day.-today:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween)::after {
content: '';
position: absolute;
bottom: 0.2em;
display: block;
width: 0.6em;
height: 1px;
background: #000;
left: 50%;
opacity: 0.5;
transform: translateX(-50%);
transition: 0.2s;
}
.Calendar__day.-today:hover:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween)::after {
opacity: 0;
}
.Calendar__day.-blank {
color: transparent;
cursor: default;
pointer-events: none;
}
.Calendar__footer {
position: relative;
z-index: 1;
}
@keyframes fadeCalendar {
from {
opacity: 0;
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeArrowFlipped {
from {
opacity: 0;
}
to {
opacity: 1;
transform: translateY(0) rotate(180deg);
}
}
@keyframes fadeTextToCenter {
to {
opacity: 1;
transform: translateX(-50%);
}
}
@keyframes FadeContentToCenter {
to {
opacity: 1;
transform: translateX(0);
}
}

@ -0,0 +1,203 @@
import React, { useState, useEffect, useRef, useLayoutEffect } from 'react';
import Calendar from './Calendar';
import DatePickerInput from './DatePickerInput';
import { getValueType } from './shared/generalUtils';
import { TYPE_SINGLE_DATE, TYPE_MUTLI_DATE, TYPE_RANGE } from './shared/constants';
const DatePicker = ({
value,
onChange,
formatInputText,
inputPlaceholder,
inputClassName,
inputName,
renderInput,
wrapperClassName,
calendarClassName,
calendarTodayClassName,
calendarSelectedDayClassName,
calendarRangeStartClassName,
calendarRangeBetweenClassName,
calendarRangeEndClassName,
calendarPopperPosition,
disabledDays,
onDisabledDayError,
colorPrimary,
colorPrimaryLight,
slideAnimationDuration,
minimumDate,
maximumDate,
selectorStartingYear,
selectorEndingYear,
locale,
shouldHighlightWeekends,
renderFooter,
customDaysClassName,
}) => {
const calendarContainerElement = useRef(null);
const inputElement = useRef(null);
const shouldPreventToggle = useRef(false);
const [isCalendarOpen, setCalendarVisiblity] = useState(false);
useEffect(() => {
const handleBlur = () => {
setCalendarVisiblity(false);
};
window.addEventListener('blur', handleBlur, false);
return () => {
window.removeEventListener('blur', handleBlur, false);
};
}, []);
// handle input focus/blur
useEffect(() => {
const valueType = getValueType(value);
if (valueType === TYPE_MUTLI_DATE) return; // no need to close the calendar
const shouldCloseCalendar =
valueType === TYPE_SINGLE_DATE ? !isCalendarOpen : !isCalendarOpen && value.from && value.to;
if (shouldCloseCalendar) inputElement.current.blur();
}, [value, isCalendarOpen]);
const handleBlur = e => {
e.persist();
if (!isCalendarOpen) return;
const isInnerElementFocused = calendarContainerElement.current.contains(e.relatedTarget);
if (shouldPreventToggle.current) {
shouldPreventToggle.current = false;
inputElement.current.focus();
} else if (isInnerElementFocused && e.relatedTarget) {
e.relatedTarget.focus();
} else {
setCalendarVisiblity(false);
}
};
const openCalendar = () => {
if (!shouldPreventToggle.current) setCalendarVisiblity(true);
};
// Keep the calendar in the screen bounds if input is near the window edges
useLayoutEffect(() => {
if (!isCalendarOpen) return;
const { left, width, height, top } = calendarContainerElement.current.getBoundingClientRect();
const { clientWidth, clientHeight } = document.documentElement;
const isOverflowingFromRight = left + width > clientWidth;
const isOverflowingFromLeft = left < 0;
const isOverflowingFromBottom = top + height > clientHeight;
const getLeftStyle = () => {
const overflowFromRightDistance = left + width - clientWidth;
if (!isOverflowingFromRight && !isOverflowingFromLeft) return;
const overflowFromLeftDistance = Math.abs(left);
const rightPosition = isOverflowingFromLeft ? overflowFromLeftDistance : 0;
const leftStyle = isOverflowingFromRight
? `calc(50% - ${overflowFromRightDistance}px)`
: `calc(50% + ${rightPosition}px)`;
return leftStyle;
};
calendarContainerElement.current.style.left = getLeftStyle();
if (
(calendarPopperPosition === 'auto' && isOverflowingFromBottom) ||
calendarPopperPosition === 'top'
) {
calendarContainerElement.current.classList.add('-top');
}
}, [isCalendarOpen]);
const handleCalendarChange = newValue => {
const valueType = getValueType(value);
onChange(newValue);
if (valueType === TYPE_SINGLE_DATE) setCalendarVisiblity(false);
else if (valueType === TYPE_RANGE && newValue.from && newValue.to) setCalendarVisiblity(false);
};
const handleKeyUp = ({ key }) => {
switch (key) {
case 'Enter':
setCalendarVisiblity(true);
break;
case 'Escape':
setCalendarVisiblity(false);
shouldPreventToggle.current = true;
break;
}
};
useEffect(() => {
if (!isCalendarOpen && shouldPreventToggle.current) {
inputElement.current.focus();
shouldPreventToggle.current = false;
}
}, [shouldPreventToggle, isCalendarOpen]);
return (
<div
onFocus={openCalendar}
onBlur={handleBlur}
onKeyUp={handleKeyUp}
className={`DatePicker ${wrapperClassName}`}
role="presentation"
>
<DatePickerInput
ref={inputElement}
formatInputText={formatInputText}
value={value}
inputPlaceholder={inputPlaceholder}
inputClassName={inputClassName}
renderInput={renderInput}
inputName={inputName}
locale={locale}
/>
{isCalendarOpen && (
<>
<div
ref={calendarContainerElement}
className="DatePicker__calendarContainer"
data-testid="calendar-container"
role="presentation"
onMouseDown={() => {
shouldPreventToggle.current = true;
}}
>
<Calendar
value={value}
onChange={handleCalendarChange}
calendarClassName={calendarClassName}
calendarTodayClassName={calendarTodayClassName}
calendarSelectedDayClassName={calendarSelectedDayClassName}
calendarRangeStartClassName={calendarRangeStartClassName}
calendarRangeBetweenClassName={calendarRangeBetweenClassName}
calendarRangeEndClassName={calendarRangeEndClassName}
disabledDays={disabledDays}
colorPrimary={colorPrimary}
colorPrimaryLight={colorPrimaryLight}
slideAnimationDuration={slideAnimationDuration}
onDisabledDayError={onDisabledDayError}
minimumDate={minimumDate}
maximumDate={maximumDate}
selectorStartingYear={selectorStartingYear}
selectorEndingYear={selectorEndingYear}
locale={locale}
shouldHighlightWeekends={shouldHighlightWeekends}
renderFooter={renderFooter}
customDaysClassName={customDaysClassName}
/>
</div>
<div className="DatePicker__calendarArrow" />
</>
)}
</div>
);
};
DatePicker.defaultProps = {
wrapperClassName: '',
locale: 'en',
calendarPopperPosition: 'auto',
};
export default DatePicker;

@ -0,0 +1,93 @@
import React from 'react';
import { useLocaleUtils, useLocaleLanguage } from './shared/hooks';
import { putZero, getValueType } from './shared/generalUtils';
import { TYPE_SINGLE_DATE, TYPE_RANGE, TYPE_MUTLI_DATE } from './shared/constants';
const DatePickerInput = React.forwardRef(
(
{ value, inputPlaceholder, inputClassName, inputName, formatInputText, renderInput, locale },
ref,
) => {
const { getLanguageDigits } = useLocaleUtils(locale);
const {
from: fromWord,
to: toWord,
yearLetterSkip,
digitSeparator,
defaultPlaceholder,
isRtl,
} = useLocaleLanguage(locale);
const getSingleDayValue = () => {
if (!value) return '';
const year = getLanguageDigits(value.year);
const month = getLanguageDigits(putZero(value.month));
const day = getLanguageDigits(putZero(value.day));
return `${year}/${month}/${day}`;
};
const getDayRangeValue = () => {
if (!value.from || !value.to) return '';
const { from, to } = value;
const fromText = `${getLanguageDigits(putZero(from.year))
.toString()
.slice(yearLetterSkip)}/${getLanguageDigits(putZero(from.month))}/${getLanguageDigits(
putZero(from.day),
)}`;
const toText = `${getLanguageDigits(putZero(to.year))
.toString()
.slice(yearLetterSkip)}/${getLanguageDigits(putZero(to.month))}/${getLanguageDigits(
putZero(to.day),
)}`;
return `${fromWord} ${fromText} ${toWord} ${toText}`;
};
const getMultiDateValue = () => {
return value.map(date => getLanguageDigits(date.day)).join(`${digitSeparator} `);
};
const getValue = () => {
if (formatInputText()) return formatInputText();
const valueType = getValueType(value);
switch (valueType) {
case TYPE_SINGLE_DATE:
return getSingleDayValue();
case TYPE_RANGE:
return getDayRangeValue();
case TYPE_MUTLI_DATE:
return getMultiDateValue();
}
};
const placeholderValue = inputPlaceholder || defaultPlaceholder;
const render = () => {
return (
renderInput({ ref }) || (
<input
data-testid="datepicker-input"
readOnly
ref={ref}
value={getValue()}
name={inputName}
placeholder={placeholderValue}
className={`DatePicker__input -${isRtl ? 'rtl' : 'ltr'} ${inputClassName}`}
aria-label={placeholderValue}
/>
)
);
};
return render();
},
);
DatePickerInput.defaultProps = {
formatInputText: () => '',
renderInput: () => null,
inputPlaceholder: '',
inputClassName: '',
inputName: '',
};
export default DatePickerInput;

@ -0,0 +1,399 @@
import React, { useRef, useEffect } from 'react';
import {
getSlideDate,
handleSlideAnimationEnd,
animateContent,
} from '../shared/sliderHelpers';
import {
deepCloneObject,
isSameDay,
createUniqueRange,
getValueType,
} from '../shared/generalUtils';
import {
TYPE_SINGLE_DATE,
TYPE_RANGE,
TYPE_MUTLI_DATE,
} from '../shared/constants';
import handleKeyboardNavigation from '../shared/keyboardNavigation';
import { useLocaleUtils, useLocaleLanguage } from '../shared/hooks';
const DaysList = ({
activeDate,
value,
monthChangeDirection,
onSlideChange,
disabledDays,
onDisabledDayError,
minimumDate,
maximumDate,
onChange,
locale,
calendarTodayClassName,
calendarSelectedDayClassName,
calendarRangeStartClassName,
calendarRangeEndClassName,
calendarRangeBetweenClassName,
shouldHighlightWeekends,
isQuickSelectorOpen,
customDaysClassName,
events,
showEvent,
type
}) => {
const calendarSectionWrapper = useRef(null);
const { isRtl, weekDays: weekDaysList } = useLocaleLanguage(locale);
const {
getToday,
isBeforeDate,
checkDayInDayRange,
getMonthFirstWeekday,
getMonthLength,
getLanguageDigits,
getMonthName,
} = useLocaleUtils(locale);
const today = getToday();
useEffect(() => {
if (!monthChangeDirection) return;
animateContent({
direction: monthChangeDirection,
parent: calendarSectionWrapper.current,
});
}, [monthChangeDirection]);
const getDayRangeValue = (day) => {
const clonedDayRange = deepCloneObject(value);
const dayRangeValue =
clonedDayRange.from && clonedDayRange.to
? { from: null, to: null }
: clonedDayRange;
const dayRangeProp = !dayRangeValue.from ? 'from' : 'to';
dayRangeValue[dayRangeProp] = day;
const { from, to } = dayRangeValue;
// swap from and to values if from is later than to
if (isBeforeDate(dayRangeValue.to, dayRangeValue.from)) {
dayRangeValue.from = to;
dayRangeValue.to = from;
}
const checkIncludingDisabledDay = (disabledDay) => {
return checkDayInDayRange({
day: disabledDay,
from: dayRangeValue.from,
to: dayRangeValue.to,
});
};
const includingDisabledDay = disabledDays.find(checkIncludingDisabledDay);
if (includingDisabledDay) {
onDisabledDayError(includingDisabledDay);
return value;
}
return dayRangeValue;
};
const getMultiDateValue = (day) => {
const isAlreadyExisting = value.some((valueDay) =>
isSameDay(valueDay, day)
);
const addedToValue = [...value, day];
const removedFromValue = value.filter(
(valueDay) => !isSameDay(valueDay, day)
);
return isAlreadyExisting ? removedFromValue : addedToValue;
};
const handleDayClick = (day) => {
const getNewValue = () => {
const valueType = getValueType(value);
switch (valueType) {
case TYPE_SINGLE_DATE:
return day;
case TYPE_RANGE:
return getDayRangeValue(day);
case TYPE_MUTLI_DATE:
return getMultiDateValue(day);
}
};
const newValue = getNewValue();
onChange(newValue);
};
const isSingleDateSelected = (day) => {
const valueType = getValueType(value);
if (valueType === TYPE_SINGLE_DATE) return isSameDay(day, value);
if (valueType === TYPE_MUTLI_DATE)
return value.some((valueDay) => isSameDay(valueDay, day));
};
const getDayStatus = (dayItem) => {
const isToday = isSameDay(dayItem, today);
const isSelected = isSingleDateSelected(dayItem);
const { from: startingDay, to: endingDay } = value || {};
const isStartingDayRange = isSameDay(dayItem, startingDay);
const isEndingDayRange = isSameDay(dayItem, endingDay);
const isWithinRange = checkDayInDayRange({
day: dayItem,
from: startingDay,
to: endingDay,
});
return {
isToday,
isSelected,
isStartingDayRange,
isEndingDayRange,
isWithinRange,
};
};
const getDayClassNames = (dayItem) => {
const {
isToday,
isSelected,
isStartingDayRange,
isEndingDayRange,
isWithinRange,
} = getDayStatus(dayItem);
const customDayItemClassName = customDaysClassName.find((day) =>
isSameDay(dayItem, day)
);
const classNames = ''
.concat(isToday && !isSelected ? ` -today ${calendarTodayClassName}` : '')
.concat(!dayItem.isStandard ? ' -blank' : '')
.concat(dayItem.isWeekend && shouldHighlightWeekends ? ' -weekend' : '')
.concat(
customDayItemClassName ? ` ${customDayItemClassName.className}` : ''
)
.concat(isSelected ? ` -selected ${calendarSelectedDayClassName}` : '')
.concat(
isStartingDayRange
? ` -selectedStart ${calendarRangeStartClassName}`
: ''
)
.concat(
isEndingDayRange ? ` -selectedEnd ${calendarRangeEndClassName}` : ''
)
.concat(
isWithinRange
? ` -selectedBetween ${calendarRangeBetweenClassName}`
: ''
)
.concat(dayItem.isDisabled ? ' -disabled' : '');
return classNames;
};
const getViewMonthDays = (date) => {
// to match month starting date with the correct weekday label
const prependingBlankDays = createUniqueRange(
getMonthFirstWeekday(date),
'starting-blank'
);
const standardDays = createUniqueRange(getMonthLength(date)).map((day) => ({
...day,
isStandard: true,
month: date.month,
year: date.year,
}));
const allDays = [...prependingBlankDays, ...standardDays];
return allDays;
};
const handleDayPress = ({ isDisabled, ...dayItem }) => {
if (isDisabled) {
onDisabledDayError(dayItem); // good for showing error messages
} else handleDayClick(dayItem);
};
const isDayReachableByKeyboard = ({
isOnActiveSlide,
isStandard,
isSelected,
isStartingDayRange,
isToday,
day,
}) => {
if (isQuickSelectorOpen || !isOnActiveSlide || !isStandard) return false;
if (isSelected || isStartingDayRange || isToday || day === 1) return true;
};
const renderEachWeekDays = (
{ id, value: day, month, year, isStandard },
index
) => {
const dayItem = { day, month, year };
const isInDisabledDaysRange = disabledDays.some((disabledDay) =>
isSameDay(dayItem, disabledDay)
);
const isBeforeMinimumDate = isBeforeDate(dayItem, minimumDate);
const isAfterMaximumDate = isBeforeDate(maximumDate, dayItem);
const isNotInValidRange =
isStandard && (isBeforeMinimumDate || isAfterMaximumDate);
const isDisabled = isInDisabledDaysRange || isNotInValidRange;
const isWeekend = weekDaysList.some(
(weekDayItem, weekDayItemIndex) =>
weekDayItem.isWeekend && weekDayItemIndex === index
);
const additionalClass = getDayClassNames({
...dayItem,
isWeekend,
isStandard,
isDisabled,
});
const dayLabel = `${weekDaysList[index].name}, ${day} ${getMonthName(
month
)} ${year}`;
const isOnActiveSlide = month === activeDate.month;
const dayStatus = getDayStatus(dayItem);
const { isSelected, isStartingDayRange, isEndingDayRange, isWithinRange } =
dayStatus;
const shouldEnableKeyboardNavigation = isDayReachableByKeyboard({
...dayItem,
...dayStatus,
isOnActiveSlide,
isStandard,
});
// showing Dots Of Events
const specialDate = (sDay, sMonth, sYear) => {
return events.map((e) => {
if (sDay == e.day && sMonth == e.month && sYear == e.year) {
return <span key={'dot' + e.id} style={{
color: e.color
}}>.</span>;
}
})
};
const showEventDescription = (sDay, sMonth, sYear) => {
return events.map((e) => {
if (sDay == e.day && sMonth == e.month && sYear == e.year) {
return (<div key={'description' + e.id}><p>{e.description}</p></div>)
}
})
}
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
tabIndex={shouldEnableKeyboardNavigation ? '0' : '-1'}
key={id}
className={`Calendar__day ${type} -${isRtl ? 'rtl' : 'ltr'} ${additionalClass}`}
onClick={() => {
handleDayPress({ ...dayItem, isDisabled });
// console.log(specialDate(day));
// console.log(showEventDescription(day))
showEvent(showEventDescription(day, month, year))
}}
onKeyDown={({ key }) => {
/* istanbul ignore else */
if (key === 'Enter') handleDayPress({ ...dayItem, isDisabled });
}}
aria-disabled={isDisabled}
aria-label={dayLabel}
aria-selected={
isSelected || isStartingDayRange || isEndingDayRange || isWithinRange
}
{...(!isStandard || !isOnActiveSlide || isQuickSelectorOpen
? { 'aria-hidden': true }
: {})}
role="gridcell"
data-is-default-selectable={shouldEnableKeyboardNavigation}
>
<p className=''>{!isStandard ? '' : getLanguageDigits(day)}</p>
{/* Dots Of Events */}
<span>{specialDate(day, month, year)}</span>
</div>
);
};
const renderMonthDays = (isInitialActiveChild) => {
const date = getSlideDate({
activeDate,
isInitialActiveChild,
monthChangeDirection,
parent: calendarSectionWrapper.current,
});
const allDays = getViewMonthDays(date);
const renderSingleWeekRow = (weekRowIndex) => {
const eachWeekDays = allDays
.slice(weekRowIndex * 7, weekRowIndex * 7 + 7)
.map(renderEachWeekDays);
return (
<div
key={String(weekRowIndex)}
className="Calendar__weekRow"
role="row"
>
{eachWeekDays}
</div>
);
};
return Array.from(Array(6).keys()).map(renderSingleWeekRow);
};
const handleKeyDown = (e) => {
handleKeyboardNavigation(e, { allowVerticalArrows: true });
};
return (
<div
ref={calendarSectionWrapper}
className="Calendar__sectionWrapper"
role="presentation"
data-testid="days-section-wrapper"
onKeyDown={handleKeyDown}
>
<div
onAnimationEnd={(e) => {
handleSlideAnimationEnd(e);
onSlideChange();
}}
className="Calendar__section -shown"
role="rowgroup"
>
{renderMonthDays(true)}
</div>
<div
onAnimationEnd={(e) => {
handleSlideAnimationEnd(e);
onSlideChange();
}}
className="Calendar__section -hiddenNext"
role="rowgroup"
>
{renderMonthDays(false)}
</div>
</div>
);
};
DaysList.defaultProps = {
onChange: () => { },
onDisabledDayError: () => { },
disabledDays: [],
calendarTodayClassName: '',
calendarSelectedDayClassName: '',
calendarRangeStartClassName: '',
calendarRangeBetweenClassName: '',
calendarRangeEndClassName: '',
shouldHighlightWeekends: false,
};
export default DaysList;

@ -0,0 +1,168 @@
import React, { useEffect, useRef } from 'react';
import { isSameDay } from '../shared/generalUtils';
import { getSlideDate, animateContent, handleSlideAnimationEnd } from '../shared/sliderHelpers';
import { useLocaleUtils, useLocaleLanguage } from '../shared/hooks';
const Header = ({
maximumDate,
minimumDate,
onMonthChange,
activeDate,
monthChangeDirection,
onMonthSelect,
onYearSelect,
isMonthSelectorOpen,
isYearSelectorOpen,
locale,
type
}) => {
const headerElement = useRef(null);
const monthYearWrapperElement = useRef(null);
const { getMonthName, isBeforeDate, getLanguageDigits } = useLocaleUtils(locale);
const {
isRtl,
nextMonth,
previousMonth,
openMonthSelector,
closeMonthSelector,
openYearSelector,
closeYearSelector,
} = useLocaleLanguage(locale);
useEffect(() => {
if (!monthChangeDirection) return;
animateContent({
direction: monthChangeDirection,
parent: monthYearWrapperElement.current,
});
}, [monthChangeDirection]);
useEffect(() => {
const isOpen = isMonthSelectorOpen || isYearSelectorOpen;
const monthText = headerElement.current.querySelector(
'.Calendar__monthYear.-shown .Calendar__monthText',
);
const yearText = monthText.nextSibling;
const hasActiveBackground = element => element.classList.contains('-activeBackground');
const isInitialRender =
!isOpen && !hasActiveBackground(monthText) && !hasActiveBackground(yearText);
if (isInitialRender) return;
const arrows = [...headerElement.current.querySelectorAll('.Calendar__monthArrowWrapper')];
const hasMonthSelectorToggled = isMonthSelectorOpen || hasActiveBackground(monthText);
const primaryElement = hasMonthSelectorToggled ? monthText : yearText;
const secondaryElement = hasMonthSelectorToggled ? yearText : monthText;
let translateXDirection = hasMonthSelectorToggled ? 1 : -1;
if (isRtl) translateXDirection *= -1;
const scale = !isOpen ? 0.95 : 1;
const translateX = !isOpen ? 0 : `${(translateXDirection * secondaryElement.offsetWidth) / 2}`;
if (!isOpen) {
secondaryElement.removeAttribute('aria-hidden');
} else {
secondaryElement.setAttribute('aria-hidden', true);
}
secondaryElement.setAttribute('tabindex', isOpen ? '-1' : '0');
secondaryElement.style.transform = '';
primaryElement.style.transform = `scale(${scale}) ${
translateX ? `translateX(${translateX}px)` : ''
}`;
primaryElement.classList.toggle('-activeBackground');
secondaryElement.classList.toggle('-hidden');
arrows.forEach(arrow => {
const isHidden = arrow.classList.contains('-hidden');
arrow.classList.toggle('-hidden');
if (isHidden) {
arrow.removeAttribute('aria-hidden');
arrow.setAttribute('tabindex', '0');
} else {
arrow.setAttribute('aria-hidden', true);
arrow.setAttribute('tabindex', '-1');
}
});
}, [isMonthSelectorOpen, isYearSelectorOpen]);
const getMonthYearText = isInitialActiveChild => {
const date = getSlideDate({
isInitialActiveChild,
monthChangeDirection,
activeDate,
parent: monthYearWrapperElement.current,
});
const year = getLanguageDigits(date.year);
const month = getMonthName(date.month);
return { month, year };
};
const isNextMonthArrowDisabled =
maximumDate &&
isBeforeDate(maximumDate, { ...activeDate, month: activeDate.month + 1, day: 1 });
const isPreviousMonthArrowDisabled =
minimumDate &&
(isBeforeDate({ ...activeDate, day: 1 }, minimumDate) ||
isSameDay(minimumDate, { ...activeDate, day: 1 }));
const onMonthChangeTrigger = direction => {
const isMonthChanging = Array.from(monthYearWrapperElement.current.children).some(child =>
child.classList.contains('-shownAnimated'),
);
if (isMonthChanging) return;
onMonthChange(direction);
};
// first button text is the one who shows the current month and year(initial active child)
const monthYearButtons = [true, false].map(isInitialActiveChild => {
const { month, year } = getMonthYearText(isInitialActiveChild);
const isActiveMonth = month === getMonthName(activeDate.month);
return (
<>
<button
onClick={onMonthSelect}
type="button"
className=""
>
{month}
</button>
<button
onClick={onYearSelect}
type="button"
className=""
>
{year}
</button>
</>
);
});
return (
<div ref={headerElement} className={` ${type}`}>
{type == 'dashboard' ?
<div>
{monthYearButtons}
</div>
:
<>
<div
className="Calendar__monthYearContainer"
ref={monthYearWrapperElement}
data-testid="month-year-container"
>
&nbsp;
{monthYearButtons}
</div>
</>
}
</div>
);
};
export default Header;

@ -0,0 +1,74 @@
import React, { useRef, useEffect } from 'react';
import { isSameDay } from '../shared/generalUtils';
import handleKeyboardNavigation from '../shared/keyboardNavigation';
import { useLocaleUtils, useLocaleLanguage } from '../shared/hooks';
const MonthSelector = ({ activeDate, maximumDate, minimumDate, onMonthSelect, isOpen, locale }) => {
const monthSelector = useRef(null);
useEffect(() => {
const classToggleMethod = isOpen ? 'add' : 'remove';
monthSelector.current.classList[classToggleMethod]('-open');
}, [isOpen]);
const { getMonthNumber, isBeforeDate } = useLocaleUtils(locale);
const { months: monthsList } = useLocaleLanguage(locale);
const handleKeyDown = e => {
handleKeyboardNavigation(e, { allowVerticalArrows: false });
};
const renderMonthSelectorItems = () =>
monthsList.map(persianMonth => {
const monthNumber = getMonthNumber(persianMonth);
const monthDate = { day: 1, month: monthNumber, year: activeDate.year };
const isAfterMaximumDate =
maximumDate && isBeforeDate(maximumDate, { ...monthDate, month: monthNumber });
const isBeforeMinimumDate =
minimumDate &&
(isBeforeDate({ ...monthDate, month: monthNumber + 1 }, minimumDate) ||
isSameDay({ ...monthDate, month: monthNumber + 1 }, minimumDate));
const isSelected = monthNumber === activeDate.month;
return (
<li
key={persianMonth}
className={`Calendar__monthSelectorItem ${isSelected ? '-active' : ''}`}
>
<button
tabIndex={isSelected && isOpen ? '0' : '-1'}
onClick={() => {
onMonthSelect(monthNumber);
}}
className="Calendar__monthSelectorItemText"
type="button"
disabled={isAfterMaximumDate || isBeforeMinimumDate}
aria-pressed={isSelected}
data-is-default-selectable={isSelected}
>
{persianMonth}
</button>
</li>
);
});
return (
<div
role="presentation"
className="Calendar__monthSelectorAnimationWrapper"
{...(isOpen ? {} : { 'aria-hidden': true })}
>
<div
role="presentation"
data-testid="month-selector-wrapper"
className="Calendar__monthSelectorWrapper"
onKeyDown={handleKeyDown}
>
<ul ref={monthSelector} className="Calendar__monthSelector" data-testid="month-selector">
{renderMonthSelectorItems()}
</ul>
</div>
</div>
);
};
export default MonthSelector;

@ -0,0 +1,99 @@
import React, { useRef, useEffect } from 'react';
import { MINIMUM_SELECTABLE_YEAR_SUBTRACT, MAXIMUM_SELECTABLE_YEAR_SUM } from '../shared/constants';
import handleKeyboardNavigation from '../shared/keyboardNavigation';
import { useLocaleUtils } from '../shared/hooks';
const YearSelector = ({
isOpen,
activeDate,
onYearSelect,
selectorStartingYear,
selectorEndingYear,
maximumDate,
minimumDate,
locale,
}) => {
const wrapperElement = useRef(null);
const yearListElement = useRef(null);
const { getLanguageDigits, getToday } = useLocaleUtils(locale);
const startingYearValue =
selectorStartingYear || getToday().year - MINIMUM_SELECTABLE_YEAR_SUBTRACT;
const endingYearValue = selectorEndingYear || getToday().year + MAXIMUM_SELECTABLE_YEAR_SUM;
const allYears = [];
for (let i = startingYearValue; i <= endingYearValue; i += 1) {
allYears.push(i);
}
useEffect(() => {
const classToggleMethod = isOpen ? 'add' : 'remove';
const activeSelectorYear = wrapperElement.current.querySelector(
'.Calendar__yearSelectorItem.-active',
);
if (!activeSelectorYear) {
throw new RangeError(
`Provided value for year is out of selectable year range. You're probably using a wrong locale prop value or your provided value's locale is different from the date picker locale. Try changing the 'locale' prop or the value you've provided.`,
);
}
wrapperElement.current.classList[classToggleMethod]('-faded');
yearListElement.current.scrollTop =
activeSelectorYear.offsetTop - activeSelectorYear.offsetHeight * 5;
yearListElement.current.classList[classToggleMethod]('-open');
}, [isOpen]);
const renderSelectorYears = () => {
return allYears.map(item => {
const isAfterMaximumDate = maximumDate && item > maximumDate.year;
const isBeforeMinimumDate = minimumDate && item < minimumDate.year;
const isSelected = activeDate.year === item;
return (
<li key={item} className={`Calendar__yearSelectorItem ${isSelected ? '-active' : ''}`}>
<button
tabIndex={isSelected && isOpen ? '0' : '-1'}
className="Calendar__yearSelectorText"
type="button"
onClick={() => {
onYearSelect(item);
}}
disabled={isAfterMaximumDate || isBeforeMinimumDate}
aria-pressed={isSelected}
data-is-default-selectable={isSelected}
>
{getLanguageDigits(item)}
</button>
</li>
);
});
};
const handleKeyDown = e => {
handleKeyboardNavigation(e, { allowVerticalArrows: false });
};
return (
<div
className="Calendar__yearSelectorAnimationWrapper"
role="presentation"
{...(isOpen ? {} : { 'aria-hidden': true })}
>
<div
ref={wrapperElement}
className="Calendar__yearSelectorWrapper"
role="presentation"
data-testid="year-selector-wrapper"
onKeyDown={handleKeyDown}
>
<ul ref={yearListElement} className="Calendar__yearSelector" data-testid="year-selector">
{renderSelectorYears()}
</ul>
</div>
</div>
);
};
YearSelector.defaultProps = {
selectorStartingYear: 0,
selectorEndingYear: 0,
};
export default YearSelector;

@ -0,0 +1,4 @@
export { default as Header } from './Header';
export { default as MonthSelector } from './MonthSelector';
export { default as YearSelector } from './YearSelector';
export { default as DaysList } from './DaysList';

@ -0,0 +1,187 @@
/* @font-face {
font-family: IRANSansBold;
src: url(../../../assets/font/IRANSans/IRANSans_Bold.ttf);
} */
/* @font-face {
font-family: IRANSans;
src: url(../../../assets/font/IRANSans/IRANSans.ttf);
} */
@font-face {
font-family: IRANSansX-Bold;
src: url(../../../assets/font/IRANSansX/Webfonts/fonts/woff2/IRANSansX-Bold.woff2) format("woff2"),
url(../../../assets/font/IRANSansX/Webfonts/fonts/woff/IRANSansX-Bold.woff) format("woff");
}
@font-face {
font-family: IRANSansX-Regular;
src: url(../../../assets/font/IRANSansX/Webfonts/fonts/woff2/IRANSansX-Regular.woff2) format("woff2"),
url(../../../assets/font/IRANSansX/Webfonts/fonts/woff/IRANSansX-Regular.woff) format("woff");
}
@font-face {
font-family: IRANSansXFaNum-Regular;
src: url(../../../assets/font/IRANSansX/Farsi-numerals/IRANSansXFaNum-Regular.ttf) format("woff2"),
url(../../../assets/font/IRANSansX/Farsi-numerals/Webfonts/Woff/IRANSansXFaNum-Regular.woff) format("woff");
}
@font-face {
font-family: IRANSansXFaNum-Bold;
src: url(../../../assets/font/IRANSansX/Farsi-numerals/IRANSansXFaNum-Bold.ttf) format("woff2"),
url(../../../assets/font/IRANSansX/Farsi-numerals/Webfonts/Woff/IRANSansXFaNum-Bold.woff) format("woff");
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.date-box{
width: 100%;
/* height: 106px; */
border-radius: 17px;
/* box-shadow: 0 0 38px -15px #ADADAD; */
border: 1px solid #E0E0E0;
direction: rtl;
background-color: white;
padding-bottom: 15px;
}
.date-box-p1{
width: 90%;
display: inline-flex;
align-items: center;
justify-content: space-between;
margin-top: 10px;
margin-right: 17.5px;
}
.date-box-p1-year-and-month{
display: flex;
align-items: center;
/* font-family: IRANSansBold; */
font-family: IRANSansX-Bold;
font-size: 19px;
color: #df1452;
}
.dbp1-month{
margin-left: 2px;
color: #df1452;
}
.dbp1-year{
margin-right: 2px;
color: #df1452;
font-family: IRANSansXFaNum-Bold;
}
.date-box-p1-time{
display: flex;
align-items: center;
/* font-family: IRANSans; */
font-family: IRANSansX-Regular;
font-size: 9px;
border-radius: 10px;
padding: 1.5px 6px;
background-color: #eac8d5;
border-radius: 2px;
/* color: #013273 !important; */
}
.date-box-p2{
width: 90%;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 6px;
}
.date-box-p2-item{
text-align: center;
position: relative;
cursor: default;
}
.dbp2i-dayname{
font-size: 11px;
/* font-family: IRANSans; */
font-family: IRANSansX-Regular;
color: #A2B4CB;
}
.dbp2i-date{
font-size: 15px;
margin-top: 10px;
padding: 2px;
color: #A9BACF;
font-family: IRANSansXFaNum-Regular;
}
.date-box-p2-item:nth-child(7) .dbp2i-dayname{
color: #FFC491 !important;
}
.date-box-p2-item:nth-child(7) .dbp2i-date{
color: #F6923B !important;
}
.dbp2i-have-Exam{
color: #E3FC08;
position: absolute;
bottom: -15px;
left: 50%;
transform: translateX(-50%);
}
.date-box-p3{
width: 90%;
margin: 0 auto;
margin-top: 18px;
font-family: IRANSansX-Regular;
font-size: 13px;
color: #013273;
}
.date-box-p3-item{
/* display: none; */
max-height: 0px;
transform: scaleY(0);
transform-origin: top;
transition: all 0.5s;
}
.date-box-p3-item-item{
display: flex;
align-items: center;
}
.date-box-p3-item-item-icon{
font-size: 16px;
margin-left: 3px;
}
.date-box-p3-item-active{
/* display: block; */
max-height: 200px;
transform: scaleY(1);
}
/* --------responsive-setting---------------------------------------------------------- */
@media screen and (max-width: 1270px){
.dbp2i-dayname{
font-size: 10px;
}
}
@media screen and (max-width: 1160px){
.dbp2i-dayname{
font-size: 9px;
}
}

@ -0,0 +1,3 @@
export { default} from './DatePicker';
export * from './Calendar';
export { default as utils } from './shared/localeUtils';

@ -0,0 +1,104 @@
export const PERSIAN_NUMBERS = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
export const PERSIAN_MONTHS = [
'فروردین',
'اردیبهشت',
'خرداد',
'تیر',
'مرداد',
'شهریور',
'مهر',
'آبان',
'آذر',
'دی',
'بهمن',
'اسفند',
];
export const GREGORIAN_MONTHS = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
export const PERSIAN_WEEK_DAYS = [
{
name: 'شنبه',
short: 'ش',
},
{
name: 'یکشنبه',
short: 'ی',
},
{
name: 'دوشنبه',
short: 'د',
},
{
name: 'سه شنبه',
short: 'س',
},
{
name: 'چهارشنبه',
short: 'چ',
},
{
name: 'پنجشنبه',
short: 'پ',
},
{
name: 'جمعه',
short: 'ج',
isWeekend: true,
},
];
export const GREGORIAN_WEEK_DAYS = [
{
name: 'Sunday',
short: 'S',
isWeekend: true,
},
{
name: 'Monday',
short: 'M',
},
{
name: 'Tuesday',
short: 'T',
},
{
name: 'Wednesday',
short: 'W',
},
{
name: 'Thursday',
short: 'T',
},
{
name: 'Friday',
short: 'F',
},
{
name: 'Saturday',
short: 'S',
isWeekend: true,
},
];
export const MINIMUM_SELECTABLE_YEAR_SUBTRACT = 100;
export const MAXIMUM_SELECTABLE_YEAR_SUM = 50;
export const TYPE_SINGLE_DATE = 'SINGLE_DATE';
export const TYPE_RANGE = 'RANGE';
export const TYPE_MUTLI_DATE = 'MUTLI_DATE';

@ -0,0 +1,69 @@
import { TYPE_SINGLE_DATE, TYPE_RANGE, TYPE_MUTLI_DATE } from './constants';
/*
These utility functions don't depend on locale of the date picker(Persian or Gregorian)
*/
const createUniqueRange = (number, startingId) =>
Array.from(Array(number).keys()).map(key => ({
value: key + 1,
id: `${startingId}-${key}`,
}));
const isSameDay = (day1, day2) => {
if (!day1 || !day2) return false;
return day1.day === day2.day && day1.month === day2.month && day1.year === day2.year;
};
const putZero = number => (number.toString().length === 1 ? `0${number}` : number);
const toExtendedDay = date => [date.year, date.month, date.day];
const shallowClone = value => ({ ...value });
const deepCloneObject = obj =>
JSON.parse(JSON.stringify(obj, (key, value) => (typeof value === 'undefined' ? null : value)));
const getDateAccordingToMonth = (date, direction) => {
const toSum = direction === 'NEXT' ? 1 : -1;
let newMonthIndex = date.month + toSum;
let newYear = date.year;
if (newMonthIndex < 1) {
newMonthIndex = 12;
newYear -= 1;
}
if (newMonthIndex > 12) {
newMonthIndex = 1;
newYear += 1;
}
const newDate = { year: newYear, month: newMonthIndex, day: 1 };
return newDate;
};
const hasProperty = (object, propertyName) =>
Object.prototype.hasOwnProperty.call(object || {}, propertyName);
const getValueType = value => {
if (Array.isArray(value)) return TYPE_MUTLI_DATE;
if (hasProperty(value, 'from') && hasProperty(value, 'to')) return TYPE_RANGE;
if (
!value ||
(hasProperty(value, 'year') && hasProperty(value, 'month') && hasProperty(value, 'day'))
) {
return TYPE_SINGLE_DATE;
}
throw new TypeError(
`The passed value is malformed! Please make sure you're using one of the valid value types for date picker.`,
);
};
export {
createUniqueRange,
isSameDay,
putZero,
toExtendedDay,
shallowClone,
deepCloneObject,
getDateAccordingToMonth,
getValueType,
};

@ -0,0 +1,10 @@
import { useMemo } from 'react';
import utils from './localeUtils';
import getLanguageText from './localeLanguages';
const useLocaleUtils = locale => useMemo(() => utils(locale), [locale]);
const useLocaleLanguage = locale => useMemo(() => getLanguageText(locale), [locale]);
export { useLocaleUtils, useLocaleLanguage };

@ -0,0 +1,44 @@
const handleArrowKeys = (e, { allowVerticalArrows }) => {
const { activeElement } = document;
const getNthChildSafe = (element, index) => (element ? element.children[index] : null);
const getStandardItem = item => item && (item.hasAttribute('aria-hidden') ? null : item);
const { nextSibling: nextRow, previousSibling: previousRow } = activeElement.parentElement;
const nextSibling = getStandardItem(activeElement.nextSibling || getNthChildSafe(nextRow, 0));
const previousRowLength = previousRow ? previousRow.children.length - 1 : 0;
const previousSibling = getStandardItem(
activeElement.previousSibling || getNthChildSafe(previousRow, previousRowLength),
);
const getVerticalSibling = row =>
getNthChildSafe(row, Array.from(activeElement.parentElement.children).indexOf(activeElement));
const downSibling = getStandardItem(getVerticalSibling(nextRow));
const upSibling = getStandardItem(getVerticalSibling(previousRow));
const isDefaultSelectable = activeElement.dataset.isDefaultSelectable === 'true';
if (!isDefaultSelectable) activeElement.tabIndex = '-1';
const focusIfAvailable = element => {
e.preventDefault();
/* istanbul ignore else */
if (element) {
element.setAttribute('tabindex', '0');
element.focus();
}
};
switch (e.key) {
case 'ArrowRight':
focusIfAvailable(nextSibling);
break;
case 'ArrowLeft':
focusIfAvailable(previousSibling);
break;
case 'ArrowDown':
/* istanbul ignore else */
if (allowVerticalArrows) focusIfAvailable(downSibling);
break;
case 'ArrowUp':
/* istanbul ignore else */
if (allowVerticalArrows) focusIfAvailable(upSibling);
break;
}
};
export default handleArrowKeys;

@ -0,0 +1,85 @@
import jalaali from 'jalaali-js';
import {
GREGORIAN_MONTHS,
PERSIAN_MONTHS,
GREGORIAN_WEEK_DAYS,
PERSIAN_WEEK_DAYS,
PERSIAN_NUMBERS,
} from './constants';
import { toExtendedDay } from './generalUtils';
const localeLanguages = {
en: {
months: GREGORIAN_MONTHS,
weekDays: GREGORIAN_WEEK_DAYS,
weekStartingIndex: 0,
getToday(gregorainTodayObject) {
return gregorainTodayObject;
},
toNativeDate(date) {
return new Date(date.year, date.month - 1, date.day);
},
getMonthLength(date) {
return new Date(date.year, date.month, 0).getDate();
},
transformDigit(digit) {
return digit;
},
nextMonth: 'Next Month',
previousMonth: 'Previous Month',
openMonthSelector: 'Open Month Selector',
openYearSelector: 'Open Year Selector',
closeMonthSelector: 'Close Month Selector',
closeYearSelector: 'Close Year Selector',
from: 'from',
to: 'to',
defaultPlaceholder: 'Select...',
digitSeparator: ',',
yearLetterSkip: 0,
isRtl: false,
},
fa: {
months: PERSIAN_MONTHS,
weekDays: PERSIAN_WEEK_DAYS,
weekStartingIndex: 1,
getToday({ year, month, day }) {
const { jy, jm, jd } = jalaali.toJalaali(year, month, day);
return { year: jy, month: jm, day: jd };
},
toNativeDate(date) {
const gregorian = jalaali.toGregorian(...toExtendedDay(date));
return new Date(gregorian.gy, gregorian.gm - 1, gregorian.gd);
},
getMonthLength(date) {
return jalaali.jalaaliMonthLength(date.year, date.month);
},
transformDigit(digit) {
return digit
.toString()
.split('')
.map(letter => PERSIAN_NUMBERS[Number(letter)])
.join('');
},
nextMonth: 'ماه بعد',
previousMonth: 'ماه قبل',
openMonthSelector: 'نمایش انتخابگر ماه',
openYearSelector: 'نمایش انتخابگر سال',
closeMonthSelector: 'بستن انتخابگر ماه',
closeYearSelector: 'بستن انتخابگر ماه',
from: 'از',
to: 'تا',
defaultPlaceholder: 'انتخاب...',
digitSeparator: '،',
yearLetterSkip: -2,
isRtl: true,
},
};
const getLocaleDetails = locale => {
if (typeof locale === 'string') return localeLanguages[locale];
return locale;
};
export { localeLanguages };
export default getLocaleDetails;

@ -0,0 +1,61 @@
/*
These utility functions highly depend on locale of the date picker(Persian or Gregorian)
*/
import getLocaleDetails from './localeLanguages';
const utils = (locale = 'en') => {
const {
months: monthsList,
getToday: localeGetToday,
toNativeDate,
getMonthLength,
weekStartingIndex,
transformDigit: getLanguageDigits,
} = typeof locale === 'string' ? getLocaleDetails(locale) : locale;
const getToday = () => {
const todayDate = new Date();
const year = todayDate.getFullYear();
const month = todayDate.getMonth() + 1;
const day = todayDate.getDate();
return localeGetToday({ year, month, day });
};
const getMonthName = month => monthsList[month - 1];
const getMonthNumber = monthName => monthsList.indexOf(monthName) + 1;
const getMonthFirstWeekday = date => {
const gregorianDate = toNativeDate({ ...date, day: 1 });
const weekday = gregorianDate.getDay();
const dayIndex = weekday + weekStartingIndex;
return dayIndex % 7;
};
const isBeforeDate = (day1, day2) => {
if (!day1 || !day2) return false;
return toNativeDate(day1) < toNativeDate(day2);
};
const checkDayInDayRange = ({ day, from, to }) => {
if (!day || !from || !to) return false;
const nativeDay = toNativeDate(day);
const nativeFrom = toNativeDate(from);
const nativeTo = toNativeDate(to);
return nativeDay > nativeFrom && nativeDay < nativeTo;
};
return {
getToday,
getMonthName,
getMonthNumber,
getMonthLength,
getMonthFirstWeekday,
isBeforeDate,
checkDayInDayRange,
getLanguageDigits,
};
};
export default utils;

@ -0,0 +1,33 @@
import { getDateAccordingToMonth } from './generalUtils';
const getSlideDate = ({ parent, isInitialActiveChild, activeDate, monthChangeDirection }) => {
if (!parent) {
return isInitialActiveChild ? activeDate : getDateAccordingToMonth(activeDate, 'NEXT');
}
const child = parent.children[isInitialActiveChild ? 0 : 1];
const isActiveSlide =
child.classList.contains('-shown') || child.classList.contains('-shownAnimated'); // check -shownAnimated for Safari bug
return isActiveSlide ? activeDate : getDateAccordingToMonth(activeDate, monthChangeDirection);
};
const animateContent = ({ parent, direction }) => {
const wrapperChildren = Array.from(parent.children);
const shownItem = wrapperChildren.find(child => child.classList.contains('-shown'));
const hiddenItem = wrapperChildren.find(child => child !== shownItem);
const baseClass = shownItem.classList[0];
const isNextMonth = direction === 'NEXT';
const getAnimationClass = value => (value ? '-hiddenNext' : '-hiddenPrevious');
hiddenItem.style.transition = 'none';
shownItem.style.transition = '';
shownItem.className = `${baseClass} ${getAnimationClass(!isNextMonth)}`;
hiddenItem.className = `${baseClass} ${getAnimationClass(isNextMonth)}`;
hiddenItem.classList.add('-shownAnimated');
};
const handleSlideAnimationEnd = ({ target }) => {
target.classList.remove('-hiddenNext');
target.classList.remove('-hiddenPrevious');
target.classList.replace('-shownAnimated', '-shown');
};
export { animateContent, getSlideDate, handleSlideAnimationEnd };

@ -0,0 +1,817 @@
.Calendar *{
font-family: 'iranSans';
}
.DatePicker {
position: relative;
display: inline-block;
z-index: 100;
}
.DatePicker__input {
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.4);
padding: 0.6em 1.2em;
font-family:'iranSans';
text-align: center;
font-size: 12px;
border-radius: 7px;
}
.DatePicker__input:focus{
outline:1px solid #06BACE;
color: #06BACE;
}
.DatePicker__input.-rtl {
direction: rtl;
}
.DatePicker__input::placeholder {
color: #979797;
}
.DatePicker__input:focus::placeholder{
color: #06BACE;
}
.DatePicker__calendarContainer.-top + .DatePicker__calendarArrow {
top: auto;
bottom: calc(100% + 10px);
transform: translateY(-2.5rem) rotate(180deg);
animation: fadeArrowFlipped 0.3s forwards;
}
.DatePicker__calendarContainer {
position: absolute;
top: calc(100% + 20px);
left: 50%;
transform: translateX(-50%);
}
.DatePicker__calendarContainer.-top {
top: auto;
bottom: calc(100% + 20px);
}
.Calendar,
.Calendar * {
margin: 0;
padding: 0;
box-sizing: border-box;
direction: ltr;
}
.Calendar,
.Calendar.-rtl * {
direction: rtl;
}
.DatePicker__calendarArrow {
position: absolute;
width: 0;
height: 0;
top: calc(100% + 10px);
left: 0;
right: 0;
margin: 0 auto;
border-style: solid;
z-index: 10;
border-width: 0 10px 10px 10px;
border-color: transparent transparent #fff transparent;
}
.Calendar {
--cl-color-black: #444444;
--cl-color-disabled: #d4d4d4;
--cl-color-error: #ff2929;
font-family:'iranSans';
font-size: 10px;
background: rgba(245, 245, 245, 0.53);
border:1px solid #DBDBDB;
box-shadow: 0 1em em rgba(0, 0, 0, 0.07);
border-radius: 1em;
position: relative;
user-select: none;
/* padding-top: 1.2em; */
display: flex;
flex-direction: column;
width: 90%;
z-index: 10;
max-width: 90vw;
/* min-height: 38.7em; */
}
.Calendar.dashboard{
--cl-color-black: #444444;
--cl-color-disabled: #d4d4d4;
--cl-color-error: #ff2929;
font-family:'iranSans';
font-size: 10px;
background: rgba(255, 255, 255, 1);
border:1px solid #EDF2FB;
box-shadow: 0 1em em rgba(0, 0, 0, 0.07);
border-radius: 1em;
position: relative;
user-select: none;
display: flex;
flex-direction: column;
width: 100%;
z-index: 10;
max-width: 90vw;
/* min-height: 38.7em; */
}
.DatePicker .Calendar,
.DatePicker__calendarArrow {
transform: translateY(2.5em);
opacity: 0;
animation: fadeCalendar 0.3s forwards;
}
.DatePicker__calendarContainer.-top .Calendar {
transform: translateY(-2.5em);
}
.Calendar.-noFocusOutline *:focus {
outline: none !important;
}
.Calendar > :not(.Calendar__footer) button {
font-family: inherit;
background: transparent;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
outline: none;
}
.Calendar__header {
display: flex;
color: var(--cl-color-black);
padding: 10px ;
align-items: center;
overflow: hidden;
}
.Calendar__monthArrowWrapper:focus {
outline: 1px dashed rgba(0, 0, 0, 0.4);
outline-offset: 2px;
}
.Calendar__monthArrowWrapper:disabled,
.Calendar__monthArrowWrapper.-hidden {
opacity: 0;
pointer-events: none;
}
.Calendar__monthArrowWrapper.-left {
transform: rotate(180deg);
}
.Calendar.-rtl .Calendar__monthArrowWrapper.-left {
transform: rotate(-180deg);
}
.Calendar__monthArrowWrapper.-right {
transform: rotate(-0deg);
}
.Calendar.-rtl .Calendar__monthArrowWrapper.-right {
transform: rotate(0deg);
}
.Calendar__monthArrowWrapper:active .Calendar__monthArrow {
transform: scale(0.7);
}
.Calendar__monthYearContainer {
flex: 1;
position: relative;
}
.Calendar__monthYear {
font-size: 20px;
font-weight: 500;
display: flex;
align-items: center;
position: absolute;
top: 0;
bottom: 0;
/* left: 50%; */
right:0;
background-color: green;
will-change: transform, opacity;
backface-visibility: hidden;
transform: translateZ(0);
transition: var(--animation-duration);
line-height: 1;
color:#df1452;
}
.Calendar__monthYear.dashboard {
font-size: 20px;
font-weight: 500;
display: flex;
align-items: center;
position: absolute;
top: 0;
bottom: 0;
/* left: 50%; */
will-change: transform, opacity;
backface-visibility: hidden;
transform: translateZ(0);
transition: var(--animation-duration);
line-height: 1;
color:#df1452;
}
.Calendar__monthYear.-hiddenNext {
opacity: 0;
display: none;
transform: translateX(50%);
}
.Calendar.-rtl .Calendar__monthYear.-hiddenNext {
transform: translateX(-150%);
}
.Calendar__monthYear.-hiddenPrevious {
opacity: 0;
transform: translateX(-150%);
}
.Calendar.-rtl .Calendar__monthYear.-hiddenPrevious {
transform: translateX(50%);
}
.Calendar__monthYear.-shown {
opacity: 1;
margin-top: auto;
margin-bottom: auto;
transform: translateX(-50%);
}
.Calendar__monthYear.-shownAnimated {
animation: var(--animation-duration) fadeTextToCenter forwards;
}
.Calendar__monthYear > * {
padding: 0.2em 0.5em;
border: 1px solid transparent;
transition: var(--animation-duration);
font-size: 1.05em;
display: flex;
justify-content: center;
align-items: center;
transform: translateX(0) scale(0.95);
will-change: transform;
border-radius: 5px;
}
.Calendar__monthYear:not(.-shown) > *,
.Calendar__monthYear > *.-hidden {
cursor: default;
pointer-events: none;
}
.Calendar__monthText {
margin-left: -0.3em;
}
.Calendar__yearText:last-child {
margin-right: -0.3em;
}
.Calendar__monthYear.-shown > *:hover,
.Calendar:not(.-noFocusOutline) .Calendar__monthYear.-shown > *:focus,
.Calendar__monthYear > *.-activeBackground {
background: #f5f5f5;
}
.Calendar__monthText:hover {
transform: translateX(-0.2em) scale(0.95);
}
.Calendar.-rtl .Calendar__monthText:hover {
transform: translateX(0.2em) scale(0.95);
}
.Calendar__yearText:hover {
transform: translateX(0.2em) scale(0.95);
}
.Calendar.-rtl .Calendar__yearText:hover {
transform: translateX(-0.2em) scale(0.95);
}
.Calendar__monthYear .Calendar__yearText.-hidden {
transform: translateX(50%);
opacity: 0;
}
.Calendar.-rtl .Calendar__monthYear .Calendar__yearText.-hidden {
transform: translateX(-50%);
}
.Calendar__monthYear .Calendar__monthText.-hidden {
transform: translateX(-50%);
opacity: 0;
}
.Calendar.-rtl .Calendar__monthYear .Calendar__monthText.-hidden {
transform: translateX(50%);
}
.Calendar__monthYear:not(.-shown) > * {
pointer-events: none;
}
.Calendar__monthSelectorAnimationWrapper,
.Calendar__yearSelectorAnimationWrapper {
position: absolute;
width: 100%;
height: 80%;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.Calendar__monthSelectorWrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.Calendar__monthSelector {
padding: 0 2.5em;
align-content: center;
padding-bottom: 2em;
}
.Calendar__monthSelector,
.Calendar__yearSelector {
display: flex;
flex-wrap: wrap;
position: relative;
z-index: 2;
background-color: #fff;
transform: translateY(-150%);
will-change: transform;
transition: 0.6s;
height: 100%;
}
.Calendar__yearSelectorWrapper {
width: 100%;
height: 100%;
}
.Calendar__yearSelectorWrapper::after,
.Calendar__yearSelectorWrapper::before {
content: '';
width: 100%;
height: 5em;
position: absolute;
left: 0;
opacity: 0;
transition: 0.4s;
transition-delay: 0.2s;
}
.Calendar__yearSelectorWrapper::after {
background-image: linear-gradient(to bottom, #fff, #fff 10%, rgba(245, 245, 245, 0));
top: -0.1em;
}
.Calendar__yearSelectorWrapper::before {
background-image: linear-gradient(to top, #fff, #fff 10%, rgba(245, 245, 245, 0));
bottom: 0;
}
.Calendar__yearSelectorWrapper.-faded::after,
.Calendar__yearSelectorWrapper.-faded::before {
opacity: 1;
z-index: 3;
}
.Calendar__yearSelector {
align-content: flex-start;
scrollbar-width: 0;
overflow: scroll;
position: relative;
width: 100%;
padding: 5em 2em;
-ms-overflow-style: none;
}
.Calendar__yearSelector::-webkit-scrollbar {
display: none;
}
.Calendar__yearSelectorItem {
width: 25%;
display: flex;
justify-content: center;
}
.Calendar__yearSelectorItem:not(:nth-child(-n + 4)) {
margin-top: 1.5em;
}
.Calendar__yearSelectorText {
border: none;
font-size: 1.4em;
min-width: 85%;
padding: 0.2em 0.5em;
border-radius: 5px;
}
.Calendar__monthSelector.-open,
.Calendar__yearSelector.-open {
transform: translateY(0);
}
.Calendar__yearSelectorText:focus,
.Calendar__monthSelectorItemText:focus {
outline: 1px dashed rgba(0, 0, 0, 0.4);
outline-offset: 2px;
}
.Calendar__monthSelectorItem {
width: calc(100% / 3);
display: flex;
justify-content: center;
}
.Calendar__monthSelectorItem:not(:nth-child(-n + 3)) {
margin-top: 2em;
}
.Calendar__monthSelectorItemText {
border: none;
padding: 0.4em 0.4em;
border-radius: 8.5px;
font-size: 1.3em;
min-width: 70%;
transition: 0.3s;
}
.Calendar__monthSelectorItem:not(.-active) .Calendar__monthSelectorItemText:not(:disabled):hover,
.Calendar__yearSelectorItem:not(.-active) .Calendar__yearSelectorText:not(:disabled):hover {
background: #f5f5f5;
}
.Calendar__monthSelectorItemText:disabled,
.Calendar__yearSelectorText:disabled {
opacity: 0.5;
cursor: default;
}
.Calendar__monthSelectorItem.-active .Calendar__monthSelectorItemText,
.Calendar__yearSelectorItem.-active .Calendar__yearSelectorText {
background-color: #006C94;
color: #fff;
}
.Calendar__weekDays {
display: flex;
justify-content: space-between;
color: var(--cl-color-disabled);
font-size: 1.2em;
/* padding: 0 2.6em; */
position: relative;
}
.Calendar__weekDays.dashboard {
display: flex;
justify-content: space-between;
color: var(--cl-color-disabled);
font-size: 10px;
margin-top: 10px;
/* padding: 10px 15px; */
position: relative;
/* background-color: #EDF2FB; */
}
.Calendar__weekDay {
display: block;
width: calc(100% / 7);
/* background: #00253A; */
text-align: center;
text-decoration: none;
border: 0px;
color: #06BACE;
/* margin:0.2em; */
white-space: nowrap;
}
.Calendar__weekDay.dashboard{
color:#A2B4CB;
}
.Calendar__weekDay[title]{
text-decoration: none;
}
.Calendar__sectionWrapper {
position: relative;
min-height: 275px;
overflow: hidden;
}
.Calendar__section {
display: flex;
flex-direction: column;
position: absolute;
color: var(--cl-color-black);
top: 0;
/* padding-top: 0.5em; */
left: 0;
width: 100%;
will-change: transform, opacity;
transform: translateZ(0);
backface-visibility: hidden;
transition: var(--animation-duration);
}
.Calendar__section.-hiddenPrevious {
opacity: 0.5;
transform: translateX(-100%);
}
.Calendar.-rtl .Calendar__section.-hiddenPrevious {
transform: translateX(100%);
}
.Calendar__section.-hiddenNext {
opacity: 0.5;
transform: translateX(100%);
}
.Calendar.-rtl .Calendar__section.-hiddenNext {
transform: translateX(-100%);
}
.Calendar__section.-shown {
opacity: 1;
transform: translateX(0);
}
.Calendar__section.-shownAnimated {
animation: var(--animation-duration) FadeContentToCenter forwards;
}
.Calendar__weekRow {
display: flex;
width: 100%;
}
.Calendar__day {
width: calc(100% / 7 );
text-align: center;
padding: calc(0.25em - 1px);
font-size: 1.6em;
border-radius: 7px;
transition: 0.2s;
border: 1px solid transparent;
margin:3px;
color: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
cursor: pointer;
vertical-align: middle;
background-color: #F3F3F3;
color:#06BACE;
}
.Calendar__day.dashboard {
width: calc(100% / 7 - 6px);
text-align: center;
padding: calc(0.25em - 1px);
font-size: 1.6em;
border-radius: 7px;
transition: 0.2s;
border: 1px solid transparent;
margin:3px;
color: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
cursor: pointer;
vertical-align: middle;
background-color: transparent;
color:#00253A;
}
.Calendar__day span{
padding: -10px;
margin-top: -30px;
font-size: 28px;
}
.Calendar__day:focus {
outline: 1px dashed rgba(0, 0, 0, 0.4);
outline-offset: 2px;
}
.Calendar__day.-ltr {
min-height: 2.6em;
font-size: 1.45em;
}
.Calendar__day.-rtl {
font-size: 1.55em;
height: 40px;
}
.Calendar__day:not(.-blank):not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween):not(.-selected):hover {
background-color: rgba(223, 20, 82, 0.06);
color: #df1452;
border:1px solid #df1452;
}
.Calendar__day.-selected,
.Calendar__day.-selectedStart,
.Calendar__day.-selectedEnd {
background: rgba(223, 20, 82, 0.06);
color: #df1452;
}
.Calendar__day.-ltr.-selectedStart {
border-radius: 0;
border-top-left-radius: 7px;
border-bottom-left-radius: 7px;
}
.Calendar__day.-rtl.-selectedStart {
border-radius: 0;
border-top-right-radius: 7px;
border-bottom-right-radius: 7px;
}
.Calendar__day.-selectedBetween {
background:rgba(0, 108, 148, 0.07);
border-radius: 0;
}
.Calendar__day.-ltr.-selectedEnd {
border-radius: 0;
border-top-right-radius: 7px;
border-bottom-right-radius: 7px;
}
.Calendar__day.-rtl.-selectedEnd {
border-radius: 0;
border-top-left-radius: 7px;
border-bottom-left-radius: 7px;
}
.Calendar__day.-weekend:not(.-selected):not(.-blank):not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween) {
color: var(--cl-color-error);
}
.Calendar__day.-weekend.-today:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween)::after {
background: var(--cl-color-error);
}
.Calendar__day.-disabled {
color: var(--cl-color-disabled) !important;
background: transparent !important;
cursor: default !important;
}
.Calendar__day.-selected {
}
.Calendar__day.-today:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween) {
font-weight: 600;
color: var(--cl-color-black);
color: #000;
position: relative;
}
.Calendar__day.-today:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween)::after {
content: '';
position: absolute;
bottom: 0.2em;
display: block;
width: 0.6em;
height: 1px;
background: #000;
left: 50%;
opacity: 0.5;
transform: translateX(-50%);
transition: 0.2s;
}
.Calendar__day.-today:hover:not(.-selectedStart):not(.-selectedEnd):not(.-selectedBetween)::after {
opacity: 0;
}
.Calendar__day.-blank {
color: transparent;
cursor: default;
pointer-events: none;
}
.Calendar__footer {
position: relative;
z-index: 1;
}
.Calendar__footer .footer__Events{
display: flex;
flex-direction: column;
align-items: center;
font-size: 12px;
font-family: 'IranSans';
padding: 3px;
}
.Calendar__footer .footer__Events.dashboard{
display: flex;
justify-content: start;
width: 100%;
align-items: flex-start;
font-size: 12px;
font-family: 'IranSans';
margin-top: 10px;
padding: 1em 2em;
border-top: 1px solid #EDF2FB;
}
.Calendar__footer .footer__Events.dashboard p{
font-size: 15px;
margin:2.5px 0px
}
.Calendar .holiday span{
color:#ff2929;
}
.Calendar .DayNumDiv{
display: flex;
flex-direction: column;
}
.Calendar .DayNumDiv span{
margin: 0;
padding: 0;
margin-bottom: -5px;
}
.Calendar .DayNumDiv .eventDots{
margin-top: -10px;
font-size: 20px;
}
.GoToTodayButton{
background-color: #006C94;
padding: 7.5px;
font-size: 12px;
color:white;
font-family: 'iranSans';
border-radius: 50%;
float: left;
margin: 15px;
}
@keyframes fadeCalendar {
from {
opacity: 0;
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeArrowFlipped {
from {
opacity: 0;
}
to {
opacity: 1;
transform: translateY(0) rotate(180deg);
}
}
@keyframes fadeTextToCenter {
to {
opacity: 1;
transform: translateX(-50%);
}
}
@keyframes FadeContentToCenter {
to {
opacity: 1;
transform: translateX(0);
}
}

@ -0,0 +1,117 @@
import React, { useState } from "react";
import './index.css';
import Calendar from "./CalendarComponents/Calendar";
import { utils } from "./CalendarComponents";
import './index.css';
const SimpleCalendar = () => {
const [selectedDay, setSelectedDay] = useState(null);
const [type, setType] = useState('dashboard');
const list = {
'default': <Calendar
value={selectedDay}
onChange={setSelectedDay}
shouldHighlightWeekends
renderFooter={() => <center><button className="GoToTodayButton" onClick={() => setSelectedDay(utils('fa').getToday())}> امروز </button></center>}
locale="fa"
events={eventsList}
/>,
'dashboard': <Calendar
value={selectedDay}
onChange={setSelectedDay}
shouldHighlightWeekends
locale="fa"
events={eventsList}
type='dashboard'
/>,
}
return (
<div className=" w-full ">
{/* <Calendar
value={selectedDay}
onChange={setSelectedDay}
shouldHighlightWeekends
renderFooter={() => <center><button className="GoToTodayButton" onClick={() => setSelectedDay(utils('fa').getToday())}> امروز </button></center>}
locale="fa"
events={eventsList}
type='dashboard'
/> */}
<Calendar
value={selectedDay}
onChange={setSelectedDay}
shouldHighlightWeekends
calendarTodayClassName={'text-red52'}
locale="fa"
events={eventsList}
type='dashboard'
/>
</div>
);
};
const eventsList = [
{
id: 2,
description: "تست 2",
type: "global",
isHoliday: true,
date: "2022-01-04T00:00:00.000Z",
year: 1400,
month: 10,
day: 2
},
{
id: 4,
description: "تست 4",
type: "global",
isHoliday: true,
date: "2022-01-12T00:00:00.000Z",
year: 1400,
month: 10,
day: 1
},
{
id: 1,
description: "تست کاربر 1",
type: "userDefined",
userId: "5",
date: "2022-01-12T00:00:00.000Z",
categoryId: 1,
year: 1400,
month: 10,
day: 3,
color: 'blue'
},
{
id: 4,
description: "تست کاربر 4",
type: "userDefined",
userId: "5",
date: "2022-01-08T00:00:00.000Z",
categoryId: 3,
year: 1400,
month: 11,
day: 6
},
{
id: 5,
description: "تست کاربر 5",
type: "userDefined",
userId: "5",
date: "2022-01-12T00:00:00.000Z",
categoryId: 1,
year: 1400,
month: 10,
day: 3
}
];
export default SimpleCalendar;

@ -0,0 +1,298 @@
.my-exam-list{
width: 100%;
/* margin-top: 25px; */
direction: rtl;
}
.my-exam-list-content{
width: 100%;
border: 1px solid #E0E0E0;
overflow: hidden;
background-color: white;
}
.melc-header{
width: 100%;
height: 65px;
display: flex;
align-items: center;
border-bottom: 5px solid #F6F6F6;
position: relative;
}
.melc-h-tab-name-item{
width: fit-content;
padding: 0 10px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 17px;
font-family: IRANSans;
color: #B1B1B1;
margin-right: 35px;
position: relative;
cursor: pointer;
}
.melc-h-tab-name-item-line{
width: 100%;
height: 5px;
background-color: #df1452;
position: absolute;
right: 0;
border-radius: 10px;
bottom: -5px;
}
.melc-h-move-btns{
position: absolute;
left: 27px;
height: 100%;
display: flex;
width: 70px;
justify-content: space-between;
align-items: center;
direction: ltr;
font-size: 15px;
font-family: IRANSans;
color: #df1452;
}
.melc-h-move-btns *{
font-size: 30px;
color: #df1452;
cursor: pointer;
}
.melc-content{
width: 100%;
height: 281px;
position: relative;
}
.melc-content-dark-cover{
position: absolute;
top: 30px;
left: -187px;
/* height: 100%; */
width: 14.42vw;
aspect-ratio: 0.989/1;
border-radius: 0 12px 30px;
background-color: rgb(0, 0, 0);
opacity: 0.7;
}
.melc-content-item{
/* width: 100%; */
/* height: 280px; */
margin: 30px 0;
/* margin-top: 30px; */
margin-right: 35px;
display: flex;
position: absolute;
top: 0;
right: 0;
transition: all 0.6s ease;
}
.melc-content-item-more{
width: 221px;
flex-shrink: 0;
height: 221px;
border-radius: 25px 12px 30px 6px;
margin-left: 20px;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
font-size: 30px;
font-family: IRANSans;
color: #df1452;
border: 2px solid #E0E0E0;
cursor: pointer;
}
.melc-content-item-more:hover{
background-color: #E0E0E0;
/* background-color: rgba(46,129,232, 0.1); */
color: white;
}
.melc-content-i-item{
width: 221px;
/* width: 27.34%; */
/* width: 14.42vw !important;
aspect-ratio: 0.989/1; */
flex-shrink: 0;
height: 221px;
position: relative;
border-radius: 25px 12px 30px 6px;
margin-left: 20px;
overflow: hidden;
}
.melc-c-i-i-bg{
width: 100%;
height: 100%;
}
.melc-c-i-i-exam-sit{
position: absolute;
top: 20px;
left: 10px;
padding: 5px 5px;
display: flex;
align-items: center;
color: #FF0000;
background-color: white;
border-radius: 5px;
}
.melc-c-i-i-exam-sit-text{
margin-right: 1px;
font-size: 9px;
font-weight: 700;
font-family: IRANSans;
}
.melc-c-i-i-cover{
width: 100%;
height: 100%;
position: absolute;
top:0;
right: 0;
background: rgb(0,0,0);
background: linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 100%);
}
.melc-c-i-i-under-cover{
width: 100%;
height: 100%;
position: absolute;
top:0;
right: 0;
transform: scaleY(0);
transform-origin: bottom;
transition: all 0.5s ease;
}
.melc-c-i-item-info{
position: absolute;
bottom: 17px;
right: 50%;
transform: translateX(50%);
width: 90%;
/* background-color: aquamarine; */
}
.melc-c-i-i-info-title{
display: flex;
align-items: center;
color: white;
font-size: 14px;
font-family: IRANSans;
}
.melc-c-i-i-info-title img{
margin-left: 5px;
}
.melc-c-i-i-info-date-time{
display: flex;
align-items: center;
justify-content: space-between;
}
.melc-ciiidt-date-container{
display: flex;
align-items: center;
margin-right: 3px;
color: white;
}
.melc-clock-icon{
font-size: 20px;
}
.melc-ciiidt-date{
color: white;
font-size: 10px;
font-family: IRANSansXFaNum-Regular;
margin-right: 5px;
}
.melc-ciiidt-time{
color: white;
font-size: 10px;
font-family: IRANSans;
margin-left: 5px;
}
.melc-c-i-i-info-line{
width: 100%;
height: 1px;
background-color: white;
opacity: 13%;
margin-top: 3px;
margin-bottom: 3px;
}
.melc-c-i-i-info-descriptin{
width: 100%;
font-size: 11px;
font-family: IRANSans;
color: white;
max-height: 0;
transform: translateY(140px);
overflow: hidden;
text-overflow: ellipsis;
transition: all 0.5s ease;
/* margin-top: 10px;
margin-bottom: 5px; */
}
.descript_is_active{
/* margin-top: 15px; */
/* display: block; */
transform: translateY(0);
/* overflow: hidden; */
display: -webkit-box;
-webkit-line-clamp: 4; /* number of lines to show */
-webkit-box-orient: vertical;
max-height: none;
margin-top: 10px;
margin-bottom: 5px;
}
/* * --------responsive-setting---------------------------------------------------------- */
@media screen and (max-width: 1200px){
.melc-h-tab-name-item{
font-size: 15px;
}
}
@media screen and (max-width: 1110px){
.melc-h-tab-name-item{
font-size: 13px;
}
}
@media screen and (max-width: 1070px){
.melc-h-tab-name-item{
font-size: 12px;
}
}

@ -0,0 +1,355 @@
import "./index.css";
import { IoIosArrowBack, IoIosArrowForward } from "react-icons/io";
import { GoPrimitiveDot } from "react-icons/go";
import calendar_icon from "../../../assets/img/stickynote.svg";
import { BsClock } from "react-icons/bs";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Link } from "react-router-dom";
import moment from "jalali-moment";
import { state } from "./state";
import ScrollContainer from "react-indiana-drag-scroll";
const MyExamList = () => {
//create suitable data list with main data----------------------------------------------------
let d = new Date();
console.log("today:"+d);
let d_day = d.getDay();
console.log("today_day:"+d_day);
let LastDayWeekDate=d;
switch (d_day) {
case 1:
LastDayWeekDate.setDate(d.getDate() + 4);
break;
case 2:
LastDayWeekDate.setDate(d.getDate() + 3);
break;
case 3:
LastDayWeekDate.setDate(d.getDate() + 2);
break;
case 4:
LastDayWeekDate.setDate(d.getDate() + 1);
break;
case 6:
LastDayWeekDate.setDate(d.getDate() + 6);
break;
case 7:
LastDayWeekDate.setDate(d.getDate() + 5);
break;
default:
LastDayWeekDate=d
break;
}
let my_exam_list_data2 = [
{
id: 1,
tab_name: "همه",
isActive: true,
tab_content: []
},
{
id: 2,
tab_name: "آزمونهای این هفته",
isActive: false,
tab_content: []
},
{
id: 3,
tab_name: "آزمونهای آینده",
isActive: false,
tab_content: []
},
{
id: 4,
tab_name: "آزمونهای در حال برگزاری",
isActive: false,
tab_content: []
},
]
for(let b=0;b<state.length;b++){
if(b<8){
let date = new Date(state[b].date);
let TabType = 1;
console.log(date);
let endDate = new Date(state[b].endDate);
if(date<LastDayWeekDate){
TabType = 1;
my_exam_list_data2[1].tab_content.push({...state[b],tabType:1,sub_id:2});
}
else if(date>LastDayWeekDate){
TabType = 2;
my_exam_list_data2[2].tab_content.push({...state[b],tabType:2,sub_id:3});
}
let D = new Date();
if(D>date && D<endDate){
TabType = 3;
my_exam_list_data2[3].tab_content.push({...state[b],tabType:3,sub_id:4});
}
my_exam_list_data2[0].tab_content.push({...state[b],sub_id:1,tabType:TabType});
}
}
console.log(my_exam_list_data2);
const [data, set_data] = useState(my_exam_list_data2);
//------------------------------------------------------
//cover style list ------------------------------------
let coverStyleList=[
{
background:"linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 60%)",
},
{
background:"linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 60%)",
},
{
background:"linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 60%)",
},
]
let underCoverStyleList=[
{
background:"#000",
opacity:0.5
},
{
background:"#000",
opacity:0.5
},
{
background:"#000",
opacity:0.5
},
]
//-----------------------------------------------------------
const [old_tab_id, set_old_tab_id] = useState(1);
useEffect(() => {
// console.log("render---------------");
document.querySelector(".melc-content-item").style.right = `0px`;
});
const change_tab = (id) => {
let new_data = data.map((item) => {
if (item.id === old_tab_id) {
item.isActive = false;
}
if (item.id === id) {
item.isActive = true;
}
return { ...item };
});
// console.log(new_data);
set_data(new_data);
set_old_tab_id(id);
// console.log(old_tab_id);
};
let i = 0;
let max_i;
for (let j = 0; j < data.length; j++) {
// console.log(data[j].isActive);
if (data[j].isActive) {
max_i = (data[j].tab_content.length - 3) * -1;
// console.log(max_i);
}
}
// const state = useSelector((state) => state.default);
if (state.openNav === "open") {
max_i--;
if (window.innerWidth < 1360) {
let tab_name_item = document.querySelectorAll(".melc-h-tab-name-item");
for (let p = 0; p < tab_name_item.length; p++) {
tab_name_item[p].style.fontSize = "15px";
}
}
if (window.innerWidth < 1305) {
let tab_name_item = document.querySelectorAll(".melc-h-tab-name-item");
for (let p = 0; p < tab_name_item.length; p++) {
tab_name_item[p].style.fontSize = "13px";
}
}
if (window.innerWidth < 1212) {
let tab_name_item = document.querySelectorAll(".melc-h-tab-name-item");
for (let p = 0; p < tab_name_item.length; p++) {
tab_name_item[p].style.fontSize = "11px";
}
}
}
if (window.innerWidth < 1536) {
max_i--;
}
if (window.innerWidth < 1170) {
max_i--;
}
const move_left = () => {
if (i > max_i) {
i--;
let movment = i * 245;
document.querySelector(".melc-content-item").style.right = `${movment}px`;
}
};
const move_right = () => {
if (i < 0) {
i++;
let movment = i * 245;
document.querySelector(".melc-content-item").style.right = `${movment}px`;
}
};
let s = 0;
const item_active_hover = (id, sub_id) => {
// console.log(id,sub_id);
// s = 0;
let ss = 0;
for (let k = 0; k < data.length; k++) {
s = 0;
for (let v = 0; v < data[k].tab_content.length; v++) {
// console.log(data[k].tab_content[v])
s++;
if (
data[k].tab_content[v].id === id &&
data[k].tab_content[v].sub_id === sub_id
) {
ss = 1;
break;
}
}
if (ss) {
break;
}
}
// console.log(s);
document.querySelectorAll(".melc-c-i-i-under-cover")[
s - 1
].style.transform = "scaleY(1)";
document
.querySelectorAll(".melc-c-i-i-info-descriptin")
[s - 1].classList.add("descript_is_active");
// document.querySelectorAll(".melc-c-i-i-info-descriptin")[s-1].style.transform="scaleY(1)";
// console.log(e.target.previousElementSibling);
//این روش پایدار نیست
// if(e.target.previousElementSibling !=null){
// e.target.previousElementSibling.style.transform="scaleY(1)";
// }
};
const item_deactive_hover = (id, sub_id) => {
if (s > 0) {
document.querySelectorAll(".melc-c-i-i-under-cover")[
s - 1
].style.transform = "scaleY(0)";
document
.querySelectorAll(".melc-c-i-i-info-descriptin")
[s - 1].classList.remove("descript_is_active");
}
// if(e.target.previousElementSibling !=null){
// e.target.previousElementSibling.style.transform="scaleY(0)";
// }
};
moment.locale("en");
return (
<div className="my-exam-list">
<div className="my-exam-list-content rounded-lg">
<h1 className="text-right w-full text-red52 pt-4 px-6">لیست آزمون های من</h1>
<div className="melc-header">
{data.map((item, i) => (
<div
style={item.isActive ? { color: "#df1452" } : null}
key={item.id || i}
className="melc-h-tab-name-item"
onClick={() => change_tab(item.id)}
>
{item.tab_name}
{item.isActive && (
<div className="melc-h-tab-name-item-line"></div>
)}
</div>
))}
<div className="melc-h-move-btns">
<IoIosArrowBack onClick={move_left} />
<IoIosArrowForward onClick={move_right} />
</div>
</div>
<ScrollContainer className="melc-content">
{data.map((item) => (
<div key={item.id}>
{item.isActive && (
<div className="melc-content-item">
{item.isActive &&
item.tab_content.map((item) => (
<Link to={`/dashboard/azmoon_list/enter_exam/${item.id}`}
key={item.id}
className="melc-content-i-item"
onMouseEnter={() =>
item_active_hover(item.id, item.sub_id)
}
onMouseLeave={() =>
item_deactive_hover(item.id, item.sub_id)
}
>
<img
className="melc-c-i-i-bg"
src={item.img}
alt="azmoon-img"
/>
{item.exam_started && (
<div className="melc-c-i-i-exam-sit">
<GoPrimitiveDot className="melc-c-i-i-exam-sit-icon" />
<div className="melc-c-i-i-exam-sit-text">
در حال برگزاری
</div>
</div>
)}
<div
style={underCoverStyleList[item.tabType-1]}
className="melc-c-i-i-under-cover"
></div>
<div
style={coverStyleList[item.tabType-1]}
className="melc-c-i-i-cover"
></div>
<div className="melc-c-i-item-info">
<div className="melc-c-i-i-info-title">
<img src={calendar_icon} alt="calendar-icon" />
{item.name}
</div>
<div className="melc-c-i-i-info-line"></div>
<div className="melc-c-i-i-info-date-time">
<div className="melc-ciiidt-date-container">
<BsClock className="melc-clock-icon" />
<div className="melc-ciiidt-date">
{moment(item.date, 'YYYY/MM/DD').format('jYYYY/jM/jD')}
</div>
</div>
<div className="melc-ciiidt-time">
ساعت {item.time}
</div>
</div>
<div className="melc-c-i-i-info-descriptin">
{item.descripton}
</div>
</div>
</Link>
))}
<Link
to="/dashboard/azmoon_list"
className="melc-content-item-more"
>
مشاهده بیشتر
</Link>
</div>
)}
</div>
))}
</ScrollContainer>
</div>
</div>
);
};
export default MyExamList;

@ -0,0 +1,470 @@
export const state = [
{
id:1,
id2:1,
img:'https://www.timeforkids.com/wp-content/uploads/2021/01/K1_CMS_0129_1.jpg',
name:"آزمون نجوم نظری",
// price:458.200,
masterPrice:450200,
price:405000,
badge:"10%",
date:"2021-10-26T12:00:00.180Z",
endDate:"2021-10-27T12:00:00.180Z",
level:"کارشناسی ارشد",
type:1, //c فردی ، گروهی
time_type:"future", //c دسته بندی زمانی آزمونها برای قرار دادن در داشبرد :"future","live","thisWeek"
filter: "collegiate", //c فیلتر کردن آزمون ها با کلیدهای فیلتر در فروشگاه و
count:100,
exam_started:true,
capacity:120,
exam_filter:"collegiate", //حذف شود
negattiveMode:true, //c نمره منفی
types:"تشریحی و تستی", //c نوع سولات
guideFileId:"#",
text:"از فصل دوم تا چهارم", //c توضیحی کوتاه که در صفحه آزمون استفاده میشود
exam_timer:60, //مدت زمان آزمون بر حسب دقیقه
// creator:{ //اطلاعات ایجاد کننده آزمون
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد", //c اطلاعاتی که در صفحه خرید آزمون استفاده میشود.
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
], //اطلاعاتی دیگری که در صفحه خرید آزمون استفاده میشود
// video:video1, //ویدیویی درباره آزمون که در صفحه خرید استفاده میشود
// video_cover:video_cover1,
files:[ //فایل های مورد نیاز برای آمادگی آزمون که در صفحه خرید استفاده میشود
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
},
{
id:2,
id2:2,
img:'https://img9.irna.ir/old/Image/1397/13970106/82871315/N82871315-72258180.jpg',
name:"آزمون جغرافیای جهان",
// price:458.200,
masterPrice:340000,
price:306000,
badge:"10%",
date:"2021-10-18T12:00:00.180Z",
endDate:"2021-10-19T12:00:00.180Z",
level:"پایه دهم",
type:2,
time_type:"thisWeek",
filter: "discounted",
exam_filter:"live",
count:100,
capacity:120,
negattiveMode:true,
types:"تشریحی و تستی",
guideFileId:"#",
text:"از فصل سوم تا پنجم",
exam_timer:60,
// creator:{
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
],
// video:video1,
// video_cover:video_cover1,
files:[
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
},
{
id:3,
id2:3,
img:'https://images.ctfassets.net/cnu0m8re1exe/7bvBF6E4WXVLLIsH88lXcC/5a3b7483a82fb30248e7d1c7856be6ec/20-things-color.jpg',
name:"آزمون رنگشناسی",
// price:458.200,
masterPrice:100000,
price:90000,
badge:"10%",
date:"2021-10-15T12:00:00.180Z",
endDate:"2021-10-17T12:00:00.180Z",
level:"کارشناسی",
type:1,
time_type:"future",
filter: "discounted",
count:100,
capacity:120,
exam_filter:"live",
negattiveMode:true,
types:"تشریحی و تستی",
guideFileId:"#",
text:"از فصل سوم تا پنجم",
exam_timer:60,
// creator:{
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
],
// video:video1,
// video_cover:video_cover1,
files:[
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
},
{
id:4,
id2:4,
img:'https://www.verywellmind.com/thmb/0-wI_ZBZiPEJVTvTPz2U7laZp1Y=/1333x1000/smart/filters:no_upscale()/depression-counseling-4769574_v4-a665f8461b0241079601241700d36487.png',
name:"آزمون روان درمانی اگزیستانسیال",
// price:458.200,
masterPrice:200000,
price:180000,
discount:"10%",
date:"2021-10-25T12:00:00.180Z",
endDate:"2021-10-26T12:00:00.180Z",
level:"پایه 1 الی 12",
type:1,
time_type:"live",
filter: "none",
count:100,
capacity:120,
exam_filter:"live",
negattiveMode:false,
types:"تشریحی و تستی",
guideFileId:"#",
text:"از فصل سوم تا پنجم",
exam_timer:60,
// creator:{
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
],
// video:video1,
// video_cover:video_cover1,
files:[
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
},
{
id:5,
id2:5,
img:'https://townsquare.media/site/295/files/2022/01/attachment-GNR-Slash.jpg',
name:"آزمون موسیقیشناسی",
// price:458.200,
masterPrice:200000,
price:"",
badge:"",
date:"2021-10-26T12:00:00.180Z",
endDate:"2021-10-27T12:00:00.180Z",
level:"پایه 5 الی 12",
time_type:"live",
type:1,
filter: "none",
count:100,
capacity:120,
exam_filter:"live",
negattiveMode:true,
types:"تشریحی و تستی",
guideFileId:"#",
text:"از فصل سوم تا پنجم",
exam_timer:60,
user_num:100,
// creator:{
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
],
// video:video1,
// video_cover:video_cover1,
files:[
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
},
{
id:6,
id2:6,
img:'https://leverageedu.com/blog/wp-content/uploads/2020/04/basic-chemistry.png',
name:"آزمون شیمی یازدهم",
// price:458.200,
masterPrice:200000,
price:180000,
badge:"10%",
date:"2021-10-28T12:00:00.180Z",
endDate:"2021-10-28T12:00:00.180Z",
level:"پایه 11",
type:1,
time_type:"thisWeek",
filter: "none",
count:100,
capacity:120,
exam_filter:"collegiate",
negattiveMode:true,
types:"تشریحی و تستی",
guideFileId:"#",
guide_file_link:"#",
text:"از فصل سوم تا پنجم",
exam_timer:60,
// creator:{
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
],
// video:video1,
// video_cover:video_cover1,
files:[
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
},
{
id:7,
id2:7,
img:'https://parade.com/wp-content/uploads/2018/10/GordonRamsay_KitchenMaster-FTR.jpg',
name:"آزمون آشپزی ملل",
// price:458.200,
masterPrice:200000,
price:"",
discount:"",
date:"2021-11-05T12:00:00.180Z",
endDate:"2021-11-06T12:00:00.180Z",
level:"عمومی",
type:2,
time_type:"thisWeek",
filter: "none",
count:100,
capacity:120,
exam_filter:"collegiate",
negattiveMode:true,
types:"تشریحی و تستی",
guideFileId:"#",
text:"از فصل سوم تا پنجم",
exam_timer:60,
// creator:{
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
],
// video:video1,
// video_cover:video_cover1,
files:[
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
},
{
id:8,
id2:8,
img:'https://img9.irna.ir/old/Image/1397/13970106/82871315/N82871315-72258180.jpg',
name:"آزمون گسسته",
// price:458.200,
masterPrice:200000,
price:0,
badge:"100%",
date:"2021-11-17T12:00:00.180Z",
endDate:"2021-11-18T12:00:00.180Z",
level:"پایه 10",
type:1,
time_type:"future",
filter: "free",
count:100,
capacity:120,
exam_filter:"collegiate",
negattiveMode:true,
types:"تشریحی و تستی",
guideFileId:"#",
text:"از فصل سوم تا پنجم",
exam_timer:60,
user_num:100,
// creator:{
// avatar:avatar1,
// name:"موسسه فرهنگی مصباح نور"
// },
descripton:"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
time:"21:30",
html:[
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد",
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد"
],
// video:video1,
// video_cover:video_cover1,
files:[
[
{
id:1,
text:"دریافت فایل پی دی اف درسهای بخش چهارم و پنجم",
path:"#"
}
],
[
{
id:1,
text:"دریافت فایل ویدیویی درسهای بخش چهارم و پنجم",
path:"#"
},
{
id:2,
text:"دریافت نرم افزار پخش ویدیو",
path:"#"
}
]
]
}
]

@ -0,0 +1,22 @@
import React from "react";
const img = 'https://img9.irna.ir/old/Image/1397/13970106/82871315/N82871315-72258180.jpg';
const ExamCarouselItem = ({exam}) => {
return(
<div className="flex flex-col justify-between rounded-xl h-full mx-2" style={{width:'250px',minHeight: '210px', background : `url(${img})`, backgroundPosition: 'center', backgroundSize: 'cover'}}>
<div className="w-full flex justify-end h-12 items-center px-3">
{
exam?.inAction && <div className="flex items-center p-1 rounded-md bg-white">
<p className="rounded-full bg-red52 ml-1" style={{width: '10px', height: '10px'}}></p>
<p className="text-red52 font-bold" style={{fontSize: '8px'}}>در حال برگزاری</p>
</div>
}
</div>
</div>
);
};
export default ExamCarouselItem;

@ -0,0 +1,202 @@
.exam-result{
width: 100%;
height: 450px;
direction: rtl;
/* box-shadow: 0 0 21px -5px #ADADAD; */
border: 1px solid #E0E0E0;
padding-top: 15px;
position: relative;
}
.exam-result-title{
width: 90%;
margin: 0 auto;
margin-top: 5px;
font-size: 19px;
/* font-family: IRANSansBold; */
font-family: IRANSansX-Bold;
color: #2E81E8;
}
.exam-result-table{
width: 90%;
height: 78%;
margin: 0 auto;
margin-top: 18px;
/* overflow-y: scroll; */
}
/* .exam-result-table::-webkit-scrollbar{
width: 0px;
}
.exam-result:hover .exam-result-table::-webkit-scrollbar{
width: 2px !important;
}
.exam-result-table::-webkit-scrollbar-thumb{
background-color: rgb(129, 128, 128);
}
.exam-result-table::-webkit-scrollbar-track{
background-color: rgb(197, 196, 196);
} */
.exam-result-table-titles{
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid rgba(224, 224, 224,0.38);
}
.ertt-item{
text-align: center;
font-size: 11px;
/* font-family: IRANSans; */
font-family: IRANSansX-Regular;
color: #A2B4CB;
}
.ertt-item:nth-child(1){
width: 42%;
}
.ertt-item:nth-child(2){
width: 33%
}
.ertt-item:nth-child(3){
width: 25%;
}
.exam-result-table-data{
width: 100%;
height: 97%;
overflow-y: scroll;
}
.exam-result-table-data::-webkit-scrollbar{
width: 0px;
}
.exam-result:hover .exam-result-table-data::-webkit-scrollbar{
width: 2px !important;
}
.exam-result-table-data::-webkit-scrollbar-thumb{
background-color: rgb(129, 128, 128);
}
.exam-result-table-data::-webkit-scrollbar-track{
background-color: rgb(214, 213, 213);
}
.ertd-item{
width: 100%;
}
.ertd-item-name{
font-size: 11px;
color: #A5B6CD;
/* font-family: IRANSans; */
font-family: IRANSansX-Regular;
margin-top: 7px;
}
.ertdi-item{
width: 100%;
/* height: 31px; */
height: 30px;
display: flex;
padding: 3px 4px;
align-items: center;
justify-content: center;
margin-top: 7px;
/* background-color: #F5FFF6; */
}
.ertdi-item-name{
width: 42%;
height: 100%;
/* display: flex; */
align-items: center;
/* justify-content: center; */
/* text-align: center; */
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis !important;
/* color: #2FB100; */
font-size: 12px;
/* font-family: IRANSans; */
font-family: IRANSansX-Regular;
}
.ertdi-item-date{
width: 33%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
/* color: #2FB100; */
font-size: 12px;
/* font-family: IRANSans; */
/* font-family: IRANSansX-Regular; */
font-family: IRANSansXFaNum-Regular;
}
.ertdi-item-result{
width: 25%;
height: 100%;
/* display: flex;
align-items: center;
justify-content: center; */
/* color: #2FB100; */
text-align: center;
font-size: 12px;
/* font-family: IRANSans; */
font-family: IRANSansX-Regular;
}
.ertd-item-line{
width: 100%;
height: 1px;
background-color: #E0E0E0;
margin-top: 15px;
opacity: 29%;
}
.exam-result-footer{
width: 90%;
margin: 0 auto;
direction: ltr;
margin-top: 15px;
}
.erf-btn{
display: flex;
width: 100%;
align-items: center;
font-size: 11px;
/* font-family: IRANSans; */
font-family: IRANSansX-Regular;
color: #ACBCD1;
margin-left: -3px;
box-sizing: content-box !important;
padding: 5px 0;
cursor: pointer;
/* left: ; */
}
.erf-btn-arrow-icon{
font-size: 18px;
}
.erf-btn:hover{
color: #2E81E8;
}
/* --------responsive-setting---------------------------------------------------------- */
@media screen and (max-width: 1508px){
.ertdi-item *{
font-size: 11px;
}
}

@ -0,0 +1,163 @@
import "./index.css";
import { VscChevronLeft } from "react-icons/vsc";
let ert_data = [
{
id: 1,
name: "نتایج نهایی",
line: true,
exams: [
{
id: 1,
name: "آزمون راهنمای و رانندگی ",
date: "1400/03/29",
result: "قبول",
isPassed: 1,
},
{
id: 2,
name: "آزمون راهنمای و رانندگی ",
date: "1400/03/29",
result: "قبول",
isPassed: 1,
},
{
id: 3,
name: "آزمون جامعه شناسی تحلیلی",
date: "1400/03/29",
result: "رد",
isPassed: 2,
},
{
id: 4,
name: "آزمون راهنمای و رانندگی ",
date: "1400/03/29",
result: "قبول",
isPassed: 1,
},
],
},
{
id: 2,
name: "نتایج موقت",
line: true,
exams: [
{
id: 1,
name: "آزمون راهنمای و رانندگی ",
date: "1400/03/29",
result: "قبول",
isPassed: 1,
},
{
id: 2,
name: "آزمون راهنمای و رانندگی ",
date: "1400/03/29",
result: "قبول",
isPassed: 1,
},
],
},
{
id: 3,
name: "نتایج قرعهکشی",
line: false,
exams: [
{
id: 1,
name: "آزمون راهنمای و رانندگی ",
date: "1400/03/29",
result: "در حال برگزاری",
isPassed: 3,
},
{
id: 2,
name: "آزمون راهنمای و رانندگی ",
date: "1400/03/29",
result: "در حال برگزاری",
isPassed: 3,
},
],
},
];
const ExamResults = () => {
return (
<div className="exam-result bg-white rounded-lg">
<div className="w-full text-red52 text-right px-4 font-bold">نتایج آزمونها</div>
<div className="exam-result-table">
<div className="exam-result-table-titles">
<div className="ertt-item">موضوع آزمون</div>
<div className="ertt-item">تاریخ برگزاری</div>
<div className="ertt-item">نتیجه</div>
</div>
<div className="exam-result-table-data">
{ert_data.map((item) => (
<div key={item.id} className="ertd-item">
<div className="ertd-item-name w-full text-right">{item.name}</div>
{item.exams.map((item) => (
<div
style={
item.isPassed === 1
? { backgroundColor: "#F5FFF6" }
: item.isPassed === 2
? { backgroundColor: "#FFF9F5" }
: { backgroundColor: "#EEFCFF" }
}
key={item.id}
className="ertdi-item"
>
<div
style={
item.isPassed === 1
? { color: "#2FB100" }
: item.isPassed === 2
? { color: "#C44000" }
: { color: "#35656F" }
}
className="ertdi-item-name"
>
{item.name}
</div>
<div
style={
item.isPassed === 1
? { color: "#2FB100" }
: item.isPassed === 2
? { color: "#C44000" }
: { color: "#35656F" }
}
className="ertdi-item-date"
>
{item.date}
</div>
<div
style={
item.isPassed === 1
? { color: "#2FB100" }
: item.isPassed === 2
? { color: "#C44000" }
: { color: "#35656F" }
}
className="ertdi-item-result"
>
{item.result}
</div>
</div>
))}
{item.line && <div className="ertd-item-line"></div>}
</div>
))}
</div>
</div>
<div className="exam-result-footer">
<div className="erf-btn">
<VscChevronLeft className="erf-btn-arrow-icon" />
مشاهده لیست نتایج
</div>
</div>
</div>
);
};
export default ExamResults;

@ -54,7 +54,7 @@ const Header = ({
کوروش زراندوز
</div>
<div className="header-profile-text-container-role text-xs">
صندوقدار
پایه ششم
</div>
</div>
</div>

@ -134,7 +134,7 @@ const Nav = ({
{/* ------------ */}
<div className="nav-menu-container w-full h-3/4 flex-col items-center absolute z-30 right-0">
<Link
to="/dashboard"
to="/"
className="nav-menu-container-item w-full h-1/6 flex flex-col items-center justify-center hover:bg-color2_5 cursor-pointer"
onClick={() => chaneNav(1)}
>

@ -1,4 +1,6 @@
import { useState } from "react";
import ExamCarousel from "../../components/exam/Carousel";
import ExamResults from "../../components/exam/resault";
import UserFullInfo from "../dashboard2/UserFullInfo";
import CashOffice from "./CashOffice";
import LastActivity from "./LastActivity";
@ -6,6 +8,7 @@ import Monitoring from "./Monitoring";
import People from "./People";
import Register from "./Register";
import Urgent from "./Urgent";
import SimpleCalendar from '../../components/Calendar'
const Dashboard = ({
@ -29,22 +32,30 @@ const Dashboard = ({
setSelectId(null);
};
return (
<div className="Dashboard w-screen h-[91.5%] absolute top-[8.5%] z-0 left-0 bg-color5 flex">
<div className="dashboard-left-part w-[30.4%] h-full py-3 px-4">
<People
<div className="Dashboard w-screen h-[91.5%] overflow-x-hidden absolute top-[8.5%] z-0 left-0 bg-color5 flex">
<div className="dashboard-left-part w-[25.4%] h-full flex flex-col items-center py-3 px-4">
{/* <People
showUserFullInfo={showUserFullInfo}
openRegister={openRegister}
hideUserFullInfo={hideUserFullInfo}
SelectId={SelectId}
setSelectId={setSelectId}
/>
/> */}
<div className="w-full mb-4">
<SimpleCalendar />
</div>
<ExamResults />
</div>
<div className="dashboard-right-part w-[63.1%] h-full py-3 pr-4 relative">
<div className="dashboard-right-part w-[68.1%] h-full py-3 pr-4 relative">
<ExamCarousel />
<div className="dashboard-right-part-row2 w-full mt-4 flex items-start justify-between flex-row-reverse">
<LastActivity />
<div className="dashboard-right-part-row2 w-full h-[42%] mt-4 flex items-start justify-between flex-row-reverse">
<CashOffice />
<Monitoring />
{ActiveUserFullInfo && (
{/* {ActiveUserFullInfo && (
<div className="dashboard-blur-box w-full h-full absolute top-0 left-0 backdrop-blur z-40">
<UserFullInfo
buyBtn={true}
@ -53,7 +64,7 @@ const Dashboard = ({
deselectUser={deselectUser}
/>
</div>
)}
)} */}
</div>
</div>
{register && <Register closeRegister={closeRegister} />}

@ -7,7 +7,7 @@ const LastActivity = () => {
{
id: 1,
date: "1400/11/11",
name: "پژمان نوروزی",
name: "آزمون آنلاین درس علوم تجربی",
nationalId: "0013578098",
activity: "شارژ حساب",
amount: 100000,
@ -16,7 +16,7 @@ const LastActivity = () => {
{
id: 2,
date: "1400/11/11",
name: "ایلیا رئیسی",
name: "آزمون آنلاین درس علوم اجتماعی",
nationalId: "0016577044",
activity: "شارژ حساب",
amount: 90000,
@ -25,7 +25,7 @@ const LastActivity = () => {
{
id: 3,
date: "1400/11/11",
name: "غزل رحیمی",
name: "آزمون آنلاین خیاطی (ریز دوزی)",
nationalId: "0093578123",
activity: "شارژ حساب",
amount: 80000,
@ -34,7 +34,7 @@ const LastActivity = () => {
{
id: 4,
date: "1400/11/11",
name: ریا عظیمی",
name: زمون حضوری آداب معاشرت",
nationalId: "0061234098",
activity: "شارژ حساب",
amount: 100000,
@ -43,7 +43,7 @@ const LastActivity = () => {
{
id: 5,
date: "1400/11/10",
name: "علی رجبی",
name: "آزمون آنلاین انضباط دوم دبیرستان",
nationalId: "0213577799",
activity: "شارژ حساب",
amount: 70000,
@ -52,7 +52,7 @@ const LastActivity = () => {
{
id: 6,
date: "1400/11/10",
name: "سارا دانش",
name: "آزمون حضوری دوره ی چگونه یوتیوبر شویم",
nationalId: "0350077708",
activity: "شارژ حساب",
amount: 70000,
@ -61,7 +61,7 @@ const LastActivity = () => {
{
id: 7,
date: "1400/11/10",
name: "امیررضا نیکوسرشت دانشپژوه تستی",
name: "آزمون آنلاین fl studio",
nationalId: "0350089964",
activity: "استرداد وجه",
amount: 70000,
@ -72,89 +72,68 @@ const LastActivity = () => {
<div className="LastActivity w-full h-[55%] max-h-[55%] rounded-lg bg-white p-4">
<div className="LastActivity-row1 w-full flex items-center justify-between flex-row-reverse mb-2">
<div className="LastActivity-title-box flex flex-row-reverse items-center">
<img
src={titleIcon}
alt="titleIcon"
className="LastActivity-title-icon"
/>
<div className="LastActivity-title-box-text mr-2 text-color2">
آخرین فعالیتها
<div className="LastActivity-title-box-text mr-2 p-2 font-bold text-color2">
لیست آزمون های من
</div>
</div>
<Link
{/* <Link
to="/accounting"
className="LastActivity-more-btn p-2 border border-color7 rounded w-fit text-sm text-color2 cursor-pointer hover:bg-color2 hover:text-white"
>
مشاهده بیشتر
</Link>
</Link> */}
</div>
<div className="LastActivity-row2 w-full py-2 border-t border-color1 flex items-center justify-between flex-row-reverse">
<div className="LastActivity-row2-item text-color2 text-sm w-1/12">
ردیف
</div>
<div className="LastActivity-row2-item text-color2 text-sm w-2/12">
تاریخ
</div>
<div className="LastActivity-row2-item text-color2 text-sm w-2/12">
نام و نام خانوادگی
</div>
<div className="LastActivity-row2-item text-color2 text-sm w-2/12">
کد ملی
<div className="LastActivity-row2 w-full py-2 border-color1 flex items-center text-right justify-between flex-row-reverse">
<div className="LastActivity-row2-item text-color2 text-sm w-3/12">
عنوان
</div>
<div className="LastActivity-row2-item text-color2 text-sm w-2/12">
نوع فعالیت
<div className="LastActivity-row2-item text-color2 text-center text-sm w-2/12">
تاریخ ثبت نام
</div>
<div className="LastActivity-row2-item text-color2 text-sm w-2/12">
مبلغ
<div className="LastActivity-row2-item text-color2 text-center text-sm w-2/12">
مبلغ پرداختی
</div>
<div className="LastActivity-row2-item text-color2 text-sm w-1/12">
نتیجه
<div className="LastActivity-row2-item text-color2 text-center text-sm w-2/12">
دریافت قرارداد
</div>
</div>
{data.map((item, index) => (
<div
key={item.id}
className="LastActivity-item w-full py-2 border-t border-color1 flex items-center justify-between flex-row-reverse hover:bg-color12"
className="LastActivity-item w-full py-2 border-t border-color1 text-red26 flex items-center cursor-pointer justify-between flex-row-reverse hover:bg-red82OP"
>
<div className="LastActivity-item-index text-sm text-color10 w-1/12">
{index + 1}
</div>
<div
className="LastActivity-item-name text-sm text-color10 w-2/12"
className="LastActivity-item-name text-sm text-right text-ellipsis whitespace-nowrap overflow-hidden rtl w-3/12"
style={{ fontFamily: "IRANSansXFaNum-Regular" }}
>
{item.date}
</div>
<div
className="LastActivity-item-name text-sm text-color10 w-2/12 text-ellipsis whitespace-nowrap overflow-hidden"
style={{ direction: "rtl" }}
>
{item.name}
</div>
<div
className="LastActivity-item-name text-sm text-color10 w-2/12"
style={{ fontFamily: "IRANSansXFaNum-Regular" }}
className="LastActivity-item-name text-sm w-2/12 text-ellipsis whitespace-nowrap overflow-hidden"
style={{ direction: "rtl", fontFamily: "IRANSansXFaNum-Regular" }}
>
{item.nationalId}
{item.date}
</div>
<div
className="LastActivity-item-name text-sm text-color10 w-2/12 text-ellipsis whitespace-nowrap overflow-hidden"
style={{ direction: "rtl" }}
className="LastActivity-item-name text-sm w-2/12 text-ellipsis whitespace-nowrap overflow-hidden"
style={{ direction: "rtl", fontFamily: "IRANSansXFaNum-Regular" }}
>
{item.activity}
{item.amount} ریال
</div>
<div
className="LastActivity-item-name text-sm text-color10 w-2/12 text-ellipsis whitespace-nowrap overflow-hidden"
className="LastActivity-item-name text-center w-2/12 text-ellipsis whitespace-nowrap overflow-hidden"
style={{ direction: "rtl", fontFamily: "IRANSansXFaNum-Regular" }}
>
{item.amount} تومان
</div>
<div
className="LastActivity-item-name text-sm text-color10 w-1/12"
style={item.situation ? { color: "#00AE41" } : { color: "#CB1F1F" }}
>
{item.situation ? "موفق" : "ناموفق"}
{
item.situation ? <p className="text-red26 font-bold ">آماده قابل دریافت</p> : <p className="text-red26 ">غیر قابل دریافت</p>
}
</div>
</div>
))}
</div>

@ -95,7 +95,7 @@ const Messages=()=>{
<div className="Messages-main-box w-3/4 h-full relative">
<div className="Messages-main-box-header w-full h-[8%] bg-white flex items-center justify-between px-6 flex-row-reverse">
<div className="Messages-main-box-header-name">امیر ناظمی</div>
<BsTelephone className="text-2xl" />
{/* <BsTelephone className="text-2xl" /> */}
</div>
<div className="Messages-main-box-chat-box w-full h-[84%] flex items-ceter justify-between px-4"></div>
<div className="Messages-main-box-footer w-full py-2 bg-white flex items-center justify-between flex-row-reverse absolute bottom-0 ">
@ -110,7 +110,7 @@ const Messages=()=>{
<img
src={sendIcon}
alt="sendIcon"
className="absolute w-8 bottom-[25%] left-4"
className="absolute w-8 bottom-[25%] left-24"
/>
</div>
</div>

@ -5436,6 +5436,11 @@
"filelist" "^1.0.1"
"minimatch" "^3.0.4"
"jalaali-js@^1.2.3":
"integrity" "sha512-irl0pXL59Xl0Oz6jyOiJed/NxrVeS6fSx6a8atQOH/LsPWPZwBCxwe5XVEIqjnwt69FRxvnCCwQn5dTMxwbazQ=="
"resolved" "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.3.tgz"
"version" "1.2.3"
"jalali-moment@^3.3.10":
"integrity" "sha512-tdSaRs9cjWjOIaWhcsGFZMhZQhfgok5J0TwqFpBIZPudZxxa6yjUPoLCOwuvbAtRpiZn7k/mvazAJh+vEN5suw=="
"resolved" "https://registry.npmjs.org/jalali-moment/-/jalali-moment-3.3.11.tgz"

Loading…
Cancel
Save