Skip to content

Commit 91ec9bd

Browse files
authored
Merge pull request #74 from wildjames/dev
Add ability to dismiss tasks
2 parents 8718970 + ddd729b commit 91ec9bd

File tree

14 files changed

+192
-107
lines changed

14 files changed

+192
-107
lines changed

todoqueue_backend/tasks/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
urlpatterns = [
1313
path("", include(router.urls)),
1414
path("toggle_frozen/<uuid:taskId>/", views.toggle_frozen, name="toggle_frozen"),
15+
path('dismiss_task/<uuid:taskId>/', views.dismiss_task, name='dismiss_task'),
1516
path(
1617
"calculate_brownie_points/",
1718
views.calculate_brownie_points_view,

todoqueue_backend/tasks/views.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,23 @@ def toggle_frozen(request, taskId):
164164
return Response({"frozen": task.frozen}, status=status.HTTP_200_OK)
165165

166166

167+
@api_view(["POST"])
168+
@authentication_classes([JWTAuthentication])
169+
@permission_classes([IsAuthenticated])
170+
def dismiss_task(request, taskId):
171+
# Use the get_task_by_id function to retrieve the task
172+
task, task_type = get_task_by_id(taskId)
173+
174+
if not task:
175+
return Response({"detail": "Task not found."}, status=status.HTTP_404_NOT_FOUND)
176+
177+
# Set the last_completed field to the current time
178+
task.last_completed = timezone.now()
179+
task.save(update_fields=["last_completed"])
180+
181+
return Response({"last_completed": task.last_completed}, status=status.HTTP_200_OK)
182+
183+
167184
class WorkLogViewSet(viewsets.ModelViewSet):
168185
permission_classes = (IsAuthenticated,)
169186
queryset = WorkLog.objects.all().order_by("-timestamp")

todoqueue_frontend/public/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"short_name": "React App",
3-
"name": "Create React App Sample",
2+
"short_name": "ToDoQu",
3+
"name": "ToDoQu",
44
"icons": [
55
{
66
"src": "favicon.ico",

todoqueue_frontend/src/api/households.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ export const inviteUserToHousehold = async (householdId, userEmail) => {
110110
if (response.status === 200) {
111111
return { success: "Invitation sent successfully." };
112112
}
113-
return { error: response };
113+
if (response.data.detail) {
114+
return { error: response.data.detail };
115+
}
116+
return { error: `Failed to invite user, server responded with ${response.status}` }
114117
} catch (error) {
115118
console.error("Failed to send invitation:", error);
116119
return { error: `Failed to send invitation. ${error.response?.data?.detail || error.message}` };

todoqueue_frontend/src/api/tasks.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ export const freezeTask = async (taskId) => {
460460
console.log("Failed to freeze task.");
461461
return false;
462462
}
463-
console.log("Freezed task with ID: ", taskId);
463+
console.log("Froze task with ID: ", taskId);
464464
return true;
465465
};
466466

@@ -488,3 +488,28 @@ export const deleteTask = async (taskId, selectedHousehold) => {
488488
console.log("Deleted task with ID: ", taskId);
489489
return true;
490490
};
491+
492+
export const dismissTask = async (taskId, selectedHousehold) => {
493+
494+
const dismissTaskUrl = `${backend_url}/api/dismiss_task/${taskId}/`;
495+
496+
console.log("Dismissing task");
497+
console.log("dismissTaskUrl: ", dismissTaskUrl);
498+
console.log("taskId: ", taskId);
499+
500+
const res = await axios.post(
501+
dismissTaskUrl,
502+
{},
503+
{
504+
headers: {
505+
'Content-Type': 'application/json',
506+
},
507+
});
508+
509+
if (res.status !== 200) {
510+
console.log("Failed to dismiss task.");
511+
return false;
512+
}
513+
console.log("Freezed task with ID: ", taskId);
514+
return true;
515+
}

todoqueue_frontend/src/components/flipper/flipper.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
}
1717

1818
.flip-clock__slot {
19-
font-size: 3em;
19+
font-size: 2em;
2020
}
2121

2222
.card {
2323
display: block;
2424
position: relative;
2525
padding-bottom: 0.72em;
26-
font-size: 2em;
26+
font-size: 1.5em;
2727
line-height: 0.95;
2828
}
2929

@@ -36,7 +36,7 @@
3636
color: #ccc;
3737
background: #222;
3838
padding: 0.25em 0.25em;
39-
border-radius: 0.15em 0.15em 0 0;
39+
border-radius: 0.2em 0.2em 0 0;
4040
backface-visiblity: hidden;
4141
transform-style: preserve-3d;
4242
width: 4em;
@@ -50,7 +50,7 @@
5050
left: 0;
5151
border-top: solid 1px #000;
5252
background: #393939;
53-
border-radius: 0 0 0.15em 0.15em;
53+
border-radius: 0 0 0.2em 0.2em;
5454
pointer-events: none;
5555
overflow: hidden;
5656
}

todoqueue_frontend/src/components/navbar/navigation.css

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
}
1717

1818
/* Adjustments for smaller screens (less than 800px) */
19-
@media (max-width: 800px) {
19+
@media (max-width: 1000px) {
2020
.navbar-center-panel {
21-
margin-top: 10px;
22-
/* Add some space above the household selector */
21+
margin-top: 15px;
22+
margin-bottom: 15px;
2323
}
2424
}
2525

2626
/* Adjustments for larger screens (more than 800px) */
27-
@media (min-width: 800px) {
27+
@media (min-width: 1000px) {
2828
.navbar-center-panel {
2929
position: absolute;
3030
top: 50%;
@@ -87,13 +87,13 @@
8787
}
8888
}
8989

90-
@media (min-width: 800px) {
90+
@media (min-width: 1000px) {
9191
.navbar-links-container {
9292
justify-content: space-between;
9393
}
9494
}
9595

96-
@media (max-width: 800px) {
96+
@media (max-width: 1000px) {
9797
.logout-link {
9898
margin-top: 25px;
9999
}
@@ -103,7 +103,7 @@
103103
margin-right: 0.75rem;
104104
}
105105

106-
@media (min-width: 800px) {
106+
@media (min-width: 1000px) {
107107
.navbar-links-right {
108108
margin-right: 1em;
109109
}

todoqueue_frontend/src/components/popups/HouseholdDetailsPopup.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ const HouseholdDetailsPopup = React.forwardRef((props, ref) => {
3333

3434
const data = await inviteUserToHousehold(props.selectedHousehold.id, userEmail);
3535

36+
console.log("Tried to invite user. Got back: ", data);
37+
3638
if (data.error) {
3739
setErrorMessage(data.error);
3840
} else if (data.success) {

todoqueue_frontend/src/components/popups/TaskDetailsPopup.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useEffect, useRef } from 'react';
22
import BasePopup from './BasePopup';
33
import { formatDuration, getTimeSince } from '../../utils';
4-
import { deleteTask, freezeTask, fetchSelectedTask } from '../../api/tasks';
4+
import { deleteTask, freezeTask, dismissTask, fetchSelectedTask } from '../../api/tasks';
55
import './popups.css';
66

77
const TaskDetailsPopup = React.forwardRef((props, ref) => {
@@ -53,6 +53,16 @@ const TaskDetailsPopup = React.forwardRef((props, ref) => {
5353
}
5454
}
5555

56+
const handleDismissTask = async (taskId) => {
57+
console.log("Dismissing task - setting as done by no user.");
58+
const succeeded = dismissTask(taskId);
59+
if (succeeded) {
60+
fetchSelectedTask();
61+
} else {
62+
console.log("Failed to dismiss task", succeeded);
63+
}
64+
}
65+
5666
function toHumanFriendlyDate(datetimeStr) {
5767
// Parse the datetime string into a Date object
5868
const dateObj = new Date(datetimeStr);
@@ -84,7 +94,7 @@ const TaskDetailsPopup = React.forwardRef((props, ref) => {
8494
case "scheduledtask":
8595
selectedType = props.PopupType.EDIT_SCHEDULED_TASK;
8696
break;
87-
97+
8898
default:
8999
selectedType = props.PopupType.NONE;
90100
break;
@@ -161,6 +171,9 @@ const TaskDetailsPopup = React.forwardRef((props, ref) => {
161171
</div>
162172
<div className="task-popup-actions">
163173
<button className="button complete-button" onClick={() => props.handleOpenCompleteTaskPopup(props.selectedTask)}>Complete Task</button>
174+
<button className="button dismiss-button" onClick={() => handleDismissTask(props.selectedTask.id)}>Dismiss Task</button>
175+
</div>
176+
<div className="task-popup-actions">
164177
<button className="button freeze-button" onClick={() => handleFreezeTask(props.selectedTask.id)}>{props.selectedTask.frozen ? "Unfreeze Task" : "Freeze Task"}</button>
165178
<button className="button delete-button" onClick={() => handleDeleteTask(props.selectedTask.id)}>Delete Task</button>
166179
<button className="button edit-button" onClick={() => handleOpenEditTaskPopup()}>Edit Task</button>

todoqueue_frontend/src/components/tasks/Tasks.css

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
transform: translateX(-50%);
1717
top: 100px;
1818
transition: top 0.5s ease;
19-
width: 95vw;
19+
width: 95vw;
2020
max-width: 95vw;
2121
white-space: initial;
2222
}
@@ -84,7 +84,7 @@
8484
/* Change from relative to absolute */
8585
top: 55px;
8686
/* Start from where it is initially placed */
87-
bottom: 120px;
87+
bottom: 95px;
8888
/* 100px from the bottom of the viewport */
8989
width: 100%;
9090
transition: left 0.5s ease;
@@ -421,4 +421,44 @@
421421
&:hover {
422422
transform: scale(1.5);
423423
}
424+
}
425+
426+
.brownie-points-animation {
427+
opacity: 0;
428+
transition: opacity 0.5s ease-in-out;
429+
font-size: 3em;
430+
color: rgb(37, 37, 37);
431+
z-index: -1000;
432+
}
433+
434+
.brownie-points-animation.show {
435+
opacity: 1;
436+
z-index: 2000;
437+
}
438+
439+
.brownie-points-popup {
440+
position: fixed;
441+
top: 50%;
442+
left: 50%;
443+
transform: translate(-50%, -50%);
444+
padding: 2rem;
445+
background-color: #fff;
446+
border: 1px solid #ccc;
447+
border-radius: 8px;
448+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
449+
opacity: 0;
450+
font-size: 1rem;
451+
transition: opacity 0.5s ease-in-out;
452+
z-index: -1000;
453+
}
454+
455+
@media (max-width: 800px) {
456+
.brownie-points-popup {
457+
width: 90%;
458+
}
459+
}
460+
461+
.brownie-points-popup.show {
462+
opacity: 1;
463+
z-index: 2000;
424464
}

0 commit comments

Comments
 (0)