Skip to content

Commit

Permalink
Feat: Implement functionality for creating repeated tasks in Django
Browse files Browse the repository at this point in the history
  • Loading branch information
trisDeveloper committed Oct 26, 2024
1 parent f2db0c9 commit ee41b2e
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 54 deletions.
1 change: 0 additions & 1 deletion backend/focusty/focusty/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-$ll28-c=vwvzhz1p8%o5-ct(0r0&$vf@=+)c5k2frf(ncpufa-"
SECRET_KEY = config("SECRET_KEY")

# SECURITY WARNING: don't run with debug turned on in production!
Expand Down
43 changes: 26 additions & 17 deletions backend/focusty/focusty_app/task_repeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta

MAX_REPEAT_LIMIT = 50
MAX_REPEAT_LIMIT = 10


def repeat_task(repeat_params, start):
dates = []
task_count = 0

if repeat_params:
start_date = datetime.strptime(start, "%Y-%m-%d")
start_date = datetime.strptime(str(start), "%Y-%m-%d")

def repeat_units(repeat_params, start_date, task_count):
temp_date = start_date
Expand All @@ -19,48 +19,57 @@ def repeat_units(repeat_params, start_date, task_count):
dates.append(temp_date)
start_date += timedelta(days=repeat_params["everyNumber"])
task_count += 1
return start_date, task_count
# weekly tasks
elif repeat_params["everyUnit"] == "weeks":
for day in repeat_params["selectedDays"]:
current_date = temp_date
if (
repeat_params["occurrences"]
repeat_params["repeatEnd"] == "after"
and task_count >= repeat_params["occurrences"]
) or (
repeat_params["repeatEnd"] == "never"
and task_count >= MAX_REPEAT_LIMIT
):
return
current_date = start_date
days_to_add = (day - current_date.weekday() + 7) % 7
break
days_to_add = ((day - 1) - temp_date.weekday() + 7) % 7
current_date += timedelta(days=days_to_add)
if current_date >= start_date:
dates.append(temp_date)
dates.append(current_date)
task_count += 1

start_date += timedelta(days=7 * repeat_params["everyNumber"])
return start_date, task_count
# monthly tasks
elif repeat_params["everyUnit"] == "months":
dates.append(temp_date)
start_date = start_date + relativedelta(
months=repeat_params["everyNumber"]
)
start_date += relativedelta(months=repeat_params["everyNumber"])
task_count += 1
return start_date, task_count
# yearly tasks
elif repeat_params["everyUnit"] == "years":
dates.append(temp_date)
start_date = temp_date + relativedelta(
years=repeat_params["everyNumber"]
)
start_date += relativedelta(years=repeat_params["everyNumber"])
task_count += 1
return start_date, task_count

# loops for repeating tasks
if repeat_params["repeatEnd"] == "after":
for _ in range(repeat_params["occurrences"]):
repeat_units(repeat_params, start_date, task_count)
start_date, task_count = repeat_units(
repeat_params, start_date, task_count
)

elif repeat_params["repeatEnd"] == "on":
end_date = datetime.strptime(repeat_params["endDate"], "%Y-%m-%d")
while start_date <= end_date:
repeat_units(repeat_params, start_date, task_count)
start_date, task_count = repeat_units(
repeat_params, start_date, task_count
)

elif repeat_params["repeatEnd"] == "never":
for _ in range(MAX_REPEAT_LIMIT):
repeat_units(repeat_params, start_date, task_count)

start_date, task_count = repeat_units(
repeat_params, start_date, task_count
)
return dates
101 changes: 72 additions & 29 deletions backend/focusty/focusty_app/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#views.py
# views.py
from datetime import datetime
from rest_framework import generics
from .models import User, Task, Pomodoro
from .serializers import TaskSerializer, UserSerializer, PomodoroSerializer
Expand All @@ -10,78 +11,120 @@
import json
from django.db.models import Count
from django.db.models import Sum
from .task_repeat import repeat_task


class UserList(generics.ListCreateAPIView):
queryset = User.objects.filter(is_staff=False)
queryset = User.objects.filter(is_staff=False)
serializer_class = UserSerializer


class UserDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer


class TaskListCreate(generics.ListCreateAPIView):
serializer_class = TaskSerializer

def get_queryset(self):
user_id = self.kwargs['user_id']
user_id = self.kwargs["user_id"]
return Task.objects.filter(user_id=user_id)

def perform_create(self, serializer):
user_id = self.kwargs['user_id']
serializer.save(user_id=user_id)

user_id = self.kwargs["user_id"]

repeat_params = serializer.validated_data.get("repeatParameters", None)
start_date = serializer.validated_data.get("date")
if repeat_params:
# Call repeat_task to generate dates based on repeat parameters
dates = repeat_task(repeat_params, start_date)
for date_instance in dates:

new_serializer = self.get_serializer(
data={
**serializer.validated_data,
"user": user_id,
"date": date_instance.date(),
"repeatId": "1",
}
)
new_serializer.is_valid(raise_exception=True)
new_serializer.save()
else:
# If no repeat, save the task as usual
serializer.save(user_id=user_id)


class TaskDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer



@api_view(['GET'])
@api_view(["GET"])
def tasks_count(request, user_id):
tasks_count_by_date = Task.objects.filter(user_id=user_id)\
.values('date')\
.annotate(tasks_count=Count('id'))
tasks_count_by_date = (
Task.objects.filter(user_id=user_id)
.values("date")
.annotate(tasks_count=Count("id"))
)

return Response(tasks_count_by_date)


@csrf_exempt
def login_view(request):
if request.method == 'POST':
if request.method == "POST":
data = json.loads(request.body)
email = data.get('email')
password = data.get('password')
email = data.get("email")
password = data.get("password")

try:
user = User.objects.get(email=email)
except User.DoesNotExist:
return JsonResponse({'success': False, 'message': 'User does not exist'}, status=404)
return JsonResponse(
{"success": False, "message": "User does not exist"}, status=404
)
if password == user.password:
print(user)
return JsonResponse({'success': True, 'user': {
'id': user.id,
'username': user.username,
'email': user.email,
}})
return JsonResponse(
{
"success": True,
"user": {
"id": user.id,
"username": user.username,
"email": user.email,
},
}
)

else:
return JsonResponse({'success': False, 'message': 'Invalid email or password'}, status=400)
return JsonResponse(
{"success": False, "message": "Invalid email or password"}, status=400
)
else:
return JsonResponse({'success': False, 'message': 'Method not allowed'}, status=405)

return JsonResponse(
{"success": False, "message": "Method not allowed"}, status=405
)


class PomodoroDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Pomodoro.objects.all()
serializer_class = PomodoroSerializer


class PomodoroListCreate(generics.ListCreateAPIView):
serializer_class = PomodoroSerializer

def get_queryset(self):
user_id = self.kwargs['user_id']
return Pomodoro.objects.filter(user_id=user_id)\
.values('date')\
.annotate(minutes=Sum('minutes'))\
.order_by('-date')
user_id = self.kwargs["user_id"]
return (
Pomodoro.objects.filter(user_id=user_id)
.values("date")
.annotate(minutes=Sum("minutes"))
.order_by("-date")
)

def perform_create(self, serializer):
user_id = self.kwargs['user_id']
user_id = self.kwargs["user_id"]
serializer.save(user_id=user_id)
22 changes: 16 additions & 6 deletions frontend/src/utils/repeat-task-logic.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
let nextTaskId = localStorage.getItem('nextTaskId') || 1
let neverMax = 365
export const repeatTask = (store, prams, start, tasks) => {
let dates = []
let taskCount = 0
Expand All @@ -7,14 +8,19 @@ export const repeatTask = (store, prams, start, tasks) => {

const repeatUnits = (prams) => {
const tempDate = new Date(startDate)

// daily tasks
if (prams.everyUnit === 'days') {
dates.push(new Date(tempDate))
startDate.setDate(startDate.getDate() + prams.everyNumber)
taskCount++
} else if (prams.everyUnit === 'weeks') {
} //weekly tasks
else if (prams.everyUnit === 'weeks') {
prams.selectedDays.forEach((day) => {
if (prams.occurrences && taskCount >= prams.occurrences) return
if (
(prams.occurrences && taskCount >= prams.occurrences) ||
(prams.repeatEnd === 'never' && taskCount >= neverMax)
)
return

const currentDate = new Date(startDate)
const daysToAdd = (day - currentDate.getDay() + 7) % 7
Expand All @@ -26,11 +32,15 @@ export const repeatTask = (store, prams, start, tasks) => {
}
})
startDate.setDate(startDate.getDate() + 7 * prams.everyNumber)
} else if (prams.everyUnit === 'months') {
}
// monthly tasks
else if (prams.everyUnit === 'months') {
dates.push(new Date(tempDate))
startDate.setMonth(startDate.getMonth() + prams.everyNumber)
taskCount++
} else if (prams.everyUnit === 'years') {
}
// yearly tasks
else if (prams.everyUnit === 'years') {
dates.push(new Date(tempDate))
startDate.setFullYear(startDate.getFullYear() + prams.everyNumber)
taskCount++
Expand All @@ -46,7 +56,7 @@ export const repeatTask = (store, prams, start, tasks) => {
repeatUnits(prams)
}
} else if (prams.repeatEnd === 'never') {
while (taskCount <= 365) {
while (taskCount <= neverMax) {
repeatUnits(prams)
}
}
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/utils/save-task-logic.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export const saveTaskLogic = async (
})
} else {
// New task creation
await axios.post(`/api/users/${store.user.id}/tasks/`, store.selectedTask)
await axios.post(`/api/users/${store.user.id}/tasks/`, {
...store.selectedTask,
thisOrAll
})
}
} else {
// update task
Expand Down

0 comments on commit ee41b2e

Please sign in to comment.