Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#159 add calendar component #243

Merged
merged 12 commits into from
Aug 22, 2024
68 changes: 68 additions & 0 deletions public/rich-components/calendar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -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 };
};
166 changes: 166 additions & 0 deletions src/common/components/front-rich-components/calendar/calendar.tsx
Original file line number Diff line number Diff line change
@@ -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<any, ShapeProps>(
({ 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 (
<Group
x={x}
y={y}
ref={ref}
width={restrictedWidth}
height={restrictedHeight}
{...shapeProps}
onClick={() => onSelected(id, 'calendar')}
>
{/* Encabezado del calendario */}
<Rect
x={0}
y={0}
width={restrictedWidth}
height={headerHeight}
cornerRadius={10}
stroke="black"
strokeWidth={2}
fill="white"
/>

{/* Left arrow */}
<Line
points={[
margin + 20,
margin + 10,
margin + 10,
margin + 20,
margin + 20,
margin + 30,
]}
closed
fill="black"
stroke="black"
strokeWidth={2}
onClick={handlePrevMonth}
cursor="pointer"
/>

{/* Year and month */}

<Text
x={margin + 20}
y={headerHeight / 3}
text={`${month} ${year}`}
width={restrictedWidth - margin - 20 - margin - 30}
fontFamily="Comic Sans MS, cursive"
fontSize={20}
fill="black"
align="center"
ellipsis={true}
/>

{/* Right arrow */}
<Line
points={[
restrictedWidth - margin - 30,
margin + 10,
restrictedWidth - margin - 20,
margin + 20,
restrictedWidth - margin - 30,
margin + 30,
]}
closed
fill="black"
stroke="black"
strokeWidth={2}
onClick={handleNextMonth}
cursor="pointer"
/>

{/* Calendar table */}
<Rect
x={0}
y={headerHeight + 10}
width={restrictedWidth}
height={height - headerHeight + 20}
cornerRadius={10}
stroke="black"
strokeWidth={2}
fill="white"
/>

{/* Week days */}
{['S', 'M', 'T', 'W', 'T', 'F', 'S'].map((day, i) => (
<Text
key={i}
x={35 + i * dayBoxWidth}
y={headerHeight + 20}
text={day}
fontFamily="Comic Sans MS, cursive"
fontSize={16}
fill="black"
/>
))}

{/* Month days */}
{days.map((week: any[], rowIndex: number) =>
week.map((day, colIndex) => (
<Text
key={`${rowIndex}-${colIndex}`}
x={35 + colIndex * dayBoxWidth}
y={headerHeight + 70 + rowIndex * dayBoxHeight}
text={day ? day.toString() : ''}
fontFamily="Comic Sans MS, cursive"
fontSize={16}
fill="black"
/>
))
)}
</Group>
);
}
);

export default CalendarShape;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './calendar';
1 change: 1 addition & 0 deletions src/common/components/front-rich-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
3 changes: 3 additions & 0 deletions src/core/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export type ShapeType =
| 'largeArrow'
| 'bar'
| 'triangle'
| 'horizontalScrollBar'
| 'image'
| 'calendar'
| 'image'
| 'table'
| 'verticalScrollBar'
Expand Down Expand Up @@ -95,6 +97,7 @@ export const ShapeDisplayName: Record<ShapeType, string> = {
image: 'Image',
table: 'Table',
horizontalScrollBar: 'Horizontal Scroll Bar',
calendar: 'Calendar',
verticalScrollBar: 'Vertical Scroll Bar',
};

Expand Down
6 changes: 6 additions & 0 deletions src/pods/canvas/canvas.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
getHorizontalMenuShapeSizeRestrictions,
getMapChartShapeSizeRestrictions,
getLineChartShapeSizeRestrictions,
getCalendarShapeSizeRestrictions,
getTableSizeRestrictions,
} from '@/common/components/front-rich-components';
import {
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions src/pods/canvas/shape-renderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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':
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<CalendarShape
id={shape.id}
key={shape.id}
ref={shapeRefs.current[shape.id]}
x={shape.x}
y={shape.y}
name="shape"
width={shape.width}
height={shape.height}
draggable
typeOfTransformer={shape.typeOfTransformer}
onSelected={handleSelected}
onDragEnd={handleDragEnd(shape.id)}
onTransform={handleTransform}
onTransformEnd={handleTransform}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -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' },
];
Loading