Skip to content

Commit a0c805b

Browse files
committed
Added Day, Week, Month View
1 parent 63021d8 commit a0c805b

File tree

5 files changed

+267
-69
lines changed

5 files changed

+267
-69
lines changed

apps/react/tables/libraries/AgGrid/marketing-spend-demo/components/document/day-view-table-component.tsx

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import React, { useEffect, useMemo, useCallback } from 'react';
3+
import React, { useEffect, useMemo, useCallback, useState } from 'react';
44
import { VeltComments, useVeltClient } from '@veltdev/react';
55
import { AgGridReact } from 'ag-grid-react';
66
import { AllCommunityModule, ModuleRegistry } from 'ag-grid-community';
@@ -11,18 +11,20 @@ ModuleRegistry.registerModules([AllCommunityModule]);
1111

1212
// Import modularized components and utilities
1313
import { customDarkTheme } from './constants';
14-
import { dateComparator } from './utils';
14+
import { dateComparator, generateTableData, generateWeeklyTableData, generateMonthlyTableData } from './utils';
1515
import { createCustomHeaderComponent } from './grid-components/CustomHeaderComponent';
1616
import { RowNumberRenderer } from './grid-components/RowNumberRenderer';
1717
import { createVeltCellRenderer } from './grid-components/VeltCellRenderer';
1818
import { Breadcrumb } from './ui-components/Breadcrumb';
19-
import { ViewToggle } from './ui-components/ViewToggle';
19+
import { ViewToggle, ViewType } from './ui-components/ViewToggle';
2020
import { Toolbar } from './ui-components/Toolbar';
2121
import { styles } from './styles';
2222
import { useTableState } from './hooks/useTableState';
2323

2424
export const TableComponent: React.FC = () => {
2525
const { client } = useVeltClient();
26+
const [activeView, setActiveView] = useState<ViewType>('day');
27+
2628
const {
2729
selectedCell,
2830
setSelectedCell,
@@ -39,6 +41,33 @@ export const TableComponent: React.FC = () => {
3941
setAlignment,
4042
} = useTableState();
4143

44+
// Handle view changes
45+
const handleViewChange = useCallback((view: ViewType) => {
46+
setActiveView(view);
47+
48+
// Update data based on view
49+
if (view === 'day') {
50+
setRowData(generateTableData());
51+
} else if (view === 'week') {
52+
setRowData(generateWeeklyTableData());
53+
} else if (view === 'month') {
54+
setRowData(generateMonthlyTableData());
55+
}
56+
57+
// Reset selection
58+
setSelectedCell(null);
59+
60+
// Reset sorting to date ascending
61+
if (gridApi) {
62+
gridApi.applyColumnState({
63+
state: [{ colId: 'date', sort: 'asc' }],
64+
defaultState: { sort: null },
65+
});
66+
setSortState({ colId: 'date', sort: 'asc' });
67+
setLocalSortState({ colId: 'date', sort: 'asc' });
68+
}
69+
}, [gridApi, setRowData, setSelectedCell, setSortState, setLocalSortState]);
70+
4271
// Initialize Velt
4372
useEffect(() => {
4473
if (client) {
@@ -93,8 +122,8 @@ export const TableComponent: React.FC = () => {
93122

94123
// Cell Renderer with Velt formatting
95124
const veltCellRenderer = useMemo(() => {
96-
return createVeltCellRenderer(cellFormatting);
97-
}, [cellFormatting]);
125+
return createVeltCellRenderer(cellFormatting, activeView);
126+
}, [cellFormatting, activeView]);
98127

99128
// Column Definitions
100129
const columnDefs = useMemo(() => [
@@ -255,10 +284,11 @@ export const TableComponent: React.FC = () => {
255284
popoverMode={true}
256285
shadowDom={false}
257286
textMode={false}
287+
groupMatchedComments={true}
258288
/>
259289

260290
<div style={styles.tableContainer}>
261-
<ViewToggle />
291+
<ViewToggle activeView={activeView} onViewChange={handleViewChange} />
262292

263293
<Toolbar
264294
toggleFormatting={toggleFormatting}

apps/react/tables/libraries/AgGrid/marketing-spend-demo/components/document/grid-components/RowNumberRenderer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const RowNumberRenderer = (props: any) => {
1313
color: 'rgba(255, 255, 255, 0.5)',
1414
letterSpacing: '0.12px'
1515
}}>
16-
{props.node.rowIndex + 2}
16+
{props.node.rowIndex + 1}
1717
</div>
1818
);
1919
};

apps/react/tables/libraries/AgGrid/marketing-spend-demo/components/document/grid-components/VeltCellRenderer.tsx

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import React from 'react';
22
import { CellFormatting } from '../types';
3-
import { getCellFormattingKey } from '../utils';
3+
import { getCellFormattingKey, getDateContext } from '../utils';
44

5-
export const createVeltCellRenderer = (cellFormatting: Record<string, CellFormatting>) => (props: any) => {
5+
type ViewType = 'day' | 'week' | 'month';
6+
7+
export const createVeltCellRenderer = (
8+
cellFormatting: Record<string, CellFormatting>,
9+
activeView: ViewType = 'day'
10+
) => (props: any) => {
611
const cellId = `cell-${props.data.id}-${props.colDef.field}`;
712
const cellKey = getCellFormattingKey(props.data.id, props.colDef.field);
813
const formatting = cellFormatting[cellKey] || {};
@@ -16,19 +21,50 @@ export const createVeltCellRenderer = (cellFormatting: Record<string, CellFormat
1621

1722
// Check if comment tool already exists
1823
let commentTool = props.eGridCell.querySelector('velt-comment-tool');
24+
25+
// Calculate context based on date and column
26+
const context = props.data.date && props.colDef.field !== 'date'
27+
? getDateContext(props.data.date, props.colDef.field, props.data.id, activeView)
28+
: null;
29+
1930
if (!commentTool) {
2031
// Create and append comment tool directly to cell
2132
commentTool = document.createElement('velt-comment-tool');
2233
commentTool.setAttribute('target-comment-element-id', cellId);
2334
commentTool.style.cssText = 'position: absolute; right: 4px; top: 50%; transform: translateY(-50%); z-index: 1;';
2435

36+
// Add context metadata for aggregation
37+
if (context) {
38+
commentTool.setAttribute('context', JSON.stringify(context));
39+
40+
// Enable partial matching for weekly and monthly views
41+
if (activeView === 'week' || activeView === 'month') {
42+
commentTool.setAttribute('context-options', JSON.stringify({ partialMatch: true }));
43+
}
44+
}
45+
2546
// Append to cell (outside ag-cell-wrapper)
2647
props.eGridCell.appendChild(commentTool);
2748
} else {
28-
// Update target-comment-element-id if it changed
49+
// Update attributes if they changed
2950
if (commentTool.getAttribute('target-comment-element-id') !== cellId) {
3051
commentTool.setAttribute('target-comment-element-id', cellId);
3152
}
53+
54+
if (context) {
55+
const currentContext = commentTool.getAttribute('context');
56+
const newContext = JSON.stringify(context);
57+
if (currentContext !== newContext) {
58+
commentTool.setAttribute('context', newContext);
59+
}
60+
61+
// Update context-options based on view
62+
if (activeView === 'week' || activeView === 'month') {
63+
commentTool.setAttribute('context-options', JSON.stringify({ partialMatch: true }));
64+
} else {
65+
commentTool.removeAttribute('context-options');
66+
}
67+
}
3268
}
3369
}
3470

@@ -41,7 +77,7 @@ export const createVeltCellRenderer = (cellFormatting: Record<string, CellFormat
4177
}
4278
}
4379
};
44-
}, [cellId, props.eGridCell]);
80+
}, [cellId, props.eGridCell, props.data.date, props.data.id, props.colDef.field, activeView]);
4581

4682
const textStyle: React.CSSProperties = {
4783
fontWeight: formatting.bold ? 'bold' : 'normal',

apps/react/tables/libraries/AgGrid/marketing-spend-demo/components/document/ui-components/ViewToggle.tsx

Lines changed: 44 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,34 @@
11
import React from 'react';
22

3-
export const ViewToggle: React.FC = () => {
3+
export type ViewType = 'day' | 'week' | 'month';
4+
5+
interface ViewToggleProps {
6+
activeView: ViewType;
7+
onViewChange: (view: ViewType) => void;
8+
}
9+
10+
export const ViewToggle: React.FC<ViewToggleProps> = ({ activeView, onViewChange }) => {
11+
const getButtonStyle = (isActive: boolean) => ({
12+
backgroundColor: isActive ? 'rgba(255, 255, 255, 0.08)' : 'transparent',
13+
border: 'none',
14+
borderRadius: '8px',
15+
padding: '4px 8px',
16+
cursor: 'pointer',
17+
display: 'flex',
18+
alignItems: 'center',
19+
justifyContent: 'center',
20+
});
21+
22+
const getTextStyle = (isActive: boolean) => ({
23+
fontFamily: 'Urbanist, sans-serif',
24+
fontSize: '13px',
25+
fontWeight: 400,
26+
lineHeight: '16px',
27+
color: isActive ? '#ffffff' : 'rgba(255, 255, 255, 0.52)',
28+
whiteSpace: 'pre' as const,
29+
letterSpacing: '0.13px',
30+
});
31+
432
return (
533
<div style={{
634
position: 'absolute',
@@ -12,65 +40,23 @@ export const ViewToggle: React.FC = () => {
1240
gap: '4px',
1341
zIndex: 10,
1442
}}>
15-
<button style={{
16-
backgroundColor: 'rgba(255, 255, 255, 0.08)',
17-
border: 'none',
18-
borderRadius: '8px',
19-
padding: '4px 8px',
20-
cursor: 'pointer',
21-
display: 'flex',
22-
alignItems: 'center',
23-
justifyContent: 'center',
24-
}}>
25-
<span style={{
26-
fontFamily: 'Urbanist, sans-serif',
27-
fontSize: '13px',
28-
fontWeight: 400,
29-
lineHeight: '16px',
30-
color: '#ffffff',
31-
whiteSpace: 'pre',
32-
letterSpacing: '0.13px',
33-
}}>Day View</span>
43+
<button
44+
onClick={() => onViewChange('day')}
45+
style={getButtonStyle(activeView === 'day')}
46+
>
47+
<span style={getTextStyle(activeView === 'day')}>Day View</span>
3448
</button>
35-
<button style={{
36-
backgroundColor: 'transparent',
37-
border: 'none',
38-
borderRadius: '8px',
39-
padding: '4px 8px',
40-
cursor: 'pointer',
41-
display: 'flex',
42-
alignItems: 'center',
43-
justifyContent: 'center',
44-
}}>
45-
<span style={{
46-
fontFamily: 'Urbanist, sans-serif',
47-
fontSize: '13px',
48-
fontWeight: 400,
49-
lineHeight: '16px',
50-
color: 'rgba(255, 255, 255, 0.52)',
51-
whiteSpace: 'pre',
52-
letterSpacing: '0.13px',
53-
}}>Weekly View</span>
49+
<button
50+
onClick={() => onViewChange('week')}
51+
style={getButtonStyle(activeView === 'week')}
52+
>
53+
<span style={getTextStyle(activeView === 'week')}>Weekly View</span>
5454
</button>
55-
<button style={{
56-
backgroundColor: 'transparent',
57-
border: 'none',
58-
borderRadius: '8px',
59-
padding: '4px 8px',
60-
cursor: 'pointer',
61-
display: 'flex',
62-
alignItems: 'center',
63-
justifyContent: 'center',
64-
}}>
65-
<span style={{
66-
fontFamily: 'Urbanist, sans-serif',
67-
fontSize: '13px',
68-
fontWeight: 400,
69-
lineHeight: '16px',
70-
color: 'rgba(255, 255, 255, 0.52)',
71-
whiteSpace: 'pre',
72-
letterSpacing: '0.13px',
73-
}}>Monthly View</span>
55+
<button
56+
onClick={() => onViewChange('month')}
57+
style={getButtonStyle(activeView === 'month')}
58+
>
59+
<span style={getTextStyle(activeView === 'month')}>Monthly View</span>
7460
</button>
7561
</div>
7662
);

0 commit comments

Comments
 (0)