diff --git a/public/rich-components/calendar.svg b/public/rich-components/calendar.svg new file mode 100644 index 00000000..3e652af2 --- /dev/null +++ b/public/rich-components/calendar.svg @@ -0,0 +1,68 @@ + + + + + + + + + + June 2024 + + + + + + + + + + S + M + T + W + T + F + S + + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + + + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 15 + 16 + 17 + 18 + 19 + 20 + 21 + + + 22 + 23 + 24 + 25 + 26 + 27 + 28 + + + 29 + 30 + \ No newline at end of file diff --git a/src/common/components/front-rich-components/calendar/calendar.business.tsx b/src/common/components/front-rich-components/calendar/calendar.business.tsx new file mode 100644 index 00000000..c5883373 --- /dev/null +++ b/src/common/components/front-rich-components/calendar/calendar.business.tsx @@ -0,0 +1,28 @@ +// TODO: #250 Add Unit tests +// https://github.com/Lemoncode/quickmock/issues/250 + +export const calculatePreviousMonth = (date: Date) => + new Date(date.getFullYear(), date.getMonth() - 1, 1); + +export const calculateNextMonth = (date: Date) => + new Date(date.getFullYear(), date.getMonth() + 1, 1); + +export const getCurrentMonthDays = (date: Date) => { + const month = date.toLocaleString('en', { month: 'long' }); + const year = date.getFullYear(); + const daysInMonth = new Date(year, date.getMonth() + 1, 0).getDate(); + const startDay = new Date(year, date.getMonth(), 1).getDay(); + + const days = []; + let week = new Array(startDay).fill(null); // Fill the first week with nulls up to the start day + + for (let day = 1; day <= daysInMonth; day++) { + week.push(day); + if (week.length === 7 || day === daysInMonth) { + days.push(week); + week = []; + } + } + + return { month, year, days }; +}; diff --git a/src/common/components/front-rich-components/calendar/calendar.tsx b/src/common/components/front-rich-components/calendar/calendar.tsx new file mode 100644 index 00000000..5806a816 --- /dev/null +++ b/src/common/components/front-rich-components/calendar/calendar.tsx @@ -0,0 +1,166 @@ +import { useState, forwardRef } from 'react'; +import { Group, Rect, Text, Line } from 'react-konva'; +import { ShapeSizeRestrictions } from '@/core/model'; +import { ShapeProps } from '../../front-components/shape.model'; +import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions'; +import { + calculateNextMonth, + calculatePreviousMonth, + getCurrentMonthDays, +} from './calendar.business'; + +const calendarShapeSizeRestrictions: ShapeSizeRestrictions = { + minWidth: 350, + minHeight: 350, + maxWidth: -1, + maxHeight: -1, + defaultWidth: 500, + defaultHeight: 500, +}; + +export const getCalendarShapeSizeRestrictions = (): ShapeSizeRestrictions => + calendarShapeSizeRestrictions; + +export const CalendarShape = forwardRef( + ({ x, y, width, height, id, onSelected, ...shapeProps }, ref) => { + const { width: restrictedWidth, height: restrictedHeight } = + fitSizeToShapeSizeRestrictions( + calendarShapeSizeRestrictions, + width, + height + ); + + const [currentDate, setCurrentDate] = useState(new Date()); + + const handlePrevMonth = () => { + setCurrentDate(prevDate => calculatePreviousMonth(prevDate)); + }; + + const handleNextMonth = () => { + setCurrentDate(prevDate => calculateNextMonth(prevDate)); + }; + + const { month, year, days } = getCurrentMonthDays(currentDate); + + const margin = 10; + const headerHeight = 50; + const dayBoxWidth = (restrictedWidth - margin * 2) / 7; + const dayBoxHeight = (height - headerHeight) / days.length; + + return ( + onSelected(id, 'calendar')} + > + {/* Encabezado del calendario */} + + + {/* Left arrow */} + + + {/* Year and month */} + + + + {/* Right arrow */} + + + {/* Calendar table */} + + + {/* Week days */} + {['S', 'M', 'T', 'W', 'T', 'F', 'S'].map((day, i) => ( + + ))} + + {/* Month days */} + {days.map((week: any[], rowIndex: number) => + week.map((day, colIndex) => ( + + )) + )} + + ); + } +); + +export default CalendarShape; diff --git a/src/common/components/front-rich-components/calendar/index.ts b/src/common/components/front-rich-components/calendar/index.ts new file mode 100644 index 00000000..edaf8f07 --- /dev/null +++ b/src/common/components/front-rich-components/calendar/index.ts @@ -0,0 +1 @@ +export * from './calendar'; diff --git a/src/common/components/front-rich-components/index.ts b/src/common/components/front-rich-components/index.ts index c1cc421f..078dd3eb 100644 --- a/src/common/components/front-rich-components/index.ts +++ b/src/common/components/front-rich-components/index.ts @@ -6,4 +6,5 @@ export * from './map-chart'; export * from './video-player'; export * from './bar-chart'; export * from './line-chart'; +export * from './calendar/calendar'; export * from './table/table'; diff --git a/src/core/model/index.ts b/src/core/model/index.ts index 3471f279..f8e99746 100644 --- a/src/core/model/index.ts +++ b/src/core/model/index.ts @@ -47,7 +47,9 @@ export type ShapeType = | 'largeArrow' | 'bar' | 'triangle' + | 'horizontalScrollBar' | 'image' + | 'calendar' | 'image' | 'table' | 'verticalScrollBar' @@ -95,6 +97,7 @@ export const ShapeDisplayName: Record = { image: 'Image', table: 'Table', horizontalScrollBar: 'Horizontal Scroll Bar', + calendar: 'Calendar', verticalScrollBar: 'Vertical Scroll Bar', }; diff --git a/src/pods/canvas/canvas.model.ts b/src/pods/canvas/canvas.model.ts index 128720c9..61842566 100644 --- a/src/pods/canvas/canvas.model.ts +++ b/src/pods/canvas/canvas.model.ts @@ -50,6 +50,7 @@ import { getHorizontalMenuShapeSizeRestrictions, getMapChartShapeSizeRestrictions, getLineChartShapeSizeRestrictions, + getCalendarShapeSizeRestrictions, getTableSizeRestrictions, } from '@/common/components/front-rich-components'; import { @@ -269,6 +270,11 @@ export const getDefaultSizeFromShape = (shapeType: ShapeType): Size => { width: getHorizontalScrollBarShapeSizeRestrictions().defaultWidth, height: getHorizontalScrollBarShapeSizeRestrictions().defaultHeight, }; + case 'calendar': + return { + width: getCalendarShapeSizeRestrictions().defaultWidth, + height: getCalendarShapeSizeRestrictions().defaultHeight, + }; case 'verticalScrollBar': return { width: getVerticalScrollBarShapeSizeRestrictions().defaultWidth, diff --git a/src/pods/canvas/shape-renderer/index.tsx b/src/pods/canvas/shape-renderer/index.tsx index 97b13702..afde584f 100644 --- a/src/pods/canvas/shape-renderer/index.tsx +++ b/src/pods/canvas/shape-renderer/index.tsx @@ -53,6 +53,7 @@ import { import { renderSmalltext } from './simple-text-components/smalltext.renderer'; import { renderParagraph } from './simple-text-components/paragraph.renderer'; import { renderImage } from './simple-basic-shapes/image.renderer'; +import { renderCalendar } from './simple-rich-components/calendar.renderer'; export const renderShapeComponent = ( shape: ShapeModel, @@ -99,6 +100,8 @@ export const renderShapeComponent = ( return renderPieChart(shape, shapeRenderedProps); case 'map': return renderMapChart(shape, shapeRenderedProps); + case 'calendar': + return renderCalendar(shape, shapeRenderedProps); case 'linechart': return renderLineChart(shape, shapeRenderedProps); case 'diamond': diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/calendar.renderer.tsx b/src/pods/canvas/shape-renderer/simple-rich-components/calendar.renderer.tsx new file mode 100644 index 00000000..50b92ff4 --- /dev/null +++ b/src/pods/canvas/shape-renderer/simple-rich-components/calendar.renderer.tsx @@ -0,0 +1,30 @@ +import { CalendarShape } from '@/common/components/front-rich-components/calendar'; +import { ShapeRendererProps } from '../model'; +import { ShapeModel } from '@/core/model'; + +export const renderCalendar = ( + shape: ShapeModel, + shapeRenderedProps: ShapeRendererProps +) => { + const { handleSelected, shapeRefs, handleDragEnd, handleTransform } = + shapeRenderedProps; + + return ( + + ); +}; diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/index.ts b/src/pods/canvas/shape-renderer/simple-rich-components/index.ts index cffb8531..423ba71e 100644 --- a/src/pods/canvas/shape-renderer/simple-rich-components/index.ts +++ b/src/pods/canvas/shape-renderer/simple-rich-components/index.ts @@ -6,4 +6,5 @@ export * from './map-chart.renderer'; export * from './breadcrumb.renderer'; export * from './bar-chart.renderer'; export * from './line-chart.renderer'; +export * from './calendar.renderer'; export * from './table.renderer'; diff --git a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts index 36dd071e..b6f96c2f 100644 --- a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts +++ b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts @@ -12,5 +12,6 @@ export const mockRichComponentsCollection: ItemInfo[] = [ { thumbnailSrc: '/rich-components/map.svg', type: 'map' }, { thumbnailSrc: '/rich-components/barchart.svg', type: 'bar' }, { thumbnailSrc: '/rich-components/line-chart.svg', type: 'linechart' }, + { thumbnailSrc: '/rich-components/calendar.svg', type: 'calendar' }, { thumbnailSrc: '/rich-components/table.svg', type: 'table' }, ];