@mindly/ui-components 3.1.4 → 3.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fonts/Lato-Bold.ttf +0 -0
- package/dist/fonts/Lato-Regular.ttf +0 -0
- package/dist/fonts/Lato-Semibold.ttf +0 -0
- package/dist/index.ts +106 -0
- package/dist/lib/AppHeader/AppHeader.style.ts +19 -0
- package/dist/lib/AppHeader/AppHeader.tsx +23 -0
- package/dist/lib/AppHeader/index.ts +1 -0
- package/dist/lib/Avatar/Avatar.style.ts +17 -0
- package/dist/lib/Avatar/Avatar.tsx +46 -0
- package/dist/lib/Avatar/index.ts +1 -0
- package/dist/lib/Container/Container.styled.ts +15 -0
- package/dist/lib/Container/Container.tsx +15 -0
- package/dist/lib/Container/index.ts +1 -0
- package/dist/lib/EntryNotFound/EntryNotFound.style.ts +14 -0
- package/dist/lib/EntryNotFound/EntryNotFound.tsx +21 -0
- package/dist/lib/EntryNotFound/calendar.svg +69 -0
- package/dist/lib/EntryNotFound/index.ts +1 -0
- package/dist/lib/Filters/ListSelect/ListSelect.style.ts +38 -0
- package/dist/lib/Filters/ListSelect/ListSelect.tsx +48 -0
- package/dist/lib/Filters/ListSelect/index.ts +1 -0
- package/dist/lib/Filters/Range/Range.style.ts +41 -0
- package/dist/lib/Filters/Range/Range.tsx +48 -0
- package/dist/lib/Filters/Range/index.ts +1 -0
- package/dist/lib/Filters/RowSelect/RowSelect.style.ts +30 -0
- package/dist/lib/Filters/RowSelect/RowSelect.tsx +38 -0
- package/dist/lib/Filters/RowSelect/index.ts +1 -0
- package/dist/lib/Filters/Toggle/Toggle.style.ts +14 -0
- package/dist/lib/Filters/Toggle/Toggle.tsx +26 -0
- package/dist/lib/Filters/Toggle/index.ts +1 -0
- package/dist/lib/HorisontalCalendar/HorizontalCalendar.styled.ts +117 -0
- package/dist/lib/HorisontalCalendar/HorizontalCalendar.tsx +213 -0
- package/dist/lib/HorisontalCalendar/index.ts +1 -0
- package/dist/lib/ImageWithFallback/ImageWithFallback.tsx +37 -0
- package/dist/lib/LetterAvatar/LetterAvatar.styled.ts +32 -0
- package/dist/lib/LetterAvatar/LetterAvatar.tsx +23 -0
- package/dist/lib/Modal/Modal.style.ts +12 -0
- package/dist/lib/Modal/Modal.tsx +30 -0
- package/dist/lib/Modal/index.ts +1 -0
- package/dist/lib/ModalCalendar/ModalCalendar.styled.ts +123 -0
- package/dist/lib/ModalCalendar/ModalCalendar.tsx +71 -0
- package/dist/lib/PersonDateTimeCard/PersonDateTimeCard.styled.ts +36 -0
- package/dist/lib/PersonDateTimeCard/PersonDateTimeCard.tsx +32 -0
- package/dist/lib/Segment/Segment.style.ts +14 -0
- package/dist/lib/Segment/Segment.tsx +29 -0
- package/dist/lib/Segment/index.ts +2 -0
- package/dist/lib/Segment/types.ts +4 -0
- package/dist/lib/SelectImpressionEmoji/ImpressionEmojiEnum.ts +9 -0
- package/dist/lib/SelectImpressionEmoji/SelectImpressionEmoji.styled.ts +28 -0
- package/dist/lib/SelectImpressionEmoji/SelectImpressionEmoji.tsx +56 -0
- package/dist/lib/SelectImpressionEmoji/SelectImpressionEmojiProps.ts +8 -0
- package/dist/lib/SelectImpressionEmoji/emojis.ts +9 -0
- package/dist/lib/SelectImpressionEmoji/index.tsx +14 -0
- package/dist/lib/Theme/global.css +251 -0
- package/dist/lib/Theme/mindly_constants.ts +23 -0
- package/dist/lib/UsersPsychologistScrollList/UserPsychologistScrollList.styled.ts +61 -0
- package/dist/lib/UsersPsychologistScrollList/UsersPsychologistScrollList.tsx +68 -0
- package/dist/lib/archived-consultation-card/ArchivedConsultation.test.tsx +9 -0
- package/dist/lib/archived-consultation-card/ArchivedConsultationCard.style.ts +72 -0
- package/dist/lib/archived-consultation-card/ArchivedConsultationCard.svg +3 -0
- package/dist/lib/archived-consultation-card/ArchivedConsultationCard.tsx +61 -0
- package/dist/lib/button/Button.style.ts +170 -0
- package/dist/lib/button/Button.test.tsx +39 -0
- package/dist/lib/button/Button.tsx +47 -0
- package/dist/lib/consultation-card/ConsultationCard.style.ts +119 -0
- package/dist/lib/consultation-card/ConsultationCard.test.tsx +65 -0
- package/dist/lib/consultation-card/ConsultationCard.tsx +155 -0
- package/dist/lib/consultation-card/ConsultationCardSkeleton.tsx +114 -0
- package/dist/lib/consultation-card/index.ts +2 -0
- package/dist/lib/content-card/ContentCard.style.ts +59 -0
- package/dist/lib/content-card/ContentCard.test.tsx +29 -0
- package/dist/lib/content-card/ContentCard.tsx +81 -0
- package/dist/lib/date-picker/DatePicker.style.ts +52 -0
- package/dist/lib/date-picker/DatePicker.test.tsx +9 -0
- package/dist/lib/date-picker/DatePicker.tsx +59 -0
- package/dist/lib/floating-button/FloatingButton.style.ts +21 -0
- package/dist/lib/floating-button/FloatingButton.test.tsx +9 -0
- package/dist/lib/floating-button/FloatingButton.tsx +29 -0
- package/dist/lib/floating-button/floating button.svg +6 -0
- package/dist/lib/footer-for-booking/FooterForBooking.style.ts +56 -0
- package/dist/lib/footer-for-booking/FooterForBooking.test.tsx +30 -0
- package/dist/lib/footer-for-booking/FooterForBooking.tsx +53 -0
- package/dist/lib/input/Input.style.ts +37 -0
- package/dist/lib/input/Input.test.tsx +21 -0
- package/dist/lib/input/Input.tsx +73 -0
- package/dist/lib/list-button/ListButton.style.ts +21 -0
- package/dist/lib/list-button/ListButton.test.tsx +26 -0
- package/dist/lib/list-button/ListButton.tsx +30 -0
- package/dist/lib/navigation-bar/NavigationBar.style.ts +81 -0
- package/dist/lib/navigation-bar/NavigationBar.test.tsx +15 -0
- package/dist/lib/navigation-bar/NavigationBar.tsx +31 -0
- package/dist/lib/no-internet-connection/NoInternetConnection.style.ts +26 -0
- package/dist/lib/no-internet-connection/NoInternetConnection.svg +10 -0
- package/dist/lib/no-internet-connection/NoInternetConnection.test.tsx +9 -0
- package/dist/lib/no-internet-connection/NoInternetConnection.tsx +30 -0
- package/dist/lib/notes-card-text/NotesCardText.style.ts +14 -0
- package/dist/lib/notes-card-text/NotesCardText.tsx +32 -0
- package/dist/lib/notes-card-text/index.ts +1 -0
- package/dist/lib/notes-editor/NotesEditor.styled.ts +24 -0
- package/dist/lib/notes-editor/NotesEditor.tsx +16 -0
- package/dist/lib/scroll-tabs/ScrollTabs.style.ts +19 -0
- package/dist/lib/scroll-tabs/ScrollTabs.test.tsx +9 -0
- package/dist/lib/scroll-tabs/ScrollTabs.tsx +42 -0
- package/dist/lib/tab-bar/TabBar.style.tsx +43 -0
- package/dist/lib/tab-bar/TabBar.tsx +11 -0
- package/dist/lib/therapist-card/TherapistCard.style.ts +104 -0
- package/dist/lib/therapist-card/TherapistCard.test.tsx +40 -0
- package/dist/lib/therapist-card/TherapistCard.tsx +96 -0
- package/dist/lib/therapist-information-component/TherapistInformationComponent.style.ts +40 -0
- package/dist/lib/therapist-information-component/TherapistInformationComponent.test.tsx +16 -0
- package/dist/lib/therapist-information-component/TherapistInformationComponent.tsx +51 -0
- package/dist/lib/toast/index.css +13 -0
- package/dist/lib/toast/toast.ts +17 -0
- package/dist/lib/userAppTypes.ts +261 -0
- package/dist/lib/your-local-time-block/YourLocalTimeBlock.styled.ts +28 -0
- package/dist/lib/your-local-time-block/YourLocalTimeBlock.tsx +26 -0
- package/dist/react-app-env.d.ts +1 -0
- package/dist/svg.d.ts +13 -0
- package/package.json +4 -17
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const ToggleWrapper = styled.div`
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: space-between;
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
export const ToggleTitle = styled.h3`
|
|
10
|
+
font-weight: 600;
|
|
11
|
+
font-size: 20px;
|
|
12
|
+
line-height: 24px;
|
|
13
|
+
color: #1d201f;
|
|
14
|
+
`;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { IonToggle } from '@ionic/react';
|
|
2
|
+
import React, { FC } from 'react';
|
|
3
|
+
import { ToggleTitle, ToggleWrapper } from './Toggle.style';
|
|
4
|
+
|
|
5
|
+
type ToggleProps = {
|
|
6
|
+
title: string;
|
|
7
|
+
checked?: boolean;
|
|
8
|
+
onChange: (checked: boolean) => void;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const Toggle: FC<ToggleProps> = ({
|
|
12
|
+
title,
|
|
13
|
+
checked = false,
|
|
14
|
+
onChange,
|
|
15
|
+
}) => {
|
|
16
|
+
return (
|
|
17
|
+
<ToggleWrapper>
|
|
18
|
+
<ToggleTitle>{title}</ToggleTitle>
|
|
19
|
+
<IonToggle
|
|
20
|
+
mode="ios"
|
|
21
|
+
checked={checked}
|
|
22
|
+
onIonChange={(e) => onChange(e.detail.checked)}
|
|
23
|
+
/>
|
|
24
|
+
</ToggleWrapper>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Toggle as default } from './Toggle';
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
const HorizontalCalendarStyled = styled.div`
|
|
4
|
+
--contrastColor: #21abd2;
|
|
5
|
+
--highlightColor: #d6f2f9;
|
|
6
|
+
user-select: none;
|
|
7
|
+
|
|
8
|
+
ul {
|
|
9
|
+
list-style: none;
|
|
10
|
+
display: flex;
|
|
11
|
+
gap: 9px;
|
|
12
|
+
overflow: scroll;
|
|
13
|
+
width: 100%;
|
|
14
|
+
white-space: nowrap;
|
|
15
|
+
padding: 0;
|
|
16
|
+
scrollbar-width: none;
|
|
17
|
+
|
|
18
|
+
&::-webkit-scrollbar {
|
|
19
|
+
display: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
li {
|
|
23
|
+
display: inline-block;
|
|
24
|
+
height: 70px;
|
|
25
|
+
width: 44px;
|
|
26
|
+
border-radius: 8px;
|
|
27
|
+
padding: 6px;
|
|
28
|
+
|
|
29
|
+
.day {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
align-items: center;
|
|
33
|
+
align-content: center;
|
|
34
|
+
font-family: 'Inter';
|
|
35
|
+
font-style: normal;
|
|
36
|
+
font-weight: 700;
|
|
37
|
+
|
|
38
|
+
.title {
|
|
39
|
+
font-size: 10px;
|
|
40
|
+
line-height: 14px;
|
|
41
|
+
text-transform: uppercase;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.tags {
|
|
45
|
+
height: 11px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.day-content {
|
|
49
|
+
font-size: 16px;
|
|
50
|
+
line-height: 16px;
|
|
51
|
+
height: 32px;
|
|
52
|
+
width: 32px;
|
|
53
|
+
border: 1px solid var(--contrastColor);
|
|
54
|
+
border-radius: 50%;
|
|
55
|
+
display: flex;
|
|
56
|
+
justify-content: center;
|
|
57
|
+
justify-items: center;
|
|
58
|
+
align-items: center;
|
|
59
|
+
align-content: center;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&.selected {
|
|
64
|
+
background-color: var(--highlightColor);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&.has-consultation .day .day-content {
|
|
68
|
+
background-color: var(--contrastColor);
|
|
69
|
+
color: #fff;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&.has-my-note .day .tags,
|
|
73
|
+
&.has-tome-notes .day .tags {
|
|
74
|
+
position: relative;
|
|
75
|
+
|
|
76
|
+
.draw {
|
|
77
|
+
position: absolute;
|
|
78
|
+
width: 5px;
|
|
79
|
+
height: 5px;
|
|
80
|
+
left: -2px;
|
|
81
|
+
top: 1px;
|
|
82
|
+
border-radius: 3px;
|
|
83
|
+
background: #21ABD2;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&.has-tome-notes .day .tags .draw {
|
|
88
|
+
width: 15px;
|
|
89
|
+
left: -7px
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.day.skeleton {
|
|
93
|
+
.title .sk {
|
|
94
|
+
width: 15px;
|
|
95
|
+
height: 14px;
|
|
96
|
+
border-radius: 4px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.tags {
|
|
100
|
+
height: 5px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.day-content {
|
|
104
|
+
border: none;
|
|
105
|
+
|
|
106
|
+
.sk {
|
|
107
|
+
width: 32px;
|
|
108
|
+
height: 32px;
|
|
109
|
+
border-radius: 50%;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
export default HorizontalCalendarStyled;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import HorizontalCalendarStyled from './HorizontalCalendar.styled';
|
|
3
|
+
import { IonSkeletonText, useIonViewDidEnter } from '@ionic/react';
|
|
4
|
+
|
|
5
|
+
export type HorizontalCalendarProps = {
|
|
6
|
+
consultationDatesSeconds?: number[],
|
|
7
|
+
myNotesDatesSeconds?: number[],
|
|
8
|
+
toMeNotesDatesSeconds?: number[],
|
|
9
|
+
/**
|
|
10
|
+
* Days to be rendered. e.g. 15 - means 7 before today and 7 after today
|
|
11
|
+
*/
|
|
12
|
+
daysToRender?: number,
|
|
13
|
+
value?: DayToRender | Date,
|
|
14
|
+
onChange?: (value: DayToRender) => void
|
|
15
|
+
/**
|
|
16
|
+
* date from which a component should start coordinates.
|
|
17
|
+
* e.g. startFrom = "15.01.2022", daysToRender=5
|
|
18
|
+
* return ["13.02.2022", "14.01.2022", "15.01.2022", "16.01.2022", "17.01.2022"]
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
startFrom?: Date;
|
|
22
|
+
showSkeleton?: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
enum DayOfWeek {
|
|
26
|
+
SUN = 'Нд',
|
|
27
|
+
MON = 'Пн',
|
|
28
|
+
TUE = 'Вт',
|
|
29
|
+
WED = 'Ср',
|
|
30
|
+
THU = 'Чт',
|
|
31
|
+
FRI = 'Пт',
|
|
32
|
+
SAT = 'Сб'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function dateToDayOfWeek(date: Date): DayOfWeek {
|
|
36
|
+
const day = date.getDay();
|
|
37
|
+
switch (day) {
|
|
38
|
+
default:
|
|
39
|
+
case 0:
|
|
40
|
+
return DayOfWeek.SUN;
|
|
41
|
+
case 1:
|
|
42
|
+
return DayOfWeek.MON;
|
|
43
|
+
case 2:
|
|
44
|
+
return DayOfWeek.TUE;
|
|
45
|
+
case 3:
|
|
46
|
+
return DayOfWeek.WED;
|
|
47
|
+
case 4:
|
|
48
|
+
return DayOfWeek.THU;
|
|
49
|
+
case 5:
|
|
50
|
+
return DayOfWeek.FRI;
|
|
51
|
+
case 6:
|
|
52
|
+
return DayOfWeek.SAT;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function dateToShortDate(d: Date): string {
|
|
57
|
+
return d.toDateString();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type DayToRender = {
|
|
61
|
+
/**
|
|
62
|
+
* e.g. "2.2.122", "24.4.122"
|
|
63
|
+
*/
|
|
64
|
+
shortDate: string;
|
|
65
|
+
dayOfMonth: number;
|
|
66
|
+
dayOfWeek: DayOfWeek;
|
|
67
|
+
date: Date;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
|
|
71
|
+
|
|
72
|
+
function getDaysToRender(daysToRender = 15, startFrom: Date = new Date()): DayToRender[] {
|
|
73
|
+
const daysAroundTodayCount = Math.floor(daysToRender / 2);
|
|
74
|
+
const days: DayToRender[] = [];
|
|
75
|
+
|
|
76
|
+
const startingDate = startFrom.valueOf() - (MILLISECONDS_IN_DAY * daysAroundTodayCount);
|
|
77
|
+
|
|
78
|
+
for (let i = 0, currentDate = startingDate;
|
|
79
|
+
i < daysToRender;
|
|
80
|
+
i++, currentDate += MILLISECONDS_IN_DAY) {
|
|
81
|
+
const date = new Date(currentDate);
|
|
82
|
+
days.push({
|
|
83
|
+
shortDate: dateToShortDate(date),
|
|
84
|
+
dayOfWeek: dateToDayOfWeek(date),
|
|
85
|
+
dayOfMonth: date.getDate(),
|
|
86
|
+
date: date,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return days;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function secondsToShortDate(seconds: number): string {
|
|
94
|
+
const date = new Date(seconds * 1000);
|
|
95
|
+
return dateToShortDate(date);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function secondsArrayToShortDatesSet(secondsArray: number[] = []): Set<string> {
|
|
99
|
+
if (!Array.isArray(secondsArray)) return new Set<string>();
|
|
100
|
+
const shortDatesArray = secondsArray.map(sec => secondsToShortDate(sec));
|
|
101
|
+
const set = new Set(shortDatesArray);
|
|
102
|
+
return set;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const HorizontalCalendar: React.FC<HorizontalCalendarProps> = (props) => {
|
|
106
|
+
const dateNow = new Date();
|
|
107
|
+
const [daysToRender, setDaysToRender] = useState<DayToRender[]>([]);
|
|
108
|
+
const currentShortDate = dateToShortDate(dateNow);
|
|
109
|
+
const todayRef = useRef<HTMLDivElement | null>(null);
|
|
110
|
+
const consultationsShortDatesSet = useMemo<Set<string>>(() => {
|
|
111
|
+
return secondsArrayToShortDatesSet(props.consultationDatesSeconds);
|
|
112
|
+
}, [props.consultationDatesSeconds]);
|
|
113
|
+
|
|
114
|
+
const myNotesDatesSet = useMemo<Set<string>>(() => {
|
|
115
|
+
return secondsArrayToShortDatesSet(props.myNotesDatesSeconds);
|
|
116
|
+
}, [props.myNotesDatesSeconds]);
|
|
117
|
+
|
|
118
|
+
const toMeNotesDatesSet = useMemo<Set<string>>(() => {
|
|
119
|
+
return secondsArrayToShortDatesSet(props.toMeNotesDatesSeconds);
|
|
120
|
+
}, [props.toMeNotesDatesSeconds]);
|
|
121
|
+
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
const toRender = getDaysToRender(props.daysToRender, props.startFrom);
|
|
124
|
+
setDaysToRender(toRender);
|
|
125
|
+
}, [props.daysToRender, dateNow.getDate(), props.startFrom]);
|
|
126
|
+
|
|
127
|
+
const scrollToSelectedDay = useCallback(() => {
|
|
128
|
+
if (props.showSkeleton) return;
|
|
129
|
+
if (!todayRef.current) return;
|
|
130
|
+
todayRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
|
131
|
+
}, [todayRef.current, props.showSkeleton]);
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
scrollToSelectedDay();
|
|
135
|
+
}, [todayRef.current, props.showSkeleton]);
|
|
136
|
+
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
// eslint-disable-next-line no-restricted-globals
|
|
139
|
+
const S = self;
|
|
140
|
+
const handler = () => {
|
|
141
|
+
scrollToSelectedDay();
|
|
142
|
+
};
|
|
143
|
+
S.addEventListener('calendar_scroll', handler);
|
|
144
|
+
return () => {
|
|
145
|
+
S.removeEventListener('calendar_scroll', handler);
|
|
146
|
+
};
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
useIonViewDidEnter(scrollToSelectedDay);
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
const valueShortDate = props.value && (
|
|
153
|
+
props.value instanceof Date ?
|
|
154
|
+
dateToShortDate(props.value)
|
|
155
|
+
: props.value?.shortDate
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
return (<HorizontalCalendarStyled>
|
|
160
|
+
<ul>
|
|
161
|
+
{daysToRender.map(day => {
|
|
162
|
+
if (props.showSkeleton) {
|
|
163
|
+
return (<li
|
|
164
|
+
key={day.shortDate}
|
|
165
|
+
>
|
|
166
|
+
<div className="day skeleton">
|
|
167
|
+
<div className="title">
|
|
168
|
+
<IonSkeletonText className="sk" animated/>
|
|
169
|
+
</div>
|
|
170
|
+
<div className="tags"></div>
|
|
171
|
+
<div className="day-content">
|
|
172
|
+
<IonSkeletonText className="sk" animated/>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</li>);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const isToday = day.shortDate === currentShortDate;
|
|
179
|
+
const hasConsultations = consultationsShortDatesSet.has(day.shortDate);
|
|
180
|
+
const isSelected = props.value ? (valueShortDate === day.shortDate) : isToday;
|
|
181
|
+
const hasMyNote = myNotesDatesSet.has(day.shortDate);
|
|
182
|
+
const hasToMeNotes = toMeNotesDatesSet.has(day.shortDate);
|
|
183
|
+
|
|
184
|
+
const classList = [];
|
|
185
|
+
if (isSelected) classList.push('selected');
|
|
186
|
+
if (isToday) classList.push('today');
|
|
187
|
+
if (hasConsultations) classList.push('has-consultation');
|
|
188
|
+
if (hasMyNote) classList.push('has-my-note');
|
|
189
|
+
if (hasToMeNotes) classList.push('has-tome-notes');
|
|
190
|
+
|
|
191
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
192
|
+
const attributes: any = {};
|
|
193
|
+
if (classList.length) {
|
|
194
|
+
attributes.className = classList.join(' ');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return (<li
|
|
198
|
+
key={day.shortDate}
|
|
199
|
+
onClick={() => {
|
|
200
|
+
props.onChange && props.onChange(day);
|
|
201
|
+
}}
|
|
202
|
+
{...attributes}
|
|
203
|
+
>
|
|
204
|
+
<div className="day" ref={isToday ? todayRef : null}>
|
|
205
|
+
<div className="title">{isToday ? 'Зараз' : day.dayOfWeek}</div>
|
|
206
|
+
<div className="tags"><span className="draw"></span></div>
|
|
207
|
+
<div className="day-content">{day.dayOfMonth}</div>
|
|
208
|
+
</div>
|
|
209
|
+
</li>);
|
|
210
|
+
})}
|
|
211
|
+
</ul>
|
|
212
|
+
</HorizontalCalendarStyled>);
|
|
213
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './HorizontalCalendar';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React, { useState, useCallback, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
export type ImageWithFallbackProps = JSX.IntrinsicElements["img"] & ({
|
|
4
|
+
onErrorContent: React.ReactElement;
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
function filterImgProps(props: any): JSX.IntrinsicElements["img"]{
|
|
9
|
+
const props2 = { ...props };
|
|
10
|
+
delete props2.onErrorContent;
|
|
11
|
+
return props2 as JSX.IntrinsicElements["img"];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ImageWithFallback : React.FC<ImageWithFallbackProps> = (props)=>{
|
|
15
|
+
const [hasError, setHasError] = useState<boolean>(false);
|
|
16
|
+
const innerProps = filterImgProps(props);
|
|
17
|
+
|
|
18
|
+
useEffect(()=>{
|
|
19
|
+
setHasError(false);
|
|
20
|
+
}, [props.src]);
|
|
21
|
+
|
|
22
|
+
const onErrorHandler = useCallback((e)=>{
|
|
23
|
+
setHasError(!!e);
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if (hasError) {
|
|
28
|
+
return props.onErrorContent;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<img {...innerProps} onError={onErrorHandler}/>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export default ImageWithFallback;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
type LetterAvatarStyledProps = {
|
|
4
|
+
dimensions: number;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const LetterAvatarStyled = styled.div<LetterAvatarStyledProps>`
|
|
8
|
+
display: inline-block;
|
|
9
|
+
text-align: center;
|
|
10
|
+
|
|
11
|
+
height: ${({ dimensions }) => dimensions}px;
|
|
12
|
+
width: ${({ dimensions }) => dimensions}px;
|
|
13
|
+
border-radius: 50%;
|
|
14
|
+
background: linear-gradient(
|
|
15
|
+
0deg,
|
|
16
|
+
rgba(255, 255, 255, 0.8),
|
|
17
|
+
rgba(255, 255, 255, 0.8)
|
|
18
|
+
),
|
|
19
|
+
#21abd2;
|
|
20
|
+
color: #21abd2;
|
|
21
|
+
|
|
22
|
+
font-size: 22.4px;
|
|
23
|
+
line-height: 56px;
|
|
24
|
+
font-family: 'Inter';
|
|
25
|
+
font-style: normal;
|
|
26
|
+
font-weight: 700;
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
export default LetterAvatarStyled;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { CSSProperties } from 'react';
|
|
2
|
+
import LetterAvatarStyled from './LetterAvatar.styled';
|
|
3
|
+
|
|
4
|
+
export type LetterAvatarProps = {
|
|
5
|
+
letter: string;
|
|
6
|
+
dimensions?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
style?: CSSProperties;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const LetterAvatar: React.FC<LetterAvatarProps> = (props) => {
|
|
12
|
+
return (
|
|
13
|
+
<LetterAvatarStyled
|
|
14
|
+
dimensions={props.dimensions ?? 56}
|
|
15
|
+
className={props.className}
|
|
16
|
+
style={props.style}
|
|
17
|
+
>
|
|
18
|
+
{props.letter}
|
|
19
|
+
</LetterAvatarStyled>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default React.memo<LetterAvatarProps>(LetterAvatar);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IonModal } from '@ionic/react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { maxContainerWidth } from '../Theme/mindly_constants';
|
|
4
|
+
|
|
5
|
+
type ModalStyledProps = {
|
|
6
|
+
isFullWidth: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const ModalStyled = styled(IonModal)<ModalStyledProps>`
|
|
10
|
+
--max-width: ${({ isFullWidth }) =>
|
|
11
|
+
isFullWidth ? maxContainerWidth : '100%'};
|
|
12
|
+
`;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isPlatform } from '@ionic/react';
|
|
2
|
+
import React, { FC } from 'react';
|
|
3
|
+
import { ModalStyled } from './Modal.style';
|
|
4
|
+
|
|
5
|
+
interface ModalProps {
|
|
6
|
+
fullwidth?: boolean;
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
onDidDismiss: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const Modal: FC<ModalProps> = ({
|
|
12
|
+
fullwidth = false,
|
|
13
|
+
isOpen,
|
|
14
|
+
onDidDismiss,
|
|
15
|
+
children,
|
|
16
|
+
}) => {
|
|
17
|
+
return (
|
|
18
|
+
<ModalStyled
|
|
19
|
+
isFullWidth={
|
|
20
|
+
!fullwidth && (isPlatform('desktop') || isPlatform('tablet'))
|
|
21
|
+
}
|
|
22
|
+
isOpen={isOpen}
|
|
23
|
+
onDidDismiss={onDidDismiss}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
</ModalStyled>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default Modal;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Modal';
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const ModalCalendarStyled = styled.div`
|
|
4
|
+
--rdp-background-color: #fff;
|
|
5
|
+
--rdp-accent-color: none;
|
|
6
|
+
--rdp-outline: none;
|
|
7
|
+
--rdp-outline-selected: none;
|
|
8
|
+
--rdp-cell-size: 48px;
|
|
9
|
+
font-family: 'Inter', sans-serif;
|
|
10
|
+
|
|
11
|
+
& .rdp {
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
& .rdp-month {
|
|
16
|
+
width: 100%;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
& .rdp-table {
|
|
20
|
+
/* max-width: 100%;
|
|
21
|
+
width: 100%; */
|
|
22
|
+
td {
|
|
23
|
+
/* width: 44px; */
|
|
24
|
+
height: 70px;
|
|
25
|
+
text-align: center;
|
|
26
|
+
vertical-align: top;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
th {
|
|
30
|
+
height: 20px;
|
|
31
|
+
text-align: center;
|
|
32
|
+
vertical-align: top;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
& .rdp-caption {
|
|
37
|
+
margin-bottom: 24px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
& .rdp-head_cell span {
|
|
41
|
+
font-weight: 700;
|
|
42
|
+
font-size: 10px;
|
|
43
|
+
line-height: 14px;
|
|
44
|
+
color: #1d201f;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
& button.rdp-day {
|
|
48
|
+
width: 44px;
|
|
49
|
+
height: 100%;
|
|
50
|
+
border: none;
|
|
51
|
+
border-radius: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
& .rdp-caption_label {
|
|
55
|
+
font-weight: 600;
|
|
56
|
+
font-size: 24px;
|
|
57
|
+
line-height: 32px;
|
|
58
|
+
color: #1d201f;
|
|
59
|
+
text-transform: capitalize;
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
type CustomDayWrapperProps = {
|
|
64
|
+
isActive?: boolean;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const CustomDayWrapper = styled.div<CustomDayWrapperProps>`
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
justify-content: flex-end;
|
|
71
|
+
align-items: center;
|
|
72
|
+
width: 100%;
|
|
73
|
+
height: 100%;
|
|
74
|
+
background: ${({ isActive }) => (isActive ? '#D6F2F9' : 'transparent')};
|
|
75
|
+
border-radius: 8px;
|
|
76
|
+
position: relative;
|
|
77
|
+
& span {
|
|
78
|
+
font-weight: 700;
|
|
79
|
+
font-size: 16px;
|
|
80
|
+
line-height: 24px;
|
|
81
|
+
}
|
|
82
|
+
& span.today-active {
|
|
83
|
+
display: inline-block;
|
|
84
|
+
font-weight: 700;
|
|
85
|
+
font-size: 10px;
|
|
86
|
+
line-height: 14px;
|
|
87
|
+
color: #1d201f;
|
|
88
|
+
text-transform: uppercase;
|
|
89
|
+
position: absolute;
|
|
90
|
+
top: 6px;
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
type CustomDayProps = {
|
|
95
|
+
isActive?: boolean;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const CustomDayStyled = styled.div<CustomDayProps>`
|
|
99
|
+
width: 32px;
|
|
100
|
+
height: 32px;
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
justify-content: center;
|
|
104
|
+
border-radius: 50%;
|
|
105
|
+
background: ${({ isActive }) => (isActive ? '#21ABD2;' : 'transparent')};
|
|
106
|
+
color: ${({ isActive }) => (isActive ? '#fff' : '#1D201F')};
|
|
107
|
+
margin-bottom: 7px;
|
|
108
|
+
margin-top: 4px;
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
export const DotStyled = styled.div`
|
|
112
|
+
width: 5px;
|
|
113
|
+
height: 5px;
|
|
114
|
+
border-radius: 50%;
|
|
115
|
+
background: #21abd2;
|
|
116
|
+
`;
|
|
117
|
+
|
|
118
|
+
export const NoteStyled = styled.div`
|
|
119
|
+
width: 15px;
|
|
120
|
+
height: 4px;
|
|
121
|
+
background: #21abd2;
|
|
122
|
+
border-radius: 3px;
|
|
123
|
+
`;
|