feat: add edit modal for expert's schedule
This commit is contained in:
parent
cda91b9ea9
commit
b52096b3bc
|
@ -38,10 +38,6 @@ export default function ExpertProfilePage({ params: { locale } }: { params: { lo
|
||||||
getPayData(locale, jwt)
|
getPayData(locale, jwt)
|
||||||
])
|
])
|
||||||
.then(([profile, person, education, tags, practice, schedule, payData]) => {
|
.then(([profile, person, education, tags, practice, schedule, payData]) => {
|
||||||
console.log('profile', profile);
|
|
||||||
console.log('person', person);
|
|
||||||
console.log('education', education);
|
|
||||||
console.log('schedule', schedule);
|
|
||||||
setIsFull(profile.fillProgress === 'full');
|
setIsFull(profile.fillProgress === 'full');
|
||||||
setData({
|
setData({
|
||||||
person,
|
person,
|
||||||
|
@ -63,14 +59,12 @@ export default function ExpertProfilePage({ params: { locale } }: { params: { lo
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Loader isLoading={loading}>
|
<Loader isLoading={loading}>
|
||||||
{data && (
|
<ExpertProfile
|
||||||
<ExpertProfile
|
isFull={isFull}
|
||||||
isFull={isFull}
|
locale={locale}
|
||||||
locale={locale}
|
data={data}
|
||||||
data={data}
|
updateData={setData}
|
||||||
updateData={setData}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Loader>
|
</Loader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
ExpertInformation,
|
ExpertInformation,
|
||||||
ExpertPractice
|
ExpertPractice
|
||||||
} from '../../../../components/Experts/ExpertDetails';
|
} from '../../../../components/Experts/ExpertDetails';
|
||||||
import { Details } from '../../../../types/experts';
|
import { Details } from '../../../../types/education';
|
||||||
import { BackButton } from '../../../../components/view/BackButton';
|
import { BackButton } from '../../../../components/view/BackButton';
|
||||||
import { i18nText } from '../../../../i18nKeys';
|
import { i18nText } from '../../../../i18nKeys';
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ export default async function ExpertItem({ params: { expertId = '', locale } }:
|
||||||
if (!expertId) notFound();
|
if (!expertId) notFound();
|
||||||
|
|
||||||
const expert = await getExpertById(expertId, locale);
|
const expert = await getExpertById(expertId, locale);
|
||||||
console.log(expert);
|
|
||||||
|
|
||||||
const getAssociationLevel = (accLevelId?: number) => {
|
const getAssociationLevel = (accLevelId?: number) => {
|
||||||
if (accLevelId) {
|
if (accLevelId) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {fetchBlogPosts} from "../lib/contentful/blogPosts";
|
import { fetchBlogPosts } from '../lib/contentful/blogPosts';
|
||||||
|
|
||||||
export default async function sitemap() {
|
export default async function sitemap() {
|
||||||
const paths = [
|
const paths = [
|
||||||
|
|
|
@ -145,7 +145,13 @@ export const ExpertProfile = ({ locale, data, updateData, isFull }: ExpertProfil
|
||||||
updateExpert={updateExpert}
|
updateExpert={updateExpert}
|
||||||
/>
|
/>
|
||||||
</Loader>
|
</Loader>
|
||||||
<ExpertSchedule locale={locale} data={data?.schedule} />
|
<Loader isLoading={loading.includes('schedule')}>
|
||||||
|
<ExpertSchedule
|
||||||
|
locale={locale}
|
||||||
|
data={data?.schedule}
|
||||||
|
updateExpert={updateExpert}
|
||||||
|
/>
|
||||||
|
</Loader>
|
||||||
<Loader isLoading={loading.includes('education')}>
|
<Loader isLoading={loading.includes('education')}>
|
||||||
<ExpertEducation
|
<ExpertEducation
|
||||||
locale={locale}
|
locale={locale}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import {useState} from "react";
|
import { useState } from 'react';
|
||||||
import {Tag} from "antd";
|
import { Tag } from 'antd';
|
||||||
import {EditOutlined} from "@ant-design/icons";
|
import { EditOutlined } from '@ant-design/icons';
|
||||||
import {LinkButton} from "../../view/LinkButton";
|
import { ExpertData, ProfileData } from '../../../types/profile';
|
||||||
import {ExpertData, ProfileData} from "../../../types/profile";
|
import { i18nText } from '../../../i18nKeys';
|
||||||
import {i18nText} from "../../../i18nKeys/index";
|
import { PracticeDTO } from '../../../types/practice';
|
||||||
import {PracticeDTO} from "../../../types/practice";
|
import { LinkButton } from '../../view/LinkButton';
|
||||||
import {ExpertPractice} from "../../Experts/ExpertDetails";
|
import { ExpertPractice } from '../../Experts/ExpertDetails';
|
||||||
import {EditExpertAboutModal} from "../../Modals/EditExpertAboutModal";
|
import { EditExpertAboutModal } from '../../Modals/EditExpertAboutModal';
|
||||||
|
|
||||||
type ExpertAboutProps = {
|
type ExpertAboutProps = {
|
||||||
locale: string;
|
locale: string;
|
||||||
|
|
|
@ -1,48 +1,56 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Tag } from 'antd';
|
||||||
import { EditOutlined } from '@ant-design/icons';
|
import { EditOutlined } from '@ant-design/icons';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { ScheduleDTO } from '../../../types/schedule';
|
import { ScheduleDTO } from '../../../types/schedule';
|
||||||
import { i18nText } from '../../../i18nKeys';
|
import { i18nText } from '../../../i18nKeys';
|
||||||
|
import { getCurrentTime, getTimeString } from '../../../utils/time';
|
||||||
|
import { ExpertData } from '../../../types/profile';
|
||||||
import { LinkButton } from '../../view/LinkButton';
|
import { LinkButton } from '../../view/LinkButton';
|
||||||
import {useState} from "react";
|
import { EditExpertScheduleModal } from '../../Modals/EditExpertScheduleModal';
|
||||||
import {Tag} from "antd";
|
|
||||||
import {getCurrentTime} from "../../../utils/time";
|
|
||||||
|
|
||||||
type ExpertScheduleProps = {
|
type ExpertScheduleProps = {
|
||||||
locale: string;
|
locale: string;
|
||||||
data?: ScheduleDTO;
|
data?: ScheduleDTO;
|
||||||
|
updateExpert: (key: keyof ExpertData) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ExpertSchedule = ({ locale, data }: ExpertScheduleProps) => {
|
export const ExpertSchedule = ({ locale, data, updateExpert }: ExpertScheduleProps) => {
|
||||||
const [showEdit, setShowEdit] = useState<boolean>(false);
|
const [showEdit, setShowEdit] = useState<boolean>(false);
|
||||||
// person51
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="coaching-section__wrap">
|
<div className="coaching-section__wrap">
|
||||||
<div className="coaching-section">
|
<div className="coaching-section">
|
||||||
<div className="coaching-section__title">
|
<div className="coaching-section__title">
|
||||||
<h2 className="title-h2">{i18nText('schedule', locale)}</h2>
|
<h2 className="title-h2">{i18nText('schedule', locale)}</h2>
|
||||||
{/*<LinkButton
|
<LinkButton
|
||||||
type="link"
|
type="link"
|
||||||
icon={<EditOutlined />}
|
icon={<EditOutlined />}
|
||||||
onClick={() => setShowEdit(true)}
|
onClick={() => setShowEdit(true)}
|
||||||
/>*/}
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="b-schedule-list">
|
<div className="b-schedule-list">
|
||||||
{data && data?.workingTimes?.map((date, index) => {
|
{data && data?.workingTimes?.map((date, index) => {
|
||||||
const { startDay, startTime, endDay, endTime } = getCurrentTime(date);
|
const { startDay, startTimeMin, endTimeMin } = getCurrentTime(date, dayjs().format('Z'));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={`date_${index}`}>
|
<div key={`date_${index}`}>
|
||||||
<Tag className="skills__list__item">{i18nText(startDay, locale)}</Tag>
|
<Tag className="skills__list__item">{i18nText(startDay, locale)}</Tag>
|
||||||
<div>{startTime}</div>
|
<div>{startTimeMin ? getTimeString(startTimeMin) : '00:00'}</div>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
{startDay !== endDay && <Tag className="skills__list__item">{i18nText(endDay, locale)}</Tag>}
|
<div>{endTimeMin ? getTimeString(endTimeMin) : '00:00'}</div>
|
||||||
<div>{endTime}</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<EditExpertScheduleModal
|
||||||
|
open={showEdit}
|
||||||
|
handleCancel={() => setShowEdit(false)}
|
||||||
|
locale={locale}
|
||||||
|
data={data}
|
||||||
|
refresh={() => updateExpert('schedule')}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { FC, useEffect, useState } from 'react';
|
||||||
|
import { Modal, Button, message } from 'antd';
|
||||||
|
import { CloseOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { i18nText } from '../../i18nKeys';
|
||||||
|
import { AUTH_TOKEN_KEY } from '../../constants/common';
|
||||||
|
import { UTC_LIST } from '../../constants/time';
|
||||||
|
import { MapWorkingTime, ScheduleDTO } from '../../types/schedule';
|
||||||
|
import {
|
||||||
|
WEEK_DAY,
|
||||||
|
formattedSchedule,
|
||||||
|
getNewTime,
|
||||||
|
getTimeZoneOffset,
|
||||||
|
getTimeString,
|
||||||
|
formattedTimeByOffset, formattedWorkList
|
||||||
|
} from '../../utils/time';
|
||||||
|
import { useLocalStorage } from '../../hooks/useLocalStorage';
|
||||||
|
import { setSchedule } from '../../actions/profile';
|
||||||
|
import { CustomSelect } from '../view/CustomSelect';
|
||||||
|
import { CustomTimePicker } from '../view/CustomTimePicker';
|
||||||
|
import { LinkButton } from '../view/LinkButton';
|
||||||
|
import { OutlinedButton } from '../view/OutlinedButton';
|
||||||
|
|
||||||
|
type EditExpertScheduleModalProps = {
|
||||||
|
open: boolean;
|
||||||
|
handleCancel: () => void;
|
||||||
|
locale: string;
|
||||||
|
data?: ScheduleDTO;
|
||||||
|
refresh: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_WORK: MapWorkingTime = { startDay: '' };
|
||||||
|
|
||||||
|
export const EditExpertScheduleModal: FC<EditExpertScheduleModalProps> = ({
|
||||||
|
open,
|
||||||
|
handleCancel,
|
||||||
|
locale,
|
||||||
|
data,
|
||||||
|
refresh,
|
||||||
|
}) => {
|
||||||
|
const defaultTimeZone = dayjs().format('Z');
|
||||||
|
const [jwt] = useLocalStorage(AUTH_TOKEN_KEY, '');
|
||||||
|
const [timeZone, setTimeZone] = useState<string>(defaultTimeZone);
|
||||||
|
const [workList, setWorkList] = useState<MapWorkingTime[]>([DEFAULT_WORK]);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open && data?.workingTimes && data.workingTimes.length > 0) {
|
||||||
|
setWorkList(formattedSchedule(data.workingTimes, timeZone));
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
const onSave = () => {
|
||||||
|
const workingTimes = formattedWorkList(workList, timeZone);
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
setSchedule(locale, jwt, { workingTimes })
|
||||||
|
.then(() => {
|
||||||
|
handleCancel();
|
||||||
|
refresh();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error('Не удалось сохранить расписание');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const addWorkingHours = () => {
|
||||||
|
setWorkList([
|
||||||
|
...workList,
|
||||||
|
DEFAULT_WORK
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteWorkingHours = (index: number) => {
|
||||||
|
setWorkList(workList.filter((work, i) => i !== index));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeWeekDay = (val: string, index: number) => {
|
||||||
|
setWorkList(workList.map((work, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
return {
|
||||||
|
...work,
|
||||||
|
startDay: val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return work;
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeTime = (time: string, index: number, start?: boolean) => {
|
||||||
|
setWorkList(workList.map((work, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
const timeMin = getNewTime(time);
|
||||||
|
let res;
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
res = {
|
||||||
|
startTimeMin: timeMin
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = {
|
||||||
|
endTimeMin: timeMin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...work,
|
||||||
|
...res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return work;
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeTimeZone = (newTimeZone: string) => {
|
||||||
|
const offset = getTimeZoneOffset(timeZone, newTimeZone);
|
||||||
|
setTimeZone(newTimeZone);
|
||||||
|
setWorkList(workList.map((work) => formattedTimeByOffset(work, offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
className="b-modal"
|
||||||
|
open={open}
|
||||||
|
title={undefined}
|
||||||
|
onOk={undefined}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
footer={false}
|
||||||
|
width={498}
|
||||||
|
closeIcon={<CloseOutlined style={{ fontSize: 20, color: '#000' }}/>}
|
||||||
|
>
|
||||||
|
<div className="b-modal__expert__content">
|
||||||
|
<div className="b-modal__expert__title">{i18nText('schedule', locale)}</div>
|
||||||
|
<div className="b-modal__expert__inner" style={{ paddingRight: 12 }}>
|
||||||
|
<div style={{ paddingRight: 0, paddingBottom: 1 }}>
|
||||||
|
<div className="schedule">
|
||||||
|
<div className="schedule__inner">
|
||||||
|
<div className="timezone">
|
||||||
|
<div className="timezone__title">{`${i18nText('yourTimezone', locale)}: ${defaultTimeZone}`}</div>
|
||||||
|
<div className="timezone__utc">
|
||||||
|
<CustomSelect
|
||||||
|
label="UTC"
|
||||||
|
value={timeZone}
|
||||||
|
options={UTC_LIST.map((value) => ({ value, label: value }))}
|
||||||
|
onChange={(val) => onChangeTimeZone(val)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3 className="title-h3">{i18nText('workTime', locale)}</h3>
|
||||||
|
<div className="schedule__wrap">
|
||||||
|
{workList.length === 1 ? workList.map(({ startDay, startTimeMin, endTimeMin }, index) => (
|
||||||
|
<div key={`day_${index}`} className="schedule-item__single">
|
||||||
|
<CustomSelect />
|
||||||
|
<CustomSelect label={i18nText('startAt', locale)} />
|
||||||
|
<CustomSelect label={i18nText('finishAt', locale)} />
|
||||||
|
</div>
|
||||||
|
)) : null}
|
||||||
|
{workList.length > 1 ? workList.map(({ startDay, startTimeMin, endTimeMin }, index) => (
|
||||||
|
<div key={`day_${index}`} className="schedule-item">
|
||||||
|
<CustomSelect
|
||||||
|
label={i18nText('day', locale)}
|
||||||
|
value={startDay || undefined}
|
||||||
|
options={WEEK_DAY.map((value) => ({ value, label: i18nText(value, locale) }))}
|
||||||
|
onChange={(val) => onChangeWeekDay(val, index)}
|
||||||
|
/>
|
||||||
|
<CustomTimePicker
|
||||||
|
label={i18nText('startAt', locale)}
|
||||||
|
value={startTimeMin ? dayjs(getTimeString(startTimeMin), 'HH:mm') : dayjs('00:00', 'HH:mm')}
|
||||||
|
onChange={(time, timeString) => onChangeTime(timeString, index, true)}
|
||||||
|
/>
|
||||||
|
<CustomTimePicker
|
||||||
|
label={i18nText('finishAt', locale)}
|
||||||
|
value={endTimeMin ? dayjs(getTimeString(endTimeMin), 'HH:mm') : dayjs('00:00', 'HH:mm')}
|
||||||
|
onChange={(time, timeString) => onChangeTime(timeString, index)}
|
||||||
|
/>
|
||||||
|
<LinkButton
|
||||||
|
type="link"
|
||||||
|
danger
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => deleteWorkingHours(index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)) : null}
|
||||||
|
</div>
|
||||||
|
<OutlinedButton
|
||||||
|
type="link"
|
||||||
|
onClick={addWorkingHours}
|
||||||
|
>
|
||||||
|
{i18nText('addWorkingHours', locale)}
|
||||||
|
</OutlinedButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="b-modal__expert__button">
|
||||||
|
<Button
|
||||||
|
className="card-detail__apply"
|
||||||
|
onClick={onSave}
|
||||||
|
loading={loading}
|
||||||
|
>
|
||||||
|
{i18nText('save', locale)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
|
@ -30,7 +30,9 @@ export const CustomMultiSelect = (props: any) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`b-multiselect-wrap ${isActiveLabel ? 'b-multiselect__active' : ''}`}>
|
<div className={`b-multiselect-wrap ${isActiveLabel ? 'b-multiselect__active' : ''}`}>
|
||||||
<div className="b-multiselect-label">{label}</div>
|
<div className="b-multiselect-label">
|
||||||
|
<span>{label}</span>
|
||||||
|
</div>
|
||||||
<Select
|
<Select
|
||||||
className="b-multiselect"
|
className="b-multiselect"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
|
|
|
@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react';
|
||||||
import { Select } from 'antd';
|
import { Select } from 'antd';
|
||||||
|
|
||||||
export const CustomSelect = (props: any) => {
|
export const CustomSelect = (props: any) => {
|
||||||
const { label, value, ...other } = props;
|
const { label, value, style, ...other } = props;
|
||||||
const [isActiveLabel, setIsActiveLabel] = useState<boolean>(false);
|
const [isActiveLabel, setIsActiveLabel] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -16,8 +16,10 @@ export const CustomSelect = (props: any) => {
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`b-select-wrap ${isActiveLabel ? 'b-select__active' : ''}`}>
|
<div className={`b-select-wrap ${isActiveLabel ? 'b-select__active' : ''}`} style={style}>
|
||||||
<div className="b-select-label">{label}</div>
|
<div className="b-select-label">
|
||||||
|
<span>{label}</span>
|
||||||
|
</div>
|
||||||
<Select
|
<Select
|
||||||
className="b-select"
|
className="b-select"
|
||||||
value={value}
|
value={value}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { TimePicker } from 'antd';
|
||||||
|
import { DownOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
export const CustomTimePicker = (props: any) => {
|
||||||
|
const { label, value, ...other } = props;
|
||||||
|
const [isActiveLabel, setIsActiveLabel] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (label) {
|
||||||
|
setIsActiveLabel(!!value);
|
||||||
|
} else {
|
||||||
|
setIsActiveLabel(false);
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
const onOpenChange = (open: boolean) => {
|
||||||
|
if (open) {
|
||||||
|
if (!isActiveLabel) setIsActiveLabel(true)
|
||||||
|
} else {
|
||||||
|
setIsActiveLabel(!!value)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`b-timepicker-wrap ${isActiveLabel ? 'b-timepicker__active' : ''}`}>
|
||||||
|
<div className="b-timepicker-label">
|
||||||
|
<span>{label}</span>
|
||||||
|
</div>
|
||||||
|
<TimePicker
|
||||||
|
className="b-timepicker"
|
||||||
|
format="HH:mm"
|
||||||
|
minuteStep={15}
|
||||||
|
value={value}
|
||||||
|
showNow={false}
|
||||||
|
onOpenChange={onOpenChange}
|
||||||
|
needConfirm={false}
|
||||||
|
placeholder=""
|
||||||
|
variant="filled"
|
||||||
|
allowClear={false}
|
||||||
|
suffixIcon={<DownOutlined style={{ color: '#2c7873', fontSize: 12 }} />}
|
||||||
|
{...other}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,37 @@
|
||||||
|
export const UTC_LIST = [
|
||||||
|
'-12:00',
|
||||||
|
'-11:00',
|
||||||
|
'-10:00',
|
||||||
|
'-09:30',
|
||||||
|
'-09:00',
|
||||||
|
'-08:00',
|
||||||
|
'-07:00',
|
||||||
|
'-06:00',
|
||||||
|
'-05:00',
|
||||||
|
'-04:00',
|
||||||
|
'-03:30',
|
||||||
|
'-03:00',
|
||||||
|
'-02:00',
|
||||||
|
'-01:00',
|
||||||
|
'+00:00',
|
||||||
|
'+01:00',
|
||||||
|
'+02:00',
|
||||||
|
'+03:00',
|
||||||
|
'+03:30',
|
||||||
|
'+04:00',
|
||||||
|
'+04:30',
|
||||||
|
'+05:00',
|
||||||
|
'+05:30',
|
||||||
|
'+06:00',
|
||||||
|
'+06:30',
|
||||||
|
'+07:00',
|
||||||
|
'+08:00',
|
||||||
|
'+09:00',
|
||||||
|
'+09:30',
|
||||||
|
'+10:00',
|
||||||
|
'+10:30',
|
||||||
|
'+11:00',
|
||||||
|
'+12:00',
|
||||||
|
'+13:00',
|
||||||
|
'+14:00'
|
||||||
|
];
|
|
@ -126,6 +126,7 @@ export default {
|
||||||
workTime: 'Arbeitszeit',
|
workTime: 'Arbeitszeit',
|
||||||
startAt: 'Beginn um',
|
startAt: 'Beginn um',
|
||||||
finishAt: 'Ende um',
|
finishAt: 'Ende um',
|
||||||
|
day: 'Tag',
|
||||||
addWorkingHours: 'Arbeitszeiten hinzufügen',
|
addWorkingHours: 'Arbeitszeiten hinzufügen',
|
||||||
specialisation: 'Spezialisierung',
|
specialisation: 'Spezialisierung',
|
||||||
selectSpecialisation: 'Wählen Sie Ihre Spezialisierung, um fortzufahren',
|
selectSpecialisation: 'Wählen Sie Ihre Spezialisierung, um fortzufahren',
|
||||||
|
|
|
@ -126,6 +126,7 @@ export default {
|
||||||
workTime: 'Work time',
|
workTime: 'Work time',
|
||||||
startAt: 'Start at',
|
startAt: 'Start at',
|
||||||
finishAt: 'Finish at',
|
finishAt: 'Finish at',
|
||||||
|
day: 'Day',
|
||||||
addWorkingHours: 'Add working hours',
|
addWorkingHours: 'Add working hours',
|
||||||
specialisation: 'Specialisation',
|
specialisation: 'Specialisation',
|
||||||
selectSpecialisation: 'Select your specialisation to proceed',
|
selectSpecialisation: 'Select your specialisation to proceed',
|
||||||
|
|
|
@ -126,6 +126,7 @@ export default {
|
||||||
workTime: 'Tiempo de trabajo',
|
workTime: 'Tiempo de trabajo',
|
||||||
startAt: 'Empieza a las',
|
startAt: 'Empieza a las',
|
||||||
finishAt: 'Termina a las',
|
finishAt: 'Termina a las',
|
||||||
|
day: 'Día',
|
||||||
addWorkingHours: 'Añadir horas de trabajo',
|
addWorkingHours: 'Añadir horas de trabajo',
|
||||||
specialisation: 'Especialización',
|
specialisation: 'Especialización',
|
||||||
selectSpecialisation: 'Selecciona tu especialización para continuar',
|
selectSpecialisation: 'Selecciona tu especialización para continuar',
|
||||||
|
|
|
@ -126,6 +126,7 @@ export default {
|
||||||
workTime: 'Heures de travail',
|
workTime: 'Heures de travail',
|
||||||
startAt: 'Commencer à',
|
startAt: 'Commencer à',
|
||||||
finishAt: 'Finir à',
|
finishAt: 'Finir à',
|
||||||
|
day: 'Jour',
|
||||||
addWorkingHours: 'Ajouter des heures de travail',
|
addWorkingHours: 'Ajouter des heures de travail',
|
||||||
specialisation: 'Spécialisation',
|
specialisation: 'Spécialisation',
|
||||||
selectSpecialisation: 'Sélectionnez votre spécialisation pour continuer',
|
selectSpecialisation: 'Sélectionnez votre spécialisation pour continuer',
|
||||||
|
|
|
@ -126,6 +126,7 @@ export default {
|
||||||
workTime: 'Orario di lavoro',
|
workTime: 'Orario di lavoro',
|
||||||
startAt: 'Inizia alle',
|
startAt: 'Inizia alle',
|
||||||
finishAt: 'Termina alle',
|
finishAt: 'Termina alle',
|
||||||
|
day: 'Giorno',
|
||||||
addWorkingHours: 'Aggiungi ore lavorative',
|
addWorkingHours: 'Aggiungi ore lavorative',
|
||||||
specialisation: 'Specializzazione',
|
specialisation: 'Specializzazione',
|
||||||
selectSpecialisation: 'Seleziona la tua specializzazione per continuare',
|
selectSpecialisation: 'Seleziona la tua specializzazione per continuare',
|
||||||
|
|
|
@ -126,6 +126,7 @@ export default {
|
||||||
workTime: 'Рабочее время',
|
workTime: 'Рабочее время',
|
||||||
startAt: 'Начало в',
|
startAt: 'Начало в',
|
||||||
finishAt: 'Завершение в',
|
finishAt: 'Завершение в',
|
||||||
|
day: 'День',
|
||||||
addWorkingHours: 'Добавить рабочие часы',
|
addWorkingHours: 'Добавить рабочие часы',
|
||||||
specialisation: 'Специализация',
|
specialisation: 'Специализация',
|
||||||
selectSpecialisation: 'Выберите свою специализацию для продолжения',
|
selectSpecialisation: 'Выберите свою специализацию для продолжения',
|
||||||
|
|
|
@ -1395,6 +1395,7 @@
|
||||||
background-position: 99% 50%;
|
background-position: 99% 50%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
color: #FFBD00;
|
color: #FFBD00;
|
||||||
|
@ -1421,6 +1422,16 @@
|
||||||
background: #C4DFE6;
|
background: #C4DFE6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
grid-template-columns: 80px 1fr 1fr 32px;
|
||||||
|
|
||||||
|
&__single {
|
||||||
|
grid-template-columns: 80px 1fr 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__inner{
|
&__inner{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -1437,6 +1448,7 @@
|
||||||
&__wrap {
|
&__wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.btn-cancel,
|
.btn-cancel,
|
||||||
.btn-edit {
|
.btn-edit {
|
||||||
|
|
|
@ -53,8 +53,15 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
|
right: 22px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
transition: all .1s ease;
|
transition: all .1s ease;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +117,14 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
|
right: 22px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
transition: all .1s ease;
|
transition: all .1s ease;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
.b-timepicker {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 54px !important;
|
||||||
|
|
||||||
|
&.ant-picker-filled {
|
||||||
|
background: transparent !important;
|
||||||
|
z-index: 1;
|
||||||
|
padding-top: 22px !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #2c7873 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-input {
|
||||||
|
input {
|
||||||
|
font-size: 15px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-picker-suffix {
|
||||||
|
margin-top: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-wrap {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #F8F8F7;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&.b-timepicker__active .b-timepicker-label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 14px;
|
||||||
|
top: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-label {
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 24px;
|
||||||
|
color: #000;
|
||||||
|
opacity: .3;
|
||||||
|
position: absolute;
|
||||||
|
left: 16px;
|
||||||
|
top: 15px;
|
||||||
|
right: 22px;
|
||||||
|
z-index: 0;
|
||||||
|
transition: all .1s ease;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,3 +8,4 @@
|
||||||
@import "_buttons.scss";
|
@import "_buttons.scss";
|
||||||
@import "_practice.scss";
|
@import "_practice.scss";
|
||||||
@import "_collapse.scss";
|
@import "_collapse.scss";
|
||||||
|
@import "_timepicker.scss";
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { UploadFile } from 'antd';
|
import { UploadFile } from 'antd';
|
||||||
import {EducationDTO} from "./education";
|
import { EducationDTO } from './education';
|
||||||
import {ExpertsTags} from "./tags";
|
import { ExpertsTags } from './tags';
|
||||||
import {PracticeDTO} from "./practice";
|
import { PracticeDTO } from './practice';
|
||||||
import {ScheduleDTO} from "./schedule";
|
import { ScheduleDTO } from './schedule';
|
||||||
|
|
||||||
export type ProfileData = {
|
export type ProfileData = {
|
||||||
username?: string;
|
username?: string;
|
||||||
|
|
|
@ -3,8 +3,15 @@ export type WorkingTime = {
|
||||||
startTimeUtc?: number,
|
startTimeUtc?: number,
|
||||||
endDayOfWeekUtc?: string,
|
endDayOfWeekUtc?: string,
|
||||||
endTimeUtc?: number
|
endTimeUtc?: number
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface ScheduleDTO {
|
export interface ScheduleDTO {
|
||||||
workingTimes?: WorkingTime[]
|
workingTimes?: WorkingTime[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MapWorkingTime = {
|
||||||
|
startDay?: string;
|
||||||
|
startTimeMin?: number;
|
||||||
|
endDay?: string;
|
||||||
|
endTimeMin?: number;
|
||||||
|
};
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
import dayjs from 'dayjs';
|
import { MapWorkingTime, WorkingTime } from '../types/schedule';
|
||||||
import { WorkingTime } from '../types/schedule';
|
|
||||||
|
|
||||||
const WEEK_DAY = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
export const WEEK_DAY = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
||||||
const MAX_DAY_TIME = 24 * 60; // min
|
const MAX_DAY_TIME = 24 * 60; // min
|
||||||
|
|
||||||
export const getCurrentTime = (data: WorkingTime) => {
|
const addWeekDay = (weekDay?: string): string => {
|
||||||
|
const ind = weekDay ? WEEK_DAY.indexOf(weekDay) + 1 : 0;
|
||||||
|
return WEEK_DAY[ind >= WEEK_DAY.length ? 0 : ind];
|
||||||
|
}
|
||||||
|
|
||||||
|
const subWeekDay = (weekDay?: string): string => {
|
||||||
|
const ind = weekDay ? WEEK_DAY.indexOf(weekDay) - 1 : 0;
|
||||||
|
return WEEK_DAY[ind < 0 ? WEEK_DAY.length - 1 : ind];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getCurrentTime = (data: WorkingTime, timeZone: string): MapWorkingTime => {
|
||||||
let startDay = data.startDayOfWeekUtc;
|
let startDay = data.startDayOfWeekUtc;
|
||||||
let endDay = data.endDayOfWeekUtc;
|
let endDay = data.endDayOfWeekUtc;
|
||||||
const currentTimeZone = dayjs().format('Z');
|
|
||||||
const startUtc = data.startTimeUtc / (1000 * 1000 * 60);
|
const startUtc = data.startTimeUtc / (1000 * 1000 * 60);
|
||||||
const endUtc = data.endTimeUtc / (1000 * 1000 * 60);
|
const endUtc = data.endTimeUtc / (1000 * 1000 * 60);
|
||||||
const matches = currentTimeZone.match(/(\+|-)([0-9]{2}):([0-9]{2})/);
|
const matches = timeZone.match(/(\+|-)([0-9]{2}):([0-9]{2})/) || [];
|
||||||
const sign = matches[1];
|
const sign = matches[1];
|
||||||
const h = matches[2];
|
const h = matches[2];
|
||||||
const m = matches[3];
|
const m = matches[3];
|
||||||
|
@ -29,34 +37,186 @@ export const getCurrentTime = (data: WorkingTime) => {
|
||||||
endMin = endUtc - (Number(h) * 60) - Number(m);
|
endMin = endUtc - (Number(h) * 60) - Number(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startMin > MAX_DAY_TIME) {
|
if (startMin >= MAX_DAY_TIME) {
|
||||||
startMin = startMin - MAX_DAY_TIME;
|
startMin = 0;
|
||||||
const ind = startDay ? WEEK_DAY.indexOf(startDay) + 1 : 0;
|
// startMin = startMin - MAX_DAY_TIME;
|
||||||
startDay = WEEK_DAY[ind >= WEEK_DAY.length ? 0 : ind];
|
// const ind = startDay ? WEEK_DAY.indexOf(startDay) + 1 : 0;
|
||||||
|
// startDay = WEEK_DAY[ind >= WEEK_DAY.length ? 0 : ind];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endMin > MAX_DAY_TIME) {
|
if (endMin >= MAX_DAY_TIME) {
|
||||||
endMin = endMin - MAX_DAY_TIME;
|
endMin = 0;
|
||||||
const ind = endDay ? WEEK_DAY.indexOf(endDay) + 1 : 0;
|
// endMin = endMin - MAX_DAY_TIME;
|
||||||
endDay = WEEK_DAY[ind >= WEEK_DAY.length ? 0 : ind];
|
// const ind = endDay ? WEEK_DAY.indexOf(endDay) + 1 : 0;
|
||||||
|
// endDay = WEEK_DAY[ind >= WEEK_DAY.length ? 0 : ind];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startMin <= 0) {
|
if (startMin <= 0) {
|
||||||
startMin = MAX_DAY_TIME - startMin;
|
startMin = 0;
|
||||||
const ind = startDay ? WEEK_DAY.indexOf(startDay) - 1 : 0;
|
// startMin = MAX_DAY_TIME - startMin;
|
||||||
startDay = WEEK_DAY[ind < 0 ? WEEK_DAY.length - 1 : ind];
|
// const ind = startDay ? WEEK_DAY.indexOf(startDay) - 1 : 0;
|
||||||
|
// startDay = WEEK_DAY[ind < 0 ? WEEK_DAY.length - 1 : ind];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endMin <= 0) {
|
if (endMin <= 0) {
|
||||||
endMin = MAX_DAY_TIME - endMin;
|
endMin = 0;
|
||||||
const ind = endDay ? WEEK_DAY.indexOf(endDay) - 1 : 0;
|
// endMin = MAX_DAY_TIME - endMin;
|
||||||
endDay = WEEK_DAY[ind < 0 ? WEEK_DAY.length - 1 : ind];
|
// const ind = endDay ? WEEK_DAY.indexOf(endDay) - 1 : 0;
|
||||||
|
// endDay = WEEK_DAY[ind < 0 ? WEEK_DAY.length - 1 : ind];
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
startDay,
|
startDay,
|
||||||
startTime: `${(startMin - startMin % 60)/60}:${startMin % 60 || '00'}`,
|
startTimeMin: startMin,
|
||||||
endDay: endDay,
|
endDay: endDay,
|
||||||
endTime: `${(endMin - endMin % 60)/60}:${endMin % 60 || '00'}`
|
endTimeMin: endMin
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getTimeString = (min: number) => {
|
||||||
|
const timeH = `${(min - min % 60)/60}`;
|
||||||
|
|
||||||
|
return `${timeH.length === 1 ? `0${timeH}` : timeH}:${min % 60 || '00'}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formattedSchedule = (workingTimes: WorkingTime[], timeZone: string): MapWorkingTime[] => (
|
||||||
|
workingTimes.map((time) => getCurrentTime(time, timeZone)) || []
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getNewTime = (time: string): number => {
|
||||||
|
const timeArr = time.split(':');
|
||||||
|
|
||||||
|
return Number(timeArr[0]) * 60 + Number(timeArr[1]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTimeZoneOffset = (oldTime: string, newTime: string): { sign: string, offset: number } => {
|
||||||
|
// старая таймзона
|
||||||
|
const matches1 = oldTime.match(/(\+|-)([0-9]{2}):([0-9]{2})/) || [];
|
||||||
|
const sign1 = matches1[1];
|
||||||
|
const min1 = Number(matches1[2]) * 60 + Number(matches1[3]);
|
||||||
|
// новая таймзона
|
||||||
|
const matches2 = newTime.match(/(\+|-)([0-9]{2}):([0-9]{2})/) || [];
|
||||||
|
const sign2 = matches2[1];
|
||||||
|
const min2 = Number(matches2[2]) * 60 + Number(matches2[3]);
|
||||||
|
|
||||||
|
if (sign1 === '+' && sign2 === '+') {
|
||||||
|
if (min1 < min2) {
|
||||||
|
return {
|
||||||
|
sign: '+',
|
||||||
|
offset: min2 - min1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
sign: '-',
|
||||||
|
offset: min1 - min2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign1 === '-' && sign2 === '-') {
|
||||||
|
if (min1 < min2) {
|
||||||
|
return {
|
||||||
|
sign: '-',
|
||||||
|
offset: min2 - min1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
sign: '+',
|
||||||
|
offset: min1 - min2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign1 === '+' && sign2 === '-') {
|
||||||
|
return {
|
||||||
|
sign: '-',
|
||||||
|
offset: min1 + min2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign1 === '-' && sign2 === '+') {
|
||||||
|
return {
|
||||||
|
sign: '+',
|
||||||
|
offset: min1 + min2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formattedTimeByOffset = (workTime: MapWorkingTime, objOffset: { sign: string, offset: number }): MapWorkingTime => {
|
||||||
|
if (objOffset.sign === '+') {
|
||||||
|
const resStartMin = workTime.startTimeMin + objOffset.offset;
|
||||||
|
const resEndMin = workTime.endTimeMin ? workTime.endTimeMin + objOffset.offset : workTime.endTimeMin;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...workTime,
|
||||||
|
startTimeMin: resStartMin >= MAX_DAY_TIME ? 0 : resStartMin,
|
||||||
|
endTimeMin: resEndMin >= MAX_DAY_TIME ? 0 : resEndMin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objOffset.sign === '-') {
|
||||||
|
const resStartMin = workTime.startTimeMin - objOffset.offset;
|
||||||
|
const resEndMin = workTime.endTimeMin ? workTime.endTimeMin - objOffset.offset : workTime.endTimeMin;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...workTime,
|
||||||
|
startTimeMin: resStartMin < 0 ? 0 : resStartMin,
|
||||||
|
endTimeMin: resEndMin < 0 ? 0 : resEndMin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return workTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getResultTime = (data: MapWorkingTime, timeZone: string): WorkingTime => {
|
||||||
|
let startDayOfWeekUtc = data.startDay;
|
||||||
|
let endDayOfWeekUtc = data.startDay;
|
||||||
|
const matches = timeZone.match(/(\+|-)([0-9]{2}):([0-9]{2})/) || [];
|
||||||
|
const sign = matches[1];
|
||||||
|
const offset = (Number(matches[2]) * 60) + Number(matches[3]);
|
||||||
|
let startTime = data.startTimeMin;
|
||||||
|
let endTime = data.endTimeMin === 0 ? MAX_DAY_TIME : data.endTimeMin;
|
||||||
|
|
||||||
|
if (sign === '+') {
|
||||||
|
startTime = startTime - offset;
|
||||||
|
endTime = endTime - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign === '-') {
|
||||||
|
startTime = startTime + offset;
|
||||||
|
endTime = endTime + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startTime >= MAX_DAY_TIME) {
|
||||||
|
startTime = startTime - MAX_DAY_TIME;
|
||||||
|
startDayOfWeekUtc = addWeekDay(startDayOfWeekUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endTime >= MAX_DAY_TIME) {
|
||||||
|
endTime = endTime - MAX_DAY_TIME;
|
||||||
|
endDayOfWeekUtc = addWeekDay(endDayOfWeekUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startTime < 0) {
|
||||||
|
startTime = MAX_DAY_TIME - Math.abs(startTime || 0);
|
||||||
|
startDayOfWeekUtc = subWeekDay(startDayOfWeekUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endTime < 0) {
|
||||||
|
endTime = MAX_DAY_TIME - Math.abs(endTime || 0);
|
||||||
|
endDayOfWeekUtc = subWeekDay(endDayOfWeekUtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
startDayOfWeekUtc,
|
||||||
|
startTimeUtc: startTime * 1000 * 1000 * 60,
|
||||||
|
endDayOfWeekUtc,
|
||||||
|
endTimeUtc: endTime * 1000 * 1000 * 60
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formattedWorkList = (workingList: MapWorkingTime[], timeZone: string): WorkingTime[] => (
|
||||||
|
workingList
|
||||||
|
.filter(({ startTimeMin, endTimeMin }) => !(!startTimeMin && !endTimeMin))
|
||||||
|
.map((time) => getResultTime(time, timeZone)) || []
|
||||||
|
);
|
||||||
|
|
Loading…
Reference in New Issue