@farm-investimentos/front-mfe-components 15.12.1 → 15.13.0
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/front-mfe-components.common.js +4484 -90
- package/dist/front-mfe-components.common.js.map +1 -1
- package/dist/front-mfe-components.css +1 -1
- package/dist/front-mfe-components.umd.js +4484 -90
- package/dist/front-mfe-components.umd.js.map +1 -1
- package/dist/front-mfe-components.umd.min.js +1 -1
- package/dist/front-mfe-components.umd.min.js.map +1 -1
- package/package.json +2 -1
- package/src/components/GanttChart/GanttChart.scss +246 -0
- package/src/components/GanttChart/GanttChart.stories.js +480 -0
- package/src/components/GanttChart/GanttChart.vue +308 -0
- package/src/components/GanttChart/__tests__/GanttChart.spec.js +561 -0
- package/src/components/GanttChart/composition/buildBarPositioning.ts +146 -0
- package/src/components/GanttChart/composition/buildGanttData.ts +61 -0
- package/src/components/GanttChart/composition/index.ts +2 -0
- package/src/components/GanttChart/index.ts +4 -0
- package/src/components/GanttChart/types/index.ts +60 -0
- package/src/components/GanttChart/utils/dateUtils.ts +98 -0
- package/src/main.ts +2 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { computed } from 'vue';
|
|
2
|
+
import { isValid, endOfMonth } from 'date-fns';
|
|
3
|
+
|
|
4
|
+
export default function buildGanttData(props) {
|
|
5
|
+
const autoCalculatedDateRange = computed(() => {
|
|
6
|
+
const allDates: Date[] = [];
|
|
7
|
+
|
|
8
|
+
props.data.groups.forEach(group => {
|
|
9
|
+
group.bars.forEach(bar => {
|
|
10
|
+
const startDate = bar.start instanceof Date ? bar.start : new Date(bar.start);
|
|
11
|
+
const endDate = bar.end instanceof Date ? bar.end : new Date(bar.end);
|
|
12
|
+
|
|
13
|
+
if (isValid(startDate)) {
|
|
14
|
+
allDates.push(startDate);
|
|
15
|
+
}
|
|
16
|
+
if (isValid(endDate)) {
|
|
17
|
+
allDates.push(endDate);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (allDates.length === 0) {
|
|
23
|
+
const now = new Date();
|
|
24
|
+
return {
|
|
25
|
+
start: new Date(now.getFullYear(), 0, 1),
|
|
26
|
+
end: new Date(now.getFullYear(), 11, 31)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const minDate = new Date(Math.min(...allDates.map(d => d.getTime())));
|
|
31
|
+
const maxDate = new Date(Math.max(...allDates.map(d => d.getTime())));
|
|
32
|
+
|
|
33
|
+
minDate.setDate(1);
|
|
34
|
+
const adjustedMaxDate = endOfMonth(maxDate);
|
|
35
|
+
|
|
36
|
+
return { start: minDate, end: adjustedMaxDate };
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const autoGeneratedLegend = computed(() => {
|
|
40
|
+
const uniqueItems = new Map<string, { label: string; color: string }>();
|
|
41
|
+
|
|
42
|
+
props.data.groups.forEach(group => {
|
|
43
|
+
group.bars.forEach(bar => {
|
|
44
|
+
const key = `${bar.color}-${bar.label}`;
|
|
45
|
+
if (!uniqueItems.has(key)) {
|
|
46
|
+
uniqueItems.set(key, {
|
|
47
|
+
label: bar.label,
|
|
48
|
+
color: bar.color
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return Array.from(uniqueItems.values());
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
autoCalculatedDateRange,
|
|
59
|
+
autoGeneratedLegend
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface GanttData {
|
|
2
|
+
groups: GanttGroup[];
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface GanttGroup {
|
|
6
|
+
title: string;
|
|
7
|
+
bars: GanttBar[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface GanttBar {
|
|
11
|
+
id: string | number;
|
|
12
|
+
label: string;
|
|
13
|
+
start: Date | string;
|
|
14
|
+
end: Date | string;
|
|
15
|
+
color: string;
|
|
16
|
+
rowPosition?: number;
|
|
17
|
+
tooltipData?: TooltipData;
|
|
18
|
+
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface LegendItem {
|
|
23
|
+
label: string;
|
|
24
|
+
color: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface MonthColumn {
|
|
28
|
+
date: Date;
|
|
29
|
+
label: string;
|
|
30
|
+
isCurrentMonth: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface BarGridStyle {
|
|
34
|
+
'grid-column-start': number;
|
|
35
|
+
'grid-column-end': number;
|
|
36
|
+
'background-color': string;
|
|
37
|
+
'grid-row': string;
|
|
38
|
+
'margin-left': string;
|
|
39
|
+
'width': string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface DateRange {
|
|
43
|
+
start: Date;
|
|
44
|
+
end: Date;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
// NEW: Tooltip data interface
|
|
49
|
+
export interface TooltipData {
|
|
50
|
+
[key: string]: string | number | null | undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// NEW: Enhanced tooltip state
|
|
54
|
+
export interface TooltipState {
|
|
55
|
+
visible: boolean;
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
title: string;
|
|
59
|
+
barData: GanttBar | null;
|
|
60
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date utility functions for GanttChart component
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
eachMonthOfInterval,
|
|
7
|
+
startOfMonth,
|
|
8
|
+
format,
|
|
9
|
+
isSameMonth,
|
|
10
|
+
getDaysInMonth as dateFnsGetDaysInMonth,
|
|
11
|
+
differenceInMonths,
|
|
12
|
+
parseISO,
|
|
13
|
+
isValid
|
|
14
|
+
} from 'date-fns';
|
|
15
|
+
import { ptBR } from 'date-fns/locale';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get all months between two dates
|
|
19
|
+
*/
|
|
20
|
+
export const getMonthsBetween = (startDate: Date, endDate: Date): Date[] => {
|
|
21
|
+
return eachMonthOfInterval({
|
|
22
|
+
start: startOfMonth(startDate),
|
|
23
|
+
end: startOfMonth(endDate)
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Format month in Brazilian Portuguese
|
|
29
|
+
*/
|
|
30
|
+
export const formatMonth = (date: Date): string => {
|
|
31
|
+
const formatted = format(date, 'MMM/yyyy', { locale: ptBR });
|
|
32
|
+
return formatted.charAt(0).toUpperCase() + formatted.slice(1);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if date is current month
|
|
37
|
+
*/
|
|
38
|
+
export const isCurrentMonth = (date: Date): boolean => {
|
|
39
|
+
return isSameMonth(date, new Date());
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get number of days in a month
|
|
44
|
+
*/
|
|
45
|
+
export const getDaysInMonth = (year: number, month: number): number => {
|
|
46
|
+
return dateFnsGetDaysInMonth(new Date(year, month));
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get column index for a date relative to start date
|
|
51
|
+
*/
|
|
52
|
+
export const getColumnForDate = (date: Date | string, startDate: Date): number => {
|
|
53
|
+
const targetDate = date instanceof Date ? date : new Date(date);
|
|
54
|
+
const startDateObj = startDate instanceof Date ? startDate : new Date(startDate);
|
|
55
|
+
|
|
56
|
+
if (!isValid(targetDate) || !isValid(startDateObj)) {
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const targetMonth = startOfMonth(targetDate);
|
|
61
|
+
const startMonth = startOfMonth(startDateObj);
|
|
62
|
+
|
|
63
|
+
return differenceInMonths(targetMonth, startMonth);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Parse ISO date string (YYYY-MM-DD) to Date object
|
|
68
|
+
*/
|
|
69
|
+
export const parseIsoDate = (iso: string): Date => {
|
|
70
|
+
if (!iso || typeof iso !== 'string') {
|
|
71
|
+
return new Date(NaN);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const parsedDate = parseISO(iso);
|
|
76
|
+
return isValid(parsedDate) ? parsedDate : new Date(NaN);
|
|
77
|
+
} catch {
|
|
78
|
+
return new Date(NaN);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Format date range for tooltip display
|
|
84
|
+
*/
|
|
85
|
+
export const formatDateRange = (start: Date | string, end: Date | string): string => {
|
|
86
|
+
const startDate = typeof start === 'string' ? new Date(start) : start;
|
|
87
|
+
const endDate = typeof end === 'string' ? new Date(end) : end;
|
|
88
|
+
|
|
89
|
+
if (!isValid(startDate) || !isValid(endDate)) {
|
|
90
|
+
return 'Data inválida';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const formatDate = (date: Date) => {
|
|
94
|
+
return format(date, 'dd/MM/yyyy', { locale: ptBR });
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return `${formatDate(startDate)} - ${formatDate(endDate)}`;
|
|
98
|
+
};
|
package/src/main.ts
CHANGED
|
@@ -20,7 +20,7 @@ import DefaultButton from './components/Buttons/DefaultButton';
|
|
|
20
20
|
import Collapsible from './components/Collapsible';
|
|
21
21
|
import IdCaption from './components/IdCaption';
|
|
22
22
|
import ResourceMetaInfo from './components/ResourceMetaInfo';
|
|
23
|
-
|
|
23
|
+
import GanttChart from './components/GanttChart';
|
|
24
24
|
export {
|
|
25
25
|
DataTableEmptyWrapper,
|
|
26
26
|
DataTablePaginator,
|
|
@@ -92,3 +92,4 @@ export * from './components/layout/Container';
|
|
|
92
92
|
export * from './components/layout/ContainerFooter';
|
|
93
93
|
export * from './components/layout/Row';
|
|
94
94
|
export * from './components/layout/Line';
|
|
95
|
+
export * from './components/GanttChart';
|