react-weekly-planning 1.0.37 → 1.0.39
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 +219 -98
- package/package.json +49 -1
- package/dist/components/AddTask/index.js +0 -17
- package/dist/components/CalendarForWeek.js +0 -49
- package/dist/components/CalendarForday.js +0 -33
- package/dist/components/DayContainer/index.js +0 -15
- package/dist/components/GroupContainer/index.js +0 -15
- package/dist/components/GroupsHeadContainer/index.js +0 -9
- package/dist/components/SumHoursContainer/index.js +0 -16
- package/dist/components/SumHoursHead/index.js +0 -9
- package/dist/components/TaskContainer/index.js +0 -35
- package/dist/components/TaskList/index.js +0 -4
- package/dist/components/index.js +0 -69
- package/dist/components/style.css +0 -123
- package/dist/contexts/CalendarContext.js +0 -12
- package/dist/definitions/index.js +0 -1
- package/dist/hooks/useCalendarDateState.js +0 -19
- package/dist/index.js +0 -7
- package/dist/lib/slyles.js +0 -21
- package/dist/lib/utils.js +0 -650
- package/dist/types/components/AddTask/index.d.ts +0 -3
- package/dist/types/components/CalendarForWeek.d.ts +0 -4
- package/dist/types/components/CalendarForday.d.ts +0 -5
- package/dist/types/components/DayContainer/index.d.ts +0 -3
- package/dist/types/components/GroupContainer/index.d.ts +0 -3
- package/dist/types/components/GroupsHeadContainer/index.d.ts +0 -3
- package/dist/types/components/SumHoursContainer/index.d.ts +0 -3
- package/dist/types/components/SumHoursHead/index.d.ts +0 -3
- package/dist/types/components/TaskContainer/index.d.ts +0 -3
- package/dist/types/components/TaskList/index.d.ts +0 -5
- package/dist/types/components/index.d.ts +0 -65
- package/dist/types/contexts/CalendarContext.d.ts +0 -15
- package/dist/types/definitions/index.d.ts +0 -395
- package/dist/types/hooks/useCalendarDateState.d.ts +0 -6
- package/dist/types/index.d.ts +0 -3
- package/dist/types/lib/slyles.d.ts +0 -4
- package/dist/types/lib/utils.d.ts +0 -86
package/README.md
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`react-weekly-planning` provides a React component for weekly planning. Easily set up and manage a weekly schedule with customizable tasks, groups and views.
|
|
6
|
+
## 🚀 react-weekly-planning, a flexible and customizable package for your productivity projects.
|
|
9
7
|
|
|
10
8
|
## Screenshot
|
|
11
9
|
|
|
@@ -55,16 +53,6 @@ It is possible to use either Weekoffset or Date, or even both simultaneously.
|
|
|
55
53
|
<Calendar date={currentDate} ... />
|
|
56
54
|
```
|
|
57
55
|
|
|
58
|
-
#### `timeZone`
|
|
59
|
-
|
|
60
|
-
- **Description**: This prop sets the timezone to be used by the calendar for all date and time calculations.
|
|
61
|
-
- **Type**: `TimeZone` (e.g., `"America/New_York"`, `"Europe/Paris"`, etc.)
|
|
62
|
-
- **Use Case**: Use this prop to align the calendar's display and event calculations to a specific global timezone instead of relying on the user's local browser timezone. This ensures consistency across different geographical locations.
|
|
63
|
-
|
|
64
|
-
**Example**:
|
|
65
|
-
```jsx
|
|
66
|
-
<Calendar timeZone="Europe/Paris" ... />
|
|
67
|
-
```
|
|
68
56
|
|
|
69
57
|
#### `scope`
|
|
70
58
|
|
|
@@ -88,94 +76,40 @@ It is possible to use either Weekoffset or Date, or even both simultaneously.
|
|
|
88
76
|
<Calendar scope="day" dayOffset={2} ... />
|
|
89
77
|
```
|
|
90
78
|
|
|
91
|
-
#### `tasks`
|
|
92
|
-
|
|
93
|
-
- **Description**: This prop is an array of tasks to be displayed in the calendar.
|
|
94
|
-
- **Type**: `TasksType`
|
|
95
|
-
- **Use Case**: Use this prop to manage and display tasks in the calendar. Each task should contain details such as start time, end time, description, date, group ID, and day index.
|
|
96
|
-
taskId, taskStart taskEnd, task, taskDate, groupId, dayIndex
|
|
97
|
-
**Example**:
|
|
98
|
-
```jsx
|
|
99
|
-
const tasks = [
|
|
100
|
-
{ taskId: '1', taskStart:'Time in milliseconde', taskEnd:'Time in milliseconde', task: 'Task 1', taskDate: new Date(), groupId: '1', dayIndex: 0, ... }
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
<Calendar tasks={tasks} ... />
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
- **Supplementary property** : If you want the tasks to be saved up to a date of your choice you can define the `taskExpiryDate` property. It's an idea of [Patrick Aimé](https://www.linkedin.com/in/patrick-aime?utm_source=share&utm_campaign=share_via&utm_content=profile&utm_medium=android_app).
|
|
107
|
-
|
|
108
|
-
- **Example**:Here's how to create a task that will expire in a day.
|
|
109
|
-
```jsx
|
|
110
|
-
const tasks = [
|
|
111
|
-
{ taskId: '1', taskStart:'Time in milliseconde', taskEnd:'Time in milliseconde', task: 'Task 1', taskDate: new Date(), groupId: '1', dayIndex: 0,taskExpiryDate:new Date(Date.now() + 86400000) ... }
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
<Calendar tasks={tasks} ... />
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
`taskExpiryDate` is used with `getSavedTasks()` To obtain the saved tasks.
|
|
118
|
-
|
|
119
|
-
**Example**:
|
|
120
|
-
```jsx
|
|
121
|
-
import {getSavedTasks} from "react-weekly-planning";
|
|
122
|
-
const [tasks,setTasks]=useState([])
|
|
123
|
-
|
|
124
|
-
useEffect(()=>{
|
|
125
|
-
setTasks(getSavedTasks())
|
|
126
|
-
},[])
|
|
127
|
-
|
|
128
|
-
<Calendar tasks={tasks} ... />
|
|
129
|
-
```
|
|
130
79
|
|
|
131
80
|
---
|
|
132
81
|
|
|
133
82
|
## Full Example for Beginners
|
|
134
83
|
|
|
135
|
-
Here is a complete, minimal example showing how to set up the `Calendar` with
|
|
84
|
+
Here is a complete, minimal example showing how to set up the `Calendar` with the `CalendarTaskContextProvider`.
|
|
136
85
|
|
|
137
86
|
```tsx
|
|
138
87
|
import React, { useState } from "react";
|
|
139
|
-
import
|
|
140
|
-
|
|
88
|
+
import {
|
|
89
|
+
Calendar,
|
|
90
|
+
CalendarTaskContextProvider
|
|
91
|
+
} from "react-pweekly-planning";
|
|
141
92
|
|
|
142
93
|
const App = () => {
|
|
143
94
|
const [date] = useState(new Date());
|
|
144
95
|
|
|
145
|
-
// Define groups (e.g., resources, team members, or projects)
|
|
146
96
|
const groups = [
|
|
147
97
|
{ id: "1", label: "Developer A" },
|
|
148
98
|
{ id: "2", label: "Developer B" }
|
|
149
99
|
];
|
|
150
100
|
|
|
151
|
-
// Create start and end times in milliseconds
|
|
152
|
-
const todayAt10 = new Date().setHours(10, 0, 0, 0);
|
|
153
|
-
const todayAt12 = new Date().setHours(12, 0, 0, 0);
|
|
154
|
-
|
|
155
|
-
// Define your tasks
|
|
156
|
-
const tasks = [
|
|
157
|
-
{
|
|
158
|
-
taskId: "t1",
|
|
159
|
-
groupId: "1", // Belongs to "Developer A"
|
|
160
|
-
taskStart: todayAt10,
|
|
161
|
-
taskEnd: todayAt12,
|
|
162
|
-
taskDate: new Date(),
|
|
163
|
-
dayIndex: new Date().getDay(), // Matches the task's day of week
|
|
164
|
-
taskSummary: "Code Review"
|
|
165
|
-
}
|
|
166
|
-
];
|
|
167
|
-
|
|
168
101
|
return (
|
|
169
|
-
<
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
102
|
+
<CalendarTaskContextProvider hashScope="week">
|
|
103
|
+
<div style={{ padding: "20px" }}>
|
|
104
|
+
<h1>My Weekly Planner</h1>
|
|
105
|
+
<Calendar
|
|
106
|
+
date={date}
|
|
107
|
+
weekOffset={0}
|
|
108
|
+
groups={groups}
|
|
109
|
+
scope="week"
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
112
|
+
</CalendarTaskContextProvider>
|
|
179
113
|
);
|
|
180
114
|
};
|
|
181
115
|
|
|
@@ -198,7 +132,6 @@ Props for the Calendar component.
|
|
|
198
132
|
| `className` | string | Additional class names for the calendar component. |
|
|
199
133
|
| `style` | React.CSSProperties \| undefined | Additional styles for the calendar component. |
|
|
200
134
|
| `date` | Date | The current date to display in the calendar. |
|
|
201
|
-
| `timeZone` | TimeZone | The timezone to use for displaying and manipulating the calendar dates. |
|
|
202
135
|
| `groupRender` | ({ currentGroup }: { currentGroup: GroupFeildsType }) => React.ReactNode | Custom render function for a group. |
|
|
203
136
|
| `dayRender` | ({ dayIndex, day, dayOfTheMonth, dayMonth, dayYear }: { dayIndex: number; day: string; dayOfTheMonth: number; dayMonth: string; dayYear: number; }) => React.ReactNode | Custom render function for a day. |
|
|
204
137
|
| `taskRender` | ({ currentTask, handleDragTask }: { currentTask: TaskFeildsType}) => React.ReactNode | Custom render function for a task. |
|
|
@@ -224,7 +157,6 @@ Props for the Calendar component.
|
|
|
224
157
|
| `sumHoursHeadClassName` | string | Additional class names for the sum hours header. |
|
|
225
158
|
| `handleAddTask` | handleAddTask?: (currentGroup: GroupFeildsType, dayInfo: dayInfoType) => void; | Handler function for adding a new task. |
|
|
226
159
|
| `addTaskRender` | addTaskRender?: ({currentGroup,dayInfo}:{currentGroup: GroupFeildsType;dayInfo: dayInfoType}) => React.ReactNode;| Custom render function for adding a task. |
|
|
227
|
-
| `tasks` | TasksType | Array of tasks to be displayed in the calendar. |
|
|
228
160
|
| `handleDragTask` | (event: React.DragEvent<HTMLDivElement>, currentTask: TaskFeildsType) => void | Handler function for dragging a task. |
|
|
229
161
|
| `handleDropTask` | (event: React.DragEvent<HTMLTableDataCellElement>, taskStart: number, taskEnd: number, taskDate: Date, groupId: string, dayIndex: number, newTask: TaskFeildsType, newTasks: TasksType) => void | Handler function for dropping a task. |
|
|
230
162
|
| `handleDragTaskEnd` | (event: React.DragEvent<HTMLDivElement>) => void | Handler function for ending the drag of a task. |
|
|
@@ -233,24 +165,202 @@ Props for the Calendar component.
|
|
|
233
165
|
| `sumHoursHeadRender` | () => React.ReactNode | Custom render function for the sum of hours header. |
|
|
234
166
|
| `handleClickTask` | (currentTask: TaskFeildsType) => void | Handler function for clicking a task. |
|
|
235
167
|
| `handleClickGroup` | (currentGroup: GroupFeildsType) => void | Handler function for clicking a group. |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### ⚡ A modular approach
|
|
172
|
+
|
|
173
|
+
This package is based on a simple principle:
|
|
174
|
+
👉 **use only what you need.**
|
|
175
|
+
|
|
176
|
+
Each feature is independent:
|
|
177
|
+
|
|
178
|
+
* 📅 calendar
|
|
179
|
+
* ⏱ planning logic
|
|
180
|
+
* 📊 data management
|
|
181
|
+
* 🧩 custom extensions
|
|
182
|
+
|
|
183
|
+
Use everything… or only a part.
|
|
184
|
+
**The choice is yours.**
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Task Management (`CalendarTaskContext`)
|
|
189
|
+
|
|
190
|
+
The `CalendarTaskContext` provides a powerful way to manage tasks globally or within specific sections of your app. It handles indexing, caching, and expiration automatically.
|
|
191
|
+
|
|
192
|
+
### `CalendarTaskContextProvider`
|
|
193
|
+
|
|
194
|
+
Wrap your application (or a specific branch) with this provider to enable task management features.
|
|
195
|
+
|
|
196
|
+
| Prop | Type | Description |
|
|
197
|
+
|------|------|-------------|
|
|
198
|
+
| `hashScope` | `"week" \| "group" \| "day"` | Defines how tasks are bucketed and cached. |
|
|
199
|
+
| `children` | `React.ReactNode` | Your application components. |
|
|
200
|
+
|
|
201
|
+
> [!NOTE]
|
|
202
|
+
> The `hashScope` is **optional** for the provider and defaults to `"week"`. It is primarily used for custom calendar implementations. When using the standard `<Calendar />` component, it internally wraps itself in a provider with `hashScope="week"`, meaning you don't need to provide one unless you are building a custom UI.
|
|
203
|
+
|
|
204
|
+
### `useCalendarTaskContext()`
|
|
205
|
+
|
|
206
|
+
Use this hook within any component nested under the provider to access the task store and management methods.
|
|
207
|
+
|
|
208
|
+
#### Properties and Methods
|
|
209
|
+
|
|
210
|
+
| Name | Type | Description |
|
|
211
|
+
|------|------|-------------|
|
|
212
|
+
| `tasks` | `TasksStore` | The current state of all tasks, organized by buckets. |
|
|
213
|
+
| `addTask` | `(task: Task) => void` | Adds a new task. |
|
|
214
|
+
| `getTasks` | `(hash: string) => Task[]` | Retrieves all tasks for a given hash (e.g., a specific week key). |
|
|
215
|
+
| `getTask` | `(hash: string, taskId: string) => Task \| undefined` | Finds a specific task by ID. |
|
|
216
|
+
| `updateTask` | `(hash: string, taskId: string, updatedTask: Partial<Task>) => void` | Updates an existing task's properties. |
|
|
217
|
+
| `deleteTask` | `(hash: string, taskId: string) => void` | Removes a task from the store. |
|
|
218
|
+
| `isValidTask` | `(task: Task) => boolean` | Checks if a task object has all required fields. |
|
|
219
|
+
| `cleanExpiredTasks` | `() => void` | Removes all tasks that have passed their `taskExpiryDate`. |
|
|
220
|
+
| `cleanExpiredTasksByHash` | `(hash: string) => void` | Removes expired tasks within a specific hash bucket. |
|
|
221
|
+
| `hashScope` | `"week" \| "group" \| "day"` | The active hashing strategy. |
|
|
222
|
+
|
|
223
|
+
#### Example: Adding a Task
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
const TaskAdder = () => {
|
|
227
|
+
const { addTask } = useCalendarTaskContext();
|
|
228
|
+
|
|
229
|
+
const handleAdd = () => {
|
|
230
|
+
addTask({
|
|
231
|
+
taskId: "123",
|
|
232
|
+
groupId: "1",
|
|
233
|
+
taskStart: Date.now(),
|
|
234
|
+
taskEnd: Date.now() + 3600000,
|
|
235
|
+
taskDate: new Date(),
|
|
236
|
+
dayIndex: new Date().getDay(),
|
|
237
|
+
taskSummary: "New Task"
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
return <button onClick={handleAdd}>Quick Add Task</button>;
|
|
242
|
+
};
|
|
243
|
+
```
|
|
244
|
+
|
|
236
245
|
---
|
|
237
246
|
|
|
247
|
+
## Custom Calendar Implementation (Modular Design)
|
|
248
|
+
|
|
249
|
+
For advanced users who want to build their own calendar UI from scratch (without using the `<Calendar />` component), the `CalendarTaskContext` provides all the necessary state and logic. This allows you to create highly personalized designs while leveraging the library's optimized task management.
|
|
250
|
+
|
|
251
|
+
### 1. Basic Setup
|
|
252
|
+
|
|
253
|
+
To build a custom calendar, wrap your components in `CalendarTaskContextProvider` and use `useCalendarTaskContext` to access the data and methods.
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
import React from 'react';
|
|
257
|
+
import {
|
|
258
|
+
CalendarTaskContextProvider,
|
|
259
|
+
useCalendarTaskContext,
|
|
260
|
+
updateOffsetWithDateCalendar,
|
|
261
|
+
getHash
|
|
262
|
+
} from 'react-weekly-planning';
|
|
263
|
+
|
|
264
|
+
const MyCustomCalendar = () => {
|
|
265
|
+
const { getTasks, addTask } = useCalendarTaskContext();
|
|
266
|
+
const currentDate = new Date();
|
|
267
|
+
|
|
268
|
+
// 1. Calculate the week offset for the desired date
|
|
269
|
+
const offset = updateOffsetWithDateCalendar(currentDate);
|
|
270
|
+
|
|
271
|
+
// 2. Generate the hash for the current view (e.g., 'week' scope)
|
|
272
|
+
const hash = getHash(offset).week;
|
|
273
|
+
|
|
274
|
+
// 3. Retrieve tasks for that hash
|
|
275
|
+
const tasks = getTasks(hash);
|
|
276
|
+
|
|
277
|
+
return (
|
|
278
|
+
<div className="my-custom-design">
|
|
279
|
+
<h2>My Weekly View</h2>
|
|
280
|
+
{tasks.length === 0 && <p>No tasks for this week.</p>}
|
|
281
|
+
{tasks.map(task => (
|
|
282
|
+
<div key={task.id} className="custom-task-card">
|
|
283
|
+
<h4>{task.taskSummary}</h4>
|
|
284
|
+
<p>
|
|
285
|
+
{new Date(task.taskStart).toLocaleTimeString()} -
|
|
286
|
+
{new Date(task.taskEnd).toLocaleTimeString()}
|
|
287
|
+
</p>
|
|
288
|
+
</div>
|
|
289
|
+
))}
|
|
290
|
+
</div>
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const App = () => (
|
|
295
|
+
<CalendarTaskContextProvider hashScope="week">
|
|
296
|
+
<MyCustomCalendar />
|
|
297
|
+
</CalendarTaskContextProvider>
|
|
298
|
+
);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### 2. Default Behavior of `<Calendar />`
|
|
302
|
+
|
|
303
|
+
It's important to note that the main `<Calendar />` component uses the `"week"` hash scope by default. If you use the standard component, you are implicitly using this scope. Explicitly defining a `hashScope` on the `CalendarTaskContextProvider` is only necessary when you want to change how tasks are indexed or when building a fully custom UI as shown above.
|
|
304
|
+
|
|
305
|
+
### 3. Understanding Hashes and Scopes
|
|
306
|
+
|
|
307
|
+
The library uses "hashes" to bucket tasks efficiently. When calling `getTasks(hash)`, `updateTask(hash, ...)` or `deleteTask(hash, ...)`, you must provide the hash that matches your `hashScope`:
|
|
308
|
+
|
|
309
|
+
- **Scope `"week"`**: Use `getHash(offset).week`.
|
|
310
|
+
- **Scope `"group"`**: Use `getHash(offset, groupId).group`.
|
|
311
|
+
- **Scope `"day"`**: Use `getHash(offset, groupId, dayIndex).day`.
|
|
312
|
+
|
|
313
|
+
### 4. Best Practices for Custom Designs
|
|
314
|
+
|
|
315
|
+
- **Manual Rendering**: Use `getTasks(hash)` to retrieve only the tasks relevant to the current view.
|
|
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 is expired before displaying it, or rely on `cleanExpiredTasks()` to prune the store.
|
|
318
|
+
- **Performance**: Accessing tasks by hash is highly optimized. Avoid looping through the entire `tasks.buckets` manually if possible.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### 🧠 Total flexibility
|
|
323
|
+
|
|
324
|
+
Whether you want:
|
|
325
|
+
|
|
326
|
+
* a simple planner
|
|
327
|
+
* a complete productivity system
|
|
328
|
+
* or a fully customized solution
|
|
329
|
+
|
|
330
|
+
This package allows you to:
|
|
331
|
+
|
|
332
|
+
* integrate only useful components
|
|
333
|
+
* easily modify behaviors
|
|
334
|
+
* build your own logic
|
|
335
|
+
|
|
336
|
+
👉 **No constraints. No imposed framework.**
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
### 💡 Designed for builders
|
|
341
|
+
|
|
342
|
+
This isn't just a tool.
|
|
343
|
+
It's a foundation.
|
|
344
|
+
|
|
345
|
+
A system you can shape, extend, and control —
|
|
346
|
+
to create an organization that truly reflects you.
|
|
347
|
+
|
|
348
|
+
**Because performance starts with the freedom to build.**
|
|
349
|
+
|
|
238
350
|
---
|
|
239
351
|
|
|
240
352
|
## Additional Functions
|
|
241
353
|
|
|
242
354
|
### `getCalendarDate`
|
|
243
355
|
|
|
244
|
-
- **Description**: Returns the current date
|
|
245
|
-
- **
|
|
246
|
-
- `timeZone` (TimeZone, optional): The timezone to use for the date calculation.
|
|
247
|
-
- **Returns**: A `Date` object representing the current time in the specified timezone (or local time if omitted).
|
|
356
|
+
- **Description**: Returns the current date.
|
|
357
|
+
- **Returns**: A `Date` object representing the current time.
|
|
248
358
|
|
|
249
359
|
**Example**:
|
|
250
360
|
```javascript
|
|
251
361
|
import { getCalendarDate } from "react-weekly-planning";
|
|
252
|
-
const now = getCalendarDate(
|
|
253
|
-
console.log(now);
|
|
362
|
+
const now = getCalendarDate();
|
|
363
|
+
console.log(now);
|
|
254
364
|
```
|
|
255
365
|
|
|
256
366
|
### `updateCalendarDateWithOffset`
|
|
@@ -295,16 +405,27 @@ Props for the Calendar component.
|
|
|
295
405
|
const formattedTime = millisecondsToHours(1716905215397);
|
|
296
406
|
console.log(formattedTime); // Logs the formatted time for 14h06
|
|
297
407
|
```
|
|
298
|
-
### `checkDuplicates`
|
|
299
408
|
|
|
300
|
-
|
|
409
|
+
|
|
410
|
+
### `getHash`
|
|
411
|
+
|
|
412
|
+
- **Description**: Generates a set of bucket hashes based on the offset, group, and day.
|
|
301
413
|
- **Parameters**:
|
|
302
|
-
- `
|
|
303
|
-
- `
|
|
304
|
-
- `
|
|
305
|
-
|
|
306
|
-
|
|
414
|
+
- `weekOffset` (number): The week offset.
|
|
415
|
+
- `groupId` (string, optional): The group ID.
|
|
416
|
+
- `dayIndex` (number, optional): The day index (0-6).
|
|
417
|
+
- **Returns**: An object containing `week`, `group`, and `day` hash strings.
|
|
418
|
+
|
|
419
|
+
**Example**:
|
|
420
|
+
```javascript
|
|
421
|
+
import { getHash } from "react-weekly-planning";
|
|
422
|
+
const hashes = getHash(0, "group-1", 2);
|
|
423
|
+
console.log(hashes.week); // "0"
|
|
424
|
+
console.log(hashes.group); // "0/group-1"
|
|
425
|
+
console.log(hashes.day); // "0/group-1/2"
|
|
426
|
+
```
|
|
307
427
|
|
|
308
428
|
|
|
309
429
|
---
|
|
310
430
|
|
|
431
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-weekly-planning",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.39",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/types/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -15,6 +15,54 @@
|
|
|
15
15
|
"./definitions": {
|
|
16
16
|
"types": "./dist/types/definitions/index.d.ts",
|
|
17
17
|
"default": "./dist/definitions/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./hooks/useCalendarTask": {
|
|
20
|
+
"types": "./dist/types/hooks/useCalendarTask.d.ts",
|
|
21
|
+
"default": "./dist/hooks/useCalendarTask.js"
|
|
22
|
+
},
|
|
23
|
+
"./contexts/CalendarTaskContext": {
|
|
24
|
+
"types": "./dist/types/contexts/CalendarTaskContext.d.ts",
|
|
25
|
+
"default": "./dist/contexts/CalendarTaskContext.js"
|
|
26
|
+
},
|
|
27
|
+
"./contexts/CalendarContext": {
|
|
28
|
+
"types": "./dist/types/contexts/CalendarContext.d.ts",
|
|
29
|
+
"default": "./dist/contexts/CalendarContext.js"
|
|
30
|
+
},
|
|
31
|
+
"./components/TaskContainer": {
|
|
32
|
+
"types": "./dist/types/components/TaskContainer.d.ts",
|
|
33
|
+
"default": "./dist/components/TaskContainer.js"
|
|
34
|
+
},
|
|
35
|
+
"./components/DayContainer": {
|
|
36
|
+
"types": "./dist/types/components/DayContainer.d.ts",
|
|
37
|
+
"default": "./dist/components/DayContainer.js"
|
|
38
|
+
},
|
|
39
|
+
"./components/VirtualGroupRow": {
|
|
40
|
+
"types": "./dist/types/components/VirtualGroupRow.d.ts",
|
|
41
|
+
"default": "./dist/components/VirtualGroupRow.js"
|
|
42
|
+
},
|
|
43
|
+
"./components/VirtualGroupRowDay": {
|
|
44
|
+
"types": "./dist/types/components/VirtualGroupRowDay.d.ts",
|
|
45
|
+
"default": "./dist/components/VirtualGroupRowDay.js"
|
|
46
|
+
},
|
|
47
|
+
"./components/TaskContainer/TaskVirtualRow": {
|
|
48
|
+
"types": "./dist/types/components/TaskContainer/TaskVirtualRow.d.ts",
|
|
49
|
+
"default": "./dist/components/TaskContainer/TaskVirtualRow.js"
|
|
50
|
+
},
|
|
51
|
+
"./components/AddTask": {
|
|
52
|
+
"types": "./dist/types/components/AddTask.d.ts",
|
|
53
|
+
"default": "./dist/components/AddTask.js"
|
|
54
|
+
},
|
|
55
|
+
"./components/SumHoursContainer": {
|
|
56
|
+
"types": "./dist/types/components/SumHoursContainer.d.ts",
|
|
57
|
+
"default": "./dist/components/SumHoursContainer.js"
|
|
58
|
+
},
|
|
59
|
+
"./components/SumHoursHead": {
|
|
60
|
+
"types": "./dist/types/components/SumHoursHead.d.ts",
|
|
61
|
+
"default": "./dist/components/SumHoursHead.js"
|
|
62
|
+
},
|
|
63
|
+
"./components/GroupContainer": {
|
|
64
|
+
"types": "./dist/types/components/GroupContainer.d.ts",
|
|
65
|
+
"default": "./dist/components/GroupContainer.js"
|
|
18
66
|
}
|
|
19
67
|
},
|
|
20
68
|
"files": [
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from "react";
|
|
3
|
-
const AddTask = ({ currentGroup, handleAddTask, addTaskRender, dayInfo, addTaskStyle, addTaskClassName, }) => {
|
|
4
|
-
if (addTaskRender) {
|
|
5
|
-
return (_jsx(_Fragment, { children: addTaskRender({
|
|
6
|
-
currentGroup,
|
|
7
|
-
dayInfo,
|
|
8
|
-
}) }));
|
|
9
|
-
}
|
|
10
|
-
const handleClick = () => {
|
|
11
|
-
if (!handleAddTask)
|
|
12
|
-
return;
|
|
13
|
-
handleAddTask(currentGroup, dayInfo);
|
|
14
|
-
};
|
|
15
|
-
return (_jsx("div", { onClick: handleClick, style: addTaskStyle, className: `addPlanStyle ${addTaskClassName}`, children: "+" }));
|
|
16
|
-
};
|
|
17
|
-
export default memo(AddTask);
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import GroupContainer from "./GroupContainer";
|
|
3
|
-
import GroupsHeadContainer from "./GroupsHeadContainer";
|
|
4
|
-
import { groupTdStyle, theadTrStyle } from "../lib/slyles";
|
|
5
|
-
import DayContainer from "./DayContainer";
|
|
6
|
-
import SumHoursHead from "./SumHoursHead";
|
|
7
|
-
import { compareWeekOffset, getSessionStorageRecordForDragAndDrop, saveTasksToLocalStorage, sumHoursByGroups, } from "../lib/utils";
|
|
8
|
-
import TaskContainer from "./TaskContainer";
|
|
9
|
-
import AddTask from "./AddTask";
|
|
10
|
-
import SumHoursContainer from "./SumHoursContainer";
|
|
11
|
-
import { memo, useEffect } from "react";
|
|
12
|
-
import useCalendarDateState from "../hooks/useCalendarDateState";
|
|
13
|
-
function CalendarForWeek(props) {
|
|
14
|
-
var _a;
|
|
15
|
-
const { dailyHours, weekDays } = useCalendarDateState(props.date, props.weekOffset, props.timeZone);
|
|
16
|
-
const handleDragOver = (event) => {
|
|
17
|
-
event.preventDefault();
|
|
18
|
-
};
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
saveTasksToLocalStorage(props.tasks);
|
|
21
|
-
}, [props.tasks]);
|
|
22
|
-
return (_jsxs("table", { className: `planningCalendar ${props.className}`, style: Object.assign({}, props.style), children: [_jsx("thead", { children: _jsxs("tr", { className: `${props.rowsClassName}`, style: Object.assign(Object.assign({}, theadTrStyle), props.rowsStyle), children: [_jsx("th", { className: `dayTh ${props.groupsColsClassName}`, style: Object.assign({}, props.groupsColsStyle), children: _jsx(GroupsHeadContainer, { className: `${props.groupHeadContainerClassName}`, style: props.groupHeadContainerStyle, groupsHeadRender: props.groupsHeadRender }) }), weekDays.map((day, i) => (_jsx("th", { className: `${props.daysColsClassName}`, style: Object.assign({}, props.daysColsStyle), children: _jsx(DayContainer, { style: props.dayStyle, className: props.dayClassName, dayIndex: i, dayRender: props.dayRender, day: day.day, dayOfTheMonth: day.dayOfTheMonth, dayMonth: day.dayMonth, dayYear: day.dayYear }) }, i))), _jsx("th", { className: `totalTh ${props.hoursColsClassName}`, style: props.hoursColsStyle, children: _jsx(SumHoursHead, { className: props.sumHoursHeadClassName, style: props.sumHoursHeadStyle, sumHoursHeadRender: props.sumHoursHeadRender }) })] }, "") }), _jsx("tbody", { children: (_a = props.groups) === null || _a === void 0 ? void 0 : _a.map((group, i) => (_jsxs("tr", { className: `${props.rowsClassName}`, style: Object.assign({}, props.rowsStyle), children: [_jsx("td", { className: `${props.groupsColsClassName}`, style: Object.assign(Object.assign({}, groupTdStyle), props.groupsColsStyle), children: _jsx(GroupContainer, { style: props.groupContainerStyle, className: props.groupContainerClassName, groupRender: props.groupRender, currentGroup: group, handleClickGroup: props.handleClickGroup }) }, i), dailyHours.map((_, positionDay) => (_jsx("td", { onDragOver: handleDragOver, onDrop: (event) => {
|
|
23
|
-
if (!props.handleDropTask || !props.tasks)
|
|
24
|
-
return;
|
|
25
|
-
const dropInfo = getSessionStorageRecordForDragAndDrop(props.tasks, positionDay, group.id);
|
|
26
|
-
if (!dropInfo)
|
|
27
|
-
return;
|
|
28
|
-
props.handleDropTask(event, dropInfo.taskDropStart, dropInfo.taskDropEnd, dropInfo.taskDropDate, group.id, positionDay, dropInfo.newTask, dropInfo.newTasks);
|
|
29
|
-
}, id: `td-${group.id}day-i`, className: props.dayColsClassName, style: props.dayColsStyle, children: _jsxs("div", { style: {
|
|
30
|
-
display: "flex",
|
|
31
|
-
width: "100%",
|
|
32
|
-
height: "100%",
|
|
33
|
-
flexDirection: "column",
|
|
34
|
-
padding: "5px",
|
|
35
|
-
}, children: [_jsx(_Fragment, { children: props.tasks
|
|
36
|
-
.map((task, taskKey) => {
|
|
37
|
-
if (task.dayIndex === positionDay &&
|
|
38
|
-
task.groupId === group.id &&
|
|
39
|
-
compareWeekOffset(props.date, props.weekOffset || 0, task.taskDate, props.timeZone)) {
|
|
40
|
-
return (_jsx(TaskContainer, { handleDragTask: props.handleDragTask, taskRender: props.taskRender, handleDragTaskEnd: props.handleDragTaskEnd, style: props.taskContainerStyle, className: `${props.taskContainerClassName}`, currentTask: task, handleClickTask: props.handleClickTask }, `${taskKey} task`));
|
|
41
|
-
}
|
|
42
|
-
else
|
|
43
|
-
return "";
|
|
44
|
-
}) }), _jsx(AddTask, { addTaskStyle: props.addTaskStyle, addTaskClassName: props.addTaskClassName, currentGroup: group, dayInfo: dailyHours[positionDay], addTaskRender: props.addTaskRender, handleAddTask: props.handleAddTask })] }, positionDay) }, `td-${group.id}day-i${positionDay}`))), _jsx("td", { style: props.hoursColsStyle, className: props.hoursColsClassName, children: _jsx(SumHoursContainer, { groupId: group.id, tasks: props.tasks, weekOffset: props.weekOffset || 0, calendarDate: props.date, sumHoursRender: props.sumHoursRender, sumHoursByGroups: sumHoursByGroups(group.id, props.tasks, props.weekOffset || 0, props.date, props.timeZone), className: props.sumHoursContainerClassName, style: props.sumHoursContainerStyle }) }, `${i}sumHours`)] }, `${i} tr`))) })] }));
|
|
45
|
-
}
|
|
46
|
-
export default memo(CalendarForWeek, (prevProps, nextProps) => prevProps.tasks === nextProps.tasks &&
|
|
47
|
-
prevProps.date === nextProps.date &&
|
|
48
|
-
prevProps.groups === nextProps.groups &&
|
|
49
|
-
prevProps.weekOffset === nextProps.weekOffset);
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import "./style.css";
|
|
3
|
-
import { memo, useEffect } from "react";
|
|
4
|
-
import { compareWeekOffset, saveTasksToLocalStorage } from "../lib/utils";
|
|
5
|
-
import useCalendarDateState from "../hooks/useCalendarDateState";
|
|
6
|
-
import AddTask from "./AddTask";
|
|
7
|
-
import TaskContainer from "./TaskContainer";
|
|
8
|
-
import GroupContainer from "./GroupContainer";
|
|
9
|
-
import DayContainer from "./DayContainer";
|
|
10
|
-
function CalendarForDay(props) {
|
|
11
|
-
const { dailyHours, weekDays } = useCalendarDateState(props.date, props.weekOffset, props.timeZone);
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
saveTasksToLocalStorage(props.tasks);
|
|
14
|
-
}, [props.tasks]);
|
|
15
|
-
const currentDay = weekDays[props.dayOffset || 0];
|
|
16
|
-
const currentDailyHours = dailyHours[props.dayOffset || 0];
|
|
17
|
-
return (_jsxs("div", { className: ` CalendarTableForDay ${props.className}`, style: Object.assign({}, props.style), children: [currentDay && (_jsx(DayContainer, { style: props.dayStyle, className: props.dayClassName, dayIndex: props.dayOffset || 0, dayRender: props.dayRender, day: currentDay.day, dayOfTheMonth: currentDay.dayOfTheMonth, dayMonth: currentDay.dayMonth, dayYear: currentDay.dayYear })), _jsx("div", { className: `CalendarTableForDayTasksContainer`, children: currentDailyHours &&
|
|
18
|
-
props.groups.map((group, i) => {
|
|
19
|
-
return (_jsxs("div", { style: Object.assign({ width: "100%", height: "auto", padding: "5px", borderBottom: "1.5px solid #0f52737e", borderRight: "0.74px solid rgba(198, 219, 225, 0.68)", borderLeft: "0.74px solid rgba(198, 219, 225, 0.68)" }, props.rowsStyle), className: `CalendarTableForDayRow ${props.rowsClassName}`, children: [_jsx("div", { style: Object.assign({ width: "auto", height: "auto" }, props.groupsColsStyle), className: props.groupsColsClassName, children: _jsx(GroupContainer, { style: props.groupContainerStyle, className: props.groupContainerClassName, groupRender: props.groupRender, currentGroup: group, handleClickGroup: props.handleClickGroup }) }), _jsxs("div", { className: "CalendarTableForDayGroupTasks", children: [props.tasks.map((task, taskKey) => {
|
|
20
|
-
if (task.dayIndex === (props.dayOffset || 0) &&
|
|
21
|
-
task.groupId === group.id &&
|
|
22
|
-
compareWeekOffset(props.date, props.weekOffset || 0, task.taskDate, props.timeZone)) {
|
|
23
|
-
return (_jsx(TaskContainer, { handleDragTask: props.handleDragTask, taskRender: props.taskRender, handleDragTaskEnd: props.handleDragTaskEnd, style: props.taskContainerStyle, className: `${props.taskContainerClassName}`, currentTask: task, handleClickTask: props.handleClickTask }, `${taskKey} task`));
|
|
24
|
-
}
|
|
25
|
-
else
|
|
26
|
-
return "";
|
|
27
|
-
}), _jsx(AddTask, { addTaskStyle: props.addTaskStyle, addTaskClassName: props.addTaskClassName, currentGroup: group, dayInfo: currentDailyHours, addTaskRender: props.addTaskRender, handleAddTask: props.handleAddTask })] })] }, i));
|
|
28
|
-
}) })] }));
|
|
29
|
-
}
|
|
30
|
-
export default memo(CalendarForDay, (prevProps, nextProps) => prevProps.tasks === nextProps.tasks &&
|
|
31
|
-
prevProps.date === nextProps.date &&
|
|
32
|
-
prevProps.groups === nextProps.groups &&
|
|
33
|
-
prevProps.weekOffset === nextProps.weekOffset);
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from "react";
|
|
3
|
-
const DayContainer = ({ dayIndex, dayOfTheMonth, day, dayMonth, dayYear, dayRender, className, style, }) => {
|
|
4
|
-
if (dayRender) {
|
|
5
|
-
return (_jsx(_Fragment, { children: dayRender({
|
|
6
|
-
dayIndex,
|
|
7
|
-
day,
|
|
8
|
-
dayOfTheMonth,
|
|
9
|
-
dayMonth,
|
|
10
|
-
dayYear,
|
|
11
|
-
}) }));
|
|
12
|
-
}
|
|
13
|
-
return (_jsx("div", { className: `${className}`, style: style, children: `${day}. ${dayOfTheMonth}` }));
|
|
14
|
-
};
|
|
15
|
-
export default memo(DayContainer);
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from "react";
|
|
3
|
-
import { groupContainerStyle } from "../../lib/slyles";
|
|
4
|
-
const GroupContainer = ({ className, style, groupRender, currentGroup, handleClickGroup, }) => {
|
|
5
|
-
if (groupRender) {
|
|
6
|
-
return _jsx(_Fragment, { children: groupRender({ currentGroup }) });
|
|
7
|
-
}
|
|
8
|
-
const handleClick = () => {
|
|
9
|
-
if (!handleClickGroup)
|
|
10
|
-
return;
|
|
11
|
-
handleClickGroup(currentGroup);
|
|
12
|
-
};
|
|
13
|
-
return (_jsxs("div", { onClick: handleClick, className: `${className}`, style: Object.assign(Object.assign({}, groupContainerStyle), style), children: [currentGroup.imageUrl && (_jsx("img", { width: 30, height: 30, src: currentGroup.imageUrl, alt: "groupimg" })), _jsx("label", { children: currentGroup.label && currentGroup.label })] }));
|
|
14
|
-
};
|
|
15
|
-
export default memo(GroupContainer);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from "react";
|
|
3
|
-
const GroupsHeadContainer = ({ groupsHeadRender, style, className, }) => {
|
|
4
|
-
if (groupsHeadRender) {
|
|
5
|
-
return _jsx(_Fragment, { children: groupsHeadRender() });
|
|
6
|
-
}
|
|
7
|
-
return (_jsx("div", { className: `${className}`, style: style, children: "WeeklyCalendar" }));
|
|
8
|
-
};
|
|
9
|
-
export default memo(GroupsHeadContainer);
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from "react";
|
|
3
|
-
import { totalLabel } from "../../lib/utils";
|
|
4
|
-
const SumHoursContainer = ({ groupId, tasks, weekOffset, calendarDate, sumHoursByGroups, sumHoursRender, className, style, }) => {
|
|
5
|
-
if (sumHoursRender) {
|
|
6
|
-
return (_jsx(_Fragment, { children: sumHoursRender({
|
|
7
|
-
groupId,
|
|
8
|
-
tasks,
|
|
9
|
-
weekOffset,
|
|
10
|
-
calendarDate,
|
|
11
|
-
sumHoursByGroups,
|
|
12
|
-
}) }));
|
|
13
|
-
}
|
|
14
|
-
return (_jsx("div", { style: Object.assign({ textAlign: "right", marginRight: "5px" }, style), className: `${className}`, children: totalLabel(sumHoursByGroups) }));
|
|
15
|
-
};
|
|
16
|
-
export default memo(SumHoursContainer);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { memo } from "react";
|
|
3
|
-
const SumHoursHead = ({ sumHoursHeadRender, className, style, }) => {
|
|
4
|
-
if (sumHoursHeadRender) {
|
|
5
|
-
return _jsx(_Fragment, { children: sumHoursHeadRender() });
|
|
6
|
-
}
|
|
7
|
-
return (_jsx("div", { className: `${className}`, style: Object.assign({ textAlign: "right", marginRight: "5px" }, style), children: "Hours" }));
|
|
8
|
-
};
|
|
9
|
-
export default memo(SumHoursHead);
|