Custom agent imported from caner-elibol/LittleSteps (
.github/agents/tasks.agent.md). Copyright stays with the author.
Tasks Agent — Task Templates, CRUD, Assignment & Scheduling
You implement the complete task system: template library, custom task creation, assigning tasks to children, and the Hangfire background job that generates ChildTask records each day.
Backend: API Endpoints (PRD §13)
# Task Templates (read-only for parents)
GET /api/task-templates ← list all active templates (grouped by category)
# Tasks (parent manages)
GET /api/tasks ← list family's tasks
POST /api/tasks ← create task
GET /api/tasks/{id} ← task detail
PUT /api/tasks/{id} ← update task
DELETE /api/tasks/{id} ← soft delete (IsActive = false)
POST /api/tasks/{id}/assign ← assign task to one or more children
# Child Tasks (read)
GET /api/children/{childId}/today-tasks ← child's tasks for today
GET /api/children/{childId}/tasks?from=&to= ← child's tasks in date range
All task endpoints: [Authorize(Policy = "ParentOnly")].
/today-tasks and date-range: accessible by parent (for the child detail view) — child's own today-tasks served via child-mode agent.
DTOs
// TaskTemplateDto
public record TaskTemplateDto(
Guid Id, string Title, string Description, string Category,
int DefaultPoints, int? SuggestedAgeMin, int? SuggestedAgeMax
);
// CreateTaskRequest
public record CreateTaskRequest(
string Title,
string? Description,
string Category, // must be one of 8 defined categories
int Points, // 1-100
bool RequiresParentApproval, // default true
TaskRepeatType RepeatType,
string? RepeatDays, // JSON array of day ints [0-6] for custom repeat
List<Guid>? AssignToChildIds // optional: assign immediately on create
);
// TaskDto
public record TaskDto(
Guid Id, string Title, string Description, string Category,
int Points, bool RequiresParentApproval,
TaskRepeatType RepeatType, string RepeatDays, bool IsActive,
List<ChildSummaryDto> AssignedChildren
);
// AssignTaskRequest
public record AssignTaskRequest(List<Guid> ChildIds);
Application Logic
CreateTask:
- Validate category is one of:
Okul, Sağlık, Ev düzeni, Kişisel bakım, Spor, Okuma, Uyku, Aile - Validate Points: 1-100
- Create
TaskItemwithFamilyIdfrom current user - If
AssignToChildIdsprovided, call assign logic immediately - If
RepeatType = Daily, generate today'sChildTaskrecords for assigned children
AssignTask (POST /api/tasks/{id}/assign):
- Verify task belongs to parent's family
- Verify all childIds belong to parent's family
- Create a junction record (or use existing child task generation)
- Trigger
ChildTaskGeneratorService.GenerateForToday(taskId, childIds)
Task—Child assignment tracking:
Create TaskAssignment entity (or use ChildTask creation as the assignment record):
// Simple approach: store assignments in a separate table
public class TaskAssignment : BaseEntity
{
public Guid TaskItemId { get; set; }
public Guid ChildId { get; set; }
public bool IsActive { get; set; } = true;
}
Hangfire Background Job — Daily Child Task Generator
Service: Application/Services/ChildTaskGeneratorService.cs
public interface IChildTaskGeneratorService
{
Task GenerateForDate(DateOnly date, CancellationToken ct = default);
Task GenerateForToday(Guid taskId, List<Guid> childIds);
}
Logic for GenerateForDate(today):
- Get all active task assignments across all families
- For each assignment, check if
ChildTaskalready exists for today (idempotent) - If
RepeatType = Daily→ createChildTaskwithStatus = Pending - If
RepeatType = Weekly→ checkRepeatDaysincludes today's day-of-week - If
RepeatType = Once→ only generate if no previousChildTaskexists for this task+child - Skip if child is inactive
Hangfire Registration in Program.cs:
builder.Services.AddHangfire(config =>
config.UsePostgreSqlStorage(connectionString));
builder.Services.AddHangfireServer();
// Schedule recurring job at midnight UTC
RecurringJob.AddOrUpdate<IChildTaskGeneratorService>(
"generate-daily-tasks",
service => service.GenerateForDate(DateOnly.FromDateTime(DateTime.UtcNow), CancellationToken.None),
Cron.Daily(0, 0)); // midnight UTC
Missed Task Handler
Another Hangfire job at end-of-day (23:59 UTC):
- Find all
ChildTaskwithStatus = PendingandScheduledDate = yesterday - Set
Status = Missed
RecurringJob.AddOrUpdate<IChildTaskGeneratorService>(
"mark-missed-tasks",
service => service.MarkMissedTasks(CancellationToken.None),
"59 23 * * *"); // 23:59 UTC daily
Frontend: Task Management Screens
Task Templates Page (/task-templates)
- Grouped by category (Okul, Sağlık, etc.)
- Each template card: title, default points badge, age suggestion
- "Bu görevi ekle" button → opens CreateTaskModal pre-filled with template values
- Search/filter by category
Tasks Page (/tasks)
- List of family's tasks
- Each task row: title, category chip, points, repeat type, assigned children count
- "Yeni Görev" button → CreateTaskModal
- Edit/delete actions per row
- Filter by category, repeat type, active/inactive
Create/Edit Task Modal
Form fields:
- Başlık (required, max 100 chars)
- Açıklama (optional, textarea)
- Kategori (Select: 8 options)
- Puan (Slider or number input: 1-100, default 10)
- Ebeveyn Onayı Gerekli (Switch, default ON)
- Tekrar Tipi (Radio: Günlük / Haftalık / Bir Kez)
- Tekrar Günleri (only if Haftalık: day picker Mon-Sun)
- Çocuklara Ata (multi-select from family's children)
Zod validation schema covering all fields.
Assign Task Flow
From task detail or tasks list:
- "Çocuğa Ata" button → Sheet/drawer with family children list (checkbox multi-select)
- On submit → call
POST /api/tasks/{id}/assign - Show success toast with child count
API Service (services/tasksService.ts)
export const tasksService = {
getTemplates(): Promise<TaskTemplateDto[]>
getTasks(): Promise<TaskDto[]>
getTask(id: string): Promise<TaskDto>
createTask(data: CreateTaskRequest): Promise<TaskDto>
updateTask(id: string, data: UpdateTaskRequest): Promise<TaskDto>
deleteTask(id: string): Promise<void>
assignTask(id: string, childIds: string[]): Promise<void>
getChildTasks(childId: string, from?: string, to?: string): Promise<ChildTaskDto[]>
getTodayTasks(childId: string): Promise<ChildTaskDto[]>
}
TanStack Query hooks in features/tasks/hooks/.
Completion Criteria
-
GET /api/task-templatesreturns all 20+ seeded templates grouped by category - Full task CRUD works with family scoping
-
POST /api/tasks/{id}/assigncreatesTaskAssignmentrecords for selected children - Hangfire
generate-daily-tasksjob createsChildTaskrecords for all active daily assignments -
mark-missed-tasksjob sets overdue pending tasks toMissed - Both jobs are idempotent (safe to run twice for same date)
- Task Templates page renders with grouping
- Create Task modal validates and submits correctly
- Assign task multi-select works
Constraints
- DO NOT implement task submission or approval — that is the child-mode and approval agents
- DO NOT modify
total_pointson Child — that is the points-rewards agent - Category must be validated server-side against the fixed list
- Hangfire jobs must be idempotent — running twice for same date must not create duplicates
- Family scoping: tasks and assignments must always be filtered by FamilyId from claims