Skip to content

Commit 66885b0

Browse files
author
Daniel Montoya
committed
feat(PDYE-1116): avance dropdown uikit y prueba con mock data
1 parent 63bc345 commit 66885b0

16 files changed

+2178
-2937
lines changed

package-lock.json

+1,465-2,936
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"@types/eclass__api": "git+ssh://git@gitlab.com/eclass/types-eclass-api.git#v3.108.0",
6666
"@types/eclass__sequelize-models": "git+ssh://git@gitlab.com/eclass/types-sequelize-models.git#v5.40.0",
6767
"@types/jest": "27.5.2",
68+
"@types/node": "^16.11.17",
6869
"@types/react": "17.0.64",
6970
"@types/react-dom": "17.0.20",
7071
"@typescript-eslint/eslint-plugin": "5.17.0",
@@ -108,7 +109,7 @@
108109
"sort-by": "1.2.0",
109110
"ts-jest": "27.1.5",
110111
"ts-patch": "2.0.1",
111-
"typescript": "4.6.3",
112+
"typescript": "4.9.5",
112113
"typescript-transform-paths": "3.3.1",
113114
"vite": "2.9.16",
114115
"vite-tsconfig-paths": "3.4.1"
@@ -117,6 +118,7 @@
117118
"@chakra-ui/react": "1.8.9",
118119
"@emotion/react": "11.8.2",
119120
"@emotion/styled": "11.8.1",
121+
"date-fns": "^4.1.0",
120122
"framer-motion": "6.2.8",
121123
"react-hot-toast": "2.4.1",
122124
"react-ripples": "2.2.1"

src/atoms/Icons/Calendar.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Base, BaseProps } from './Base'
2+
export function Calendar(props: BaseProps): JSX.Element {
3+
return (
4+
<Base {...props} title="Calendar">
5+
<g fill="#B0CFE0">
6+
<path
7+
fill="#B0CFE0"
8+
d="M15 2h-2V0h-2v2H9V0H7v2H5V0H3v2H1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1zm-1 12H2V5h12v9z"
9+
/>
10+
<path d="M4 7h2v2H4zM7 7h2v2H7zM4 10h2v2H4zM7 10h2v2H7zM10 7h2v2h-2zM10 10h2v2h-2z" />
11+
</g>
12+
</Base>
13+
)
14+
}
15+
16+
Calendar.displayName = 'Calendar'

src/atoms/Icons/Clock.tsx

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Base, BaseProps } from './Base'
2+
export function Clock(props: BaseProps): JSX.Element {
3+
return (
4+
<Base {...props} title="Clock">
5+
<path
6+
fill="#B0CFE0"
7+
d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 9H7V4h2v3h3v2z"
8+
/>
9+
</Base>
10+
)
11+
}
12+
13+
Clock.displayName = 'Clock'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { CalendarDropdownContainer } from './CalendarDropdown/CalendarDropdownContainer'
2+
import { ICalendarDropdown } from './types'
3+
4+
export const CalendarDropdown = ({
5+
redirectToCalendar,
6+
text,
7+
courseColors,
8+
now,
9+
events,
10+
loading,
11+
}: ICalendarDropdown): JSX.Element => {
12+
const date = new Date(now)
13+
const isoDate = date.toISOString()
14+
15+
return (
16+
<CalendarDropdownContainer
17+
events={events}
18+
loading={loading}
19+
now={isoDate}
20+
courseColors={courseColors}
21+
redirectToCalendar={redirectToCalendar}
22+
text={text}
23+
/>
24+
)
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { useEffect, useState } from 'react'
2+
import { Box, Menu, MenuList, useMediaQuery } from '@chakra-ui/react'
3+
4+
import { useParseEvents } from './services/parseEvents'
5+
import { GoToCalendar } from './Components/GoToCalendar'
6+
import { Header } from './Components/Header'
7+
import { Empty } from './Components/Empty'
8+
import { Events } from './Components/Events'
9+
import { ICalendarDropdown } from '../types'
10+
11+
export const CalendarDropdownContainer = ({
12+
events,
13+
loading,
14+
text,
15+
now,
16+
redirectToCalendar,
17+
courseColors: colors,
18+
}: ICalendarDropdown): JSX.Element => {
19+
const [isMobile] = useMediaQuery('(max-width: 577px)')
20+
const { closeAndMarkSeen, empty, hasNew, ...all } = useParseEvents(events, now)
21+
22+
const [isTooltipDisabled, setTooltipDisabled] = useState(false)
23+
const [isMenuOpen, setMenuOpen] = useState(false)
24+
25+
// Resuelve tooltip que se mantiene visible al cerrar el menu
26+
useEffect(() => {
27+
if (isMenuOpen) {
28+
setTooltipDisabled(true)
29+
} else {
30+
const timer = setTimeout(() => setTooltipDisabled(false), 300)
31+
return () => clearTimeout(timer)
32+
}
33+
}, [isMenuOpen])
34+
35+
const onClose = (): void => {
36+
closeAndMarkSeen()
37+
setMenuOpen(false)
38+
}
39+
40+
return (
41+
<Box
42+
zIndex={4}
43+
className="calendarDropdown"
44+
mr="24px"
45+
position="relative"
46+
sx={{
47+
'>div': {
48+
position: isMobile ? 'fixed !important' : 'absolute',
49+
left: isMobile ? '0 !important' : 'auto',
50+
top: isMobile ? '62px !important' : 'auto',
51+
transform: isMobile ? 'none !important' : 'translate3d(-409px, 38px, 0px) !important',
52+
},
53+
54+
'.chakra-menu__menu-list': {
55+
position: 'absolute',
56+
width: isMobile ? '100vw' : '500px',
57+
maxHeight: isMobile ? 'calc(100vh - 62px)' : 'auto',
58+
overflowY: isMobile ? 'auto' : 'hidden',
59+
borderRadius: isMobile ? '0' : '10px',
60+
boxShadow: isMobile ? 'none' : 'rgba(47, 47, 47, 0.2) -1px 6px 40px 0px',
61+
animation: 'none !important',
62+
transition: 'none !important',
63+
transform: 'none !important',
64+
opacity: '1 !important',
65+
},
66+
'.chakra-menu__group__title': {
67+
fontSize: '18px',
68+
lineHeight: '31px',
69+
margin: '32px 0 0',
70+
padding: '0 0 8px 24px',
71+
},
72+
'.react-ripples': {
73+
width: 'inherit',
74+
},
75+
}}
76+
>
77+
<Menu autoSelect={false} onOpen={() => setMenuOpen(true)} onClose={onClose}>
78+
<>
79+
<GoToCalendar
80+
hasNew={hasNew ?? false}
81+
text={text?.tooltip || 'Ir a Mi Calendario'}
82+
tooltipDisabled={isTooltipDisabled}
83+
/>
84+
<MenuList>
85+
<Header
86+
text={text?.header || 'Próximas fechas importantes de tus cursos'}
87+
isMobile={isMobile}
88+
/>
89+
{loading ? (
90+
<Loading text={text?.loading || 'Cargando'} />
91+
) : events.length === 0 || empty ? (
92+
<Empty text={text?.empty || 'Aún no tienes eventos en tu calendario'} />
93+
) : (
94+
<Events
95+
colors={colors}
96+
events={all}
97+
text={text}
98+
redirecToCalendar={redirectToCalendar}
99+
isMobile={isMobile}
100+
/>
101+
)}
102+
</MenuList>
103+
</>
104+
</Menu>
105+
</Box>
106+
)
107+
}
108+
109+
const Loading = ({ text }: { text?: string }): JSX.Element => {
110+
return <div>{text ?? 'Loading...'}</div>
111+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Box } from '@chakra-ui/react'
2+
3+
import { NoEventsIcon } from '../Icons/NoEventsIcon'
4+
5+
export const Empty = ({ text }: { text?: string }): JSX.Element => {
6+
return (
7+
<Box
8+
alignItems="center"
9+
display="flex"
10+
flexDirection="column"
11+
gap="24px"
12+
padding="104px 0px 64px"
13+
>
14+
<NoEventsIcon />
15+
<Box fontSize="20px" fontWeight={700} color="#2F2F2F">
16+
{text ?? 'Aún no tienes eventos en tu calendario'}
17+
</Box>
18+
</Box>
19+
)
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import { BtnSecondary } from '@/molecules'
2+
import { Box, MenuGroup } from '@chakra-ui/react'
3+
import { Key } from 'react'
4+
5+
import { EventsList } from '../../../EventsList/EventsList'
6+
import { Text } from '../../types'
7+
8+
interface EventsProps {
9+
events: {
10+
today: Event[]
11+
tomorrow: Event[]
12+
next: Event[]
13+
}
14+
text: Text
15+
redirecToCalendar: () => void
16+
isMobile: boolean
17+
colors: any
18+
}
19+
20+
export const Events = ({
21+
events,
22+
text,
23+
redirecToCalendar,
24+
isMobile,
25+
colors,
26+
}: EventsProps): JSX.Element => {
27+
const { today, tomorrow, next } = events
28+
return (
29+
<Box
30+
borderRadius="10px"
31+
color="#1C1818"
32+
h={isMobile ? 'auto' : '552px'}
33+
overflowY="scroll"
34+
pb="32px"
35+
sx={{
36+
'.calendar-events-group': {
37+
borderBottom: '1px solid #E8E8E8',
38+
},
39+
}}
40+
>
41+
{redirecToCalendar && (
42+
<Box
43+
sx={{
44+
button: {
45+
p: '8px ',
46+
fontSize: '14px',
47+
lineHeight: '14px',
48+
minW: 'fit-content',
49+
minH: 'fit-content',
50+
},
51+
}}
52+
>
53+
<BtnSecondary onClick={redirecToCalendar} m="72px 0 0 24px">
54+
{text?.buttonCalendar ?? 'Ir a Mi Calendario'}
55+
</BtnSecondary>
56+
</Box>
57+
)}
58+
<EventsGroup
59+
colors={colors}
60+
text={text.course}
61+
title={text?.events?.today ?? 'Hoy'}
62+
events={today}
63+
/>
64+
<EventsGroup
65+
colors={colors}
66+
text={text.course}
67+
title={text?.events?.tomorrow ?? 'Mañana'}
68+
events={tomorrow}
69+
/>
70+
<EventsGroup
71+
colors={colors}
72+
text={text.course}
73+
title={text?.events?.next ?? 'Próximos'}
74+
events={next}
75+
/>
76+
</Box>
77+
)
78+
}
79+
interface Event {
80+
id: Key | null | undefined
81+
associated_resource: { name: any }
82+
course: { name: string | undefined }
83+
formatedDate: { start: string; hours: string }
84+
course_id: string | number
85+
isNew: boolean | undefined
86+
}
87+
88+
interface EventsGroupProps {
89+
title: string
90+
events: Event[]
91+
text: string
92+
colors: any
93+
}
94+
95+
const EventsGroup = ({ title, events, text, colors }: EventsGroupProps): JSX.Element => {
96+
if (!events || (events && events.length === 0)) return <></>
97+
return (
98+
<Box
99+
className="calendar-events-group"
100+
_focus={{
101+
background: 'none !important',
102+
border: '1px solid #0189FF',
103+
}}
104+
sx={{
105+
'.chakra-menu__menuitem > div': {
106+
w: '100%',
107+
},
108+
}}
109+
>
110+
<MenuGroup title={title}>
111+
{events.map(
112+
(event: {
113+
id: Key | null | undefined
114+
associated_resource: { name: any }
115+
course: { name: string | undefined }
116+
formatedDate: { start: string; hours: string }
117+
course_id: string | number
118+
isNew: boolean | undefined
119+
}) => {
120+
return (
121+
<Box // Una vez que el evento se comporte como link, se debe cambiar Box a MenuItem y aplicar el efecto de focus
122+
bg="#FFFFFF"
123+
border="none"
124+
cursor="default"
125+
padding="0"
126+
key={event.id}
127+
_hover={{
128+
boxShadow: 'none !important',
129+
cursor: 'default !important',
130+
bg: 'none !important',
131+
}}
132+
_focus={{
133+
background: 'none !important',
134+
boxShadow: 'none !important',
135+
}}
136+
// _focus={{
137+
// background: 'none !important',
138+
// boxShadow: `inset 0px 0.5px 0px 3px ${vars('colors-icon-deepSkyBlue')}`,
139+
// }}
140+
>
141+
<EventsList
142+
key={event.id}
143+
name={event.associated_resource.name || ''}
144+
courseName={event.course.name}
145+
date={event.formatedDate.start}
146+
hours={event.formatedDate.hours}
147+
color={event.course_id && colors?.[event.course_id]}
148+
text={text}
149+
hasNotification={event.isNew}
150+
isDropdown
151+
/>
152+
</Box>
153+
)
154+
}
155+
)}
156+
</MenuGroup>
157+
</Box>
158+
)
159+
}

0 commit comments

Comments
 (0)