react-weekly-planning 1.0.42 → 1.0.43
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/README.md
CHANGED
|
@@ -215,7 +215,7 @@ Use this hook within any component nested under the provider to access the task
|
|
|
215
215
|
| `getTask` | `(hash: string, taskId: string) => Task \| undefined` | Finds a specific task by ID. |
|
|
216
216
|
| `updateTask` | `(hash: string, taskId: string, updatedTask: Partial<Task>) => void` | Updates an existing task's properties. |
|
|
217
217
|
| `deleteTask` | `(hash: string, taskId: string) => void` | Removes a task from the store. |
|
|
218
|
-
| `isValidTask` | `(task: Task) => boolean` |
|
|
218
|
+
| `isValidTask` | `(task: Task) => boolean` | Verifies if a task has not yet expired. |
|
|
219
219
|
| `cleanExpiredTasks` | `() => void` | Removes all tasks that have passed their `taskExpiryDate`. |
|
|
220
220
|
| `cleanExpiredTasksByHash` | `(hash: string) => void` | Removes expired tasks within a specific hash bucket. |
|
|
221
221
|
| `hashScope` | `"week" \| "group" \| "day"` | The active hashing strategy. |
|
|
@@ -314,7 +314,7 @@ The library uses "hashes" to bucket tasks efficiently. When calling `getTasks(ha
|
|
|
314
314
|
|
|
315
315
|
- **Manual Rendering**: Use `getTasks(hash)` to retrieve only the tasks relevant to the current view.
|
|
316
316
|
- **CRUD Operations**: Use `addTask`, `updateTask`, and `deleteTask` to modify the store. The UI will re-render automatically thanks to the context.
|
|
317
|
-
- **Validation**: Use `isValidTask(task)` to verify if a task
|
|
317
|
+
- **Validation**: Use `isValidTask(task)` to verify if a task has not yet expired before displaying it, or rely on `cleanExpiredTasks()` to prune the store.
|
|
318
318
|
- **Performance**: Accessing tasks by hash is highly optimized. Avoid looping through the entire `tasks.buckets` manually if possible.
|
|
319
319
|
|
|
320
320
|
---
|
|
@@ -425,6 +425,33 @@ to create an organization that truly reflects you.
|
|
|
425
425
|
console.log(hashes.day); // "0/group-1/2"
|
|
426
426
|
```
|
|
427
427
|
|
|
428
|
+
### `calculateWeekDifference`
|
|
429
|
+
|
|
430
|
+
- **Description**: Calculates the week difference in days between a selected date and the current date, normalized to Sundays.
|
|
431
|
+
- **Parameters**:
|
|
432
|
+
- `dateSelectionnee` (Date): The date to compare.
|
|
433
|
+
- `timeZone` (string, optional): The timezone to use for the comparison.
|
|
434
|
+
- **Returns**: The difference in days (e.g., 0, 7, -7, 14, -14...).
|
|
435
|
+
|
|
436
|
+
**Example**:
|
|
437
|
+
```javascript
|
|
438
|
+
import { calculateWeekDifference } from "react-weekly-planning";
|
|
439
|
+
const diff = calculateWeekDifference(new Date());
|
|
440
|
+
console.log(diff); // Logs 0 if it's the current week
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### `getUniqueId`
|
|
444
|
+
|
|
445
|
+
- **Description**: Generates a unique identifier (UUID v4).
|
|
446
|
+
- **Returns**: A unique ID string.
|
|
447
|
+
|
|
448
|
+
**Example**:
|
|
449
|
+
```javascript
|
|
450
|
+
import { getUniqueId } from "react-weekly-planning";
|
|
451
|
+
const id = getUniqueId();
|
|
452
|
+
console.log(id); // Logs a unique UUID
|
|
453
|
+
```
|
|
454
|
+
|
|
428
455
|
### `getNewTaskForDropOrPaste`
|
|
429
456
|
|
|
430
457
|
- **Description**: Utility function to generate a new task correctly positioned when dropping or pasting it in a custom calendar context. It reads the dragged task information from the browser's `sessionStorage` and calculates the new start/end dates based on the drop target.
|
|
@@ -462,4 +489,3 @@ to create an organization that truly reflects you.
|
|
|
462
489
|
```
|
|
463
490
|
|
|
464
491
|
---
|
|
465
|
-
|
|
@@ -5,7 +5,7 @@ import { useIntersectionObserver } from "../hooks/useIntersectionObserver";
|
|
|
5
5
|
import GroupContainer from "./GroupContainer";
|
|
6
6
|
import TaskVirtual from "./TaskContainer/TaskVirtual";
|
|
7
7
|
import AddTask from "./AddTask";
|
|
8
|
-
import { getHash, getNewTaskForDropOrPaste,
|
|
8
|
+
import { getHash, getNewTaskForDropOrPaste, getUniqueId, updateOffsetWithDateCalendar, } from "../lib/utils";
|
|
9
9
|
import { groupTdStyle } from "../lib/slyles";
|
|
10
10
|
const VirtualGroupRow = ({ group, i, props, getTasks, isValidTask, addTask, deleteTask, getTask, dailyHours, hashScope, tasks, sumHoursByGroupsCount }) => {
|
|
11
11
|
const ref = useRef(null);
|
|
@@ -38,7 +38,7 @@ const VirtualGroupRow = ({ group, i, props, getTasks, isValidTask, addTask, dele
|
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
deleteTask(dropInfo.newTask.draghash, dropInfo.newTask.id);
|
|
41
|
-
addTask(Object.assign(Object.assign({}, dropInfo.newTask), { id:
|
|
41
|
+
addTask(Object.assign(Object.assign({}, dropInfo.newTask), { id: getUniqueId() }));
|
|
42
42
|
}, id: `col-${group.id}day-i`, className: `dayCol ${props.dayColsClassName}`, style: props.dayColsStyle, children: _jsxs("div", { style: {
|
|
43
43
|
display: "flex",
|
|
44
44
|
width: "100%",
|
|
@@ -4,7 +4,7 @@ import { useIntersectionObserver } from "../hooks/useIntersectionObserver";
|
|
|
4
4
|
import GroupContainer from "./GroupContainer";
|
|
5
5
|
import TaskVirtual from "./TaskContainer/TaskVirtual";
|
|
6
6
|
import AddTask from "./AddTask";
|
|
7
|
-
import { getHash, getNewTaskForDropOrPaste,
|
|
7
|
+
import { getHash, getNewTaskForDropOrPaste, getUniqueId, updateOffsetWithDateCalendar, } from "../lib/utils";
|
|
8
8
|
const VirtualGroupRowDay = ({ group, i, props, getTasks, isValidTask, addTask, deleteTask, updateTask, getTask, dailyHours, dayOffset, hashScope, tasks, }) => {
|
|
9
9
|
const ref = useRef(null);
|
|
10
10
|
const entry = useIntersectionObserver(ref, {
|
|
@@ -26,7 +26,7 @@ const VirtualGroupRowDay = ({ group, i, props, getTasks, isValidTask, addTask, d
|
|
|
26
26
|
if (!dropInfo)
|
|
27
27
|
return;
|
|
28
28
|
if (props.drop === "copy") {
|
|
29
|
-
addTask(Object.assign(Object.assign({}, dropInfo.newTask), { id:
|
|
29
|
+
addTask(Object.assign(Object.assign({}, dropInfo.newTask), { id: getUniqueId() }));
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
updateTask(hash[hashScope], dropInfo.newTask.id, dropInfo.newTask);
|
|
@@ -1,167 +1,167 @@
|
|
|
1
1
|
.addPlanStyle {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
cursor: pointer;
|
|
3
|
+
display: flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
flex: 1;
|
|
7
|
+
background-color: #f2f8fb;
|
|
8
|
+
opacity: 0;
|
|
9
|
+
border-radius: 5px;
|
|
10
|
+
color: #0f5173;
|
|
11
|
+
transition: background-color 0.3s, opacity 0.3s;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.addPlanStyle:hover {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
background-color: #c6dbe159;
|
|
16
|
+
opacity: 1;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
.taskContainer {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
20
|
+
box-shadow: 0px 7px 18px 0px rgba(15, 105, 115, 0.03),
|
|
21
|
+
0px 6px 10px 0px rgba(15, 105, 115, 0.04),
|
|
22
|
+
0px 3px 5px 0px rgba(15, 105, 115, 0.05);
|
|
23
|
+
display: flex;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
column-gap: 10px;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
height: auto;
|
|
28
|
+
border-left: 5px solid #457993;
|
|
29
|
+
background-color: #f4ffff;
|
|
30
|
+
color: #457993;
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
border-radius: 5px;
|
|
33
|
+
margin-bottom: 5px;
|
|
34
|
+
font-size: 13px;
|
|
35
|
+
overflow: auto;
|
|
36
|
+
padding: 2px;
|
|
37
|
+
z-index: 10;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.tasklabel {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
color: #55585d;
|
|
42
|
+
font-size: 12px;
|
|
43
|
+
line-height: 16px;
|
|
44
|
+
font-weight: 400;
|
|
45
|
+
margin-left: 5px;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
.taskhour {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
font-size: 12px;
|
|
50
|
+
line-height: 16px;
|
|
51
|
+
font-weight: 600;
|
|
52
|
+
margin-left: 5px;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
.planningCalendar {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
width: 100%;
|
|
57
|
+
border-radius: 0.5rem;
|
|
58
|
+
z-index: 10;
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
border: 0.74px solid rgba(198, 219, 225, 0.68);
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
background-color: white;
|
|
64
64
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
.planningCalendarHeader {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
display: flex;
|
|
69
|
+
width: 100%;
|
|
70
|
+
z-index: 200;
|
|
71
|
+
border-bottom: 1.5px solid #0f52737e;
|
|
72
|
+
background-color: #fff;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
.planningCalendarRow {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
display: flex;
|
|
77
|
+
width: 100%;
|
|
78
|
+
border-bottom: 1.5px solid #0f52737e;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
.planningCalendarRow:last-child {
|
|
82
|
-
|
|
82
|
+
border-bottom: none;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
.planningCalendar .dayTh,
|
|
86
86
|
.planningCalendar .groupCol {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
flex: 0 0 150px;
|
|
88
|
+
color: #0f5173;
|
|
89
|
+
padding-left: 5px;
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
.planningCalendar .dayCol {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
flex: 1;
|
|
96
|
+
border-left: 0.74px solid rgba(198, 219, 225, 0.68);
|
|
97
|
+
min-width: 0;
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-direction: column;
|
|
100
|
+
justify-content: center;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
.planningCalendar .totalTh,
|
|
104
104
|
.planningCalendar .totalCol {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
flex: 0 0 50px;
|
|
106
|
+
color: #0f5173;
|
|
107
|
+
text-align: right;
|
|
108
|
+
padding-right: 5px;
|
|
109
|
+
border-left: 0.74px solid rgba(198, 219, 225, 0.68);
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: flex-end;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
.CalendarTableForDay {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
display: flex;
|
|
117
|
+
gap: 10px;
|
|
118
|
+
width: 100vw;
|
|
119
|
+
height: auto;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
.CalendarTableForDayTasksContainer {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
flex: 1;
|
|
124
|
+
display: flex;
|
|
125
|
+
flex-direction: column;
|
|
126
|
+
height: auto;
|
|
127
|
+
padding: 10px;
|
|
128
|
+
position: relative;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
.CalendarTableForDayRow {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
display: flex !important;
|
|
133
|
+
flex-direction: row !important;
|
|
134
|
+
gap: 15px;
|
|
135
|
+
align-items: flex-start;
|
|
136
|
+
padding: 15px !important;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
.CalendarTableForDayGroupTasks {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
flex: 1;
|
|
141
|
+
display: grid;
|
|
142
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
143
|
+
gap: 10px;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
.CalendarTableForDayGroupTasks .taskContainer,
|
|
147
147
|
.CalendarTableForDayGroupTasks .addPlanStyle {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
margin-bottom: 0px;
|
|
149
|
+
height: 100%;
|
|
150
|
+
min-height: 80px;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
.calendarForWeek {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
display: flex;
|
|
155
|
+
width: 100%;
|
|
156
|
+
flex: 1;
|
|
157
|
+
overflow: auto;
|
|
158
|
+
position: relative;
|
|
159
159
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
.calendarForWeek-container {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
display: flex;
|
|
164
|
+
flex-direction: column;
|
|
165
|
+
width: 100%;
|
|
166
|
+
height: 100%;
|
|
167
167
|
}
|
package/dist/lib/utils.js
CHANGED
|
@@ -388,7 +388,7 @@ function recurring(ecartDay, task, timeZone) {
|
|
|
388
388
|
newTask.taskExpiryDate = new Date(newTask.taskExpiryDate.getTime() + ecartDay);
|
|
389
389
|
newTask.taskDate = new Date(newTask.taskStart);
|
|
390
390
|
newTask.dayIndex = getArbitraryDateInTimeZone(newTask.taskDate, timeZone).getDay();
|
|
391
|
-
newTask.id =
|
|
391
|
+
newTask.id = getUniqueId();
|
|
392
392
|
return newTask;
|
|
393
393
|
}
|
|
394
394
|
export function recurringTasks(allTasks, task, recurrenceType, occurrences, timeZone) {
|
|
@@ -539,7 +539,7 @@ function updateTaskStartTimeAnEndTime(start, end, calendarOffset, dayIndex, task
|
|
|
539
539
|
const endTime = end + diffDay * DAY_IN_MILLISECONDS;
|
|
540
540
|
return { startTime, endTime };
|
|
541
541
|
}
|
|
542
|
-
export function
|
|
542
|
+
export function getUniqueId() {
|
|
543
543
|
const uid = uuidv4();
|
|
544
544
|
return uid;
|
|
545
545
|
}
|
|
@@ -552,7 +552,7 @@ export function pastTasks(dayInfo, groupId, tasks, taskExpiryDate, timeZone) {
|
|
|
552
552
|
const newTaskStartAndEnd = updateTaskStartTimeAnEndTime(copiedTasktaskStart, copiedTasktaskEnd, updateOffsetWithDateCalendar(dayInfo.day, timeZone), dayInfo.positionDay, copiedTaskDayIndex, timeZone);
|
|
553
553
|
if (!checkDuplicates(previousTasks, newTaskStartAndEnd.startTime, newTaskStartAndEnd.endTime, groupId)) {
|
|
554
554
|
const newTaskDate = new Date(newTaskStartAndEnd.startTime);
|
|
555
|
-
const newTaskId = `${
|
|
555
|
+
const newTaskId = `${getUniqueId()}`;
|
|
556
556
|
const newTask = Object.assign({ taskStart: newTaskStartAndEnd.startTime, taskEnd: newTaskStartAndEnd.endTime, dayIndex: dayInfo.positionDay, id: newTaskId, taskDate: newTaskDate, groupId: groupId, taskExpiryDate: taskExpiryDate }, rest);
|
|
557
557
|
return [...previousTasks, newTask];
|
|
558
558
|
}
|
|
@@ -591,7 +591,7 @@ export function duplicateTasksForPeriod(periodStart, periodEnd, calendarOffset,
|
|
|
591
591
|
const newTaskEnd = taskEnd + ecartDay * DAY_IN_MILLISECONDS;
|
|
592
592
|
const newTaskDate = new Date(taskDate.getTime() + ecartDay * DAY_IN_MILLISECONDS);
|
|
593
593
|
if (!checkDuplicates(allTasks, newTaskStart, newTaskEnd, rest.groupId)) {
|
|
594
|
-
const newTask = Object.assign(Object.assign({}, rest), { taskDate: newTaskDate, taskStart: newTaskStart, taskEnd: newTaskEnd, id:
|
|
594
|
+
const newTask = Object.assign(Object.assign({}, rest), { taskDate: newTaskDate, taskStart: newTaskStart, taskEnd: newTaskEnd, id: getUniqueId() });
|
|
595
595
|
tasks.push(Object.assign(Object.assign({}, newTask), { offset: newOffset }));
|
|
596
596
|
}
|
|
597
597
|
});
|
|
@@ -613,7 +613,7 @@ export function duplicateTaskForPeriod(periodStart, periodEnd, task, ecartDay, g
|
|
|
613
613
|
const newTaskEnd = taskEnd + ecartDay * DAY_IN_MILLISECONDS;
|
|
614
614
|
const newTaskDate = new Date(taskDate.getTime() + ecartDay * DAY_IN_MILLISECONDS);
|
|
615
615
|
if (!checkDuplicates(allTasks, newTaskStart, newTaskEnd, rest.groupId)) {
|
|
616
|
-
const newTask = Object.assign(Object.assign({}, rest), { taskDate: newTaskDate, taskStart: newTaskStart, taskEnd: newTaskEnd, id:
|
|
616
|
+
const newTask = Object.assign(Object.assign({}, rest), { taskDate: newTaskDate, taskStart: newTaskStart, taskEnd: newTaskEnd, id: getUniqueId(), groupId: groupId ? groupId : currentTaskGroupId, taskExpiryDate: taskExpiryDate });
|
|
617
617
|
allTasks.push(Object.assign(Object.assign({}, newTask), { offset: newOffset }));
|
|
618
618
|
}
|
|
619
619
|
}
|
|
@@ -76,7 +76,7 @@ export declare function selectTask(task: TaskFeildsType): void;
|
|
|
76
76
|
export declare function deSelectTask(task: TaskFeildsType): void;
|
|
77
77
|
export declare function copyTasks(task: TaskFeildsType): void;
|
|
78
78
|
export declare function cutTasks(task: TaskFeildsType, tasks: TaskFeildsType[]): TaskFeildsType[];
|
|
79
|
-
export declare function
|
|
79
|
+
export declare function getUniqueId(): string;
|
|
80
80
|
export declare function pastTasks(dayInfo: dayInfoType, groupId: string, tasks: TaskFeildsType[], taskExpiryDate?: Date, timeZone?: TimeZone): TaskFeildsType[] | undefined;
|
|
81
81
|
export declare function updateTask(tasks: TaskFeildsType[], taskId: string, newtask: TaskFeildsType): TaskFeildsType[];
|
|
82
82
|
export declare function duplicateTasksForPeriod(periodStart: Date, periodEnd: Date, calendarOffset: number, allTasks: TasksType): TasksType;
|