← back to kkrlosdev__tasks_api

Function bodies 57 total

All specs Real LLM only Function bodies
DashboardApp function · typescript · L3-L11 (9 LOC)
frontend/src/app/DashboardApp.tsx
export function DashboardApp() {
  return (
    <main className="app-shell">
      <div className="app-shell__content">
        <TaskDashboard />
      </div>
    </main>
  )
}
App function · typescript · L4-L6 (3 LOC)
frontend/src/App.tsx
function App() {
  return <DashboardApp />
}
EmptyState function · typescript · L6-L13 (8 LOC)
frontend/src/components/EmptyState.tsx
export function EmptyState({ title, description }: EmptyStateProps) {
  return (
    <div className="empty-state">
      <h3>{title}</h3>
      <p>{description}</p>
    </div>
  )
}
StatusBadge function · typescript · L7-L16 (10 LOC)
frontend/src/components/StatusBadge.tsx
export function StatusBadge({ status }: StatusBadgeProps) {
  const tone = getTaskStatusTone(status)

  return (
    <span className={`status-badge status-badge--${tone}`}>
      <span className="status-badge__dot" />
      {getTaskStatusLabel(status)}
    </span>
  )
}
TaskDashboard function · typescript · L10-L183 (174 LOC)
frontend/src/features/tasks/TaskDashboard.tsx
export function TaskDashboard() {
  const [tasks, setTasks] = useState<Task[]>([])
  const [selectedStatus, setSelectedStatus] = useState<string>('all')
  const [activeTask, setActiveTask] = useState<Task | null>(null)
  const [isLoading, setIsLoading] = useState<boolean>(true)
  const [isSubmitting, setIsSubmitting] = useState<boolean>(false)
  const [busyTaskId, setBusyTaskId] = useState<number | null>(null)
  const [screenError, setScreenError] = useState<string | null>(null)
  const [formError, setFormError] = useState<string | null>(null)

  useEffect(() => {
    void loadTasks(selectedStatus)
  }, [selectedStatus])

  async function loadTasks(statusFilter: string) {
    setIsLoading(true)
    setScreenError(null)

    try {
      const status = statusFilter === 'all' ? undefined : Number(statusFilter)
      const data = await getTasks(status)
      setTasks(data)
    } catch (error) {
      setScreenError(getErrorMessage(error))
    } finally {
      setIsLoading(false)
    }
  }
loadTasks function · typescript · L24-L37 (14 LOC)
frontend/src/features/tasks/TaskDashboard.tsx
  async function loadTasks(statusFilter: string) {
    setIsLoading(true)
    setScreenError(null)

    try {
      const status = statusFilter === 'all' ? undefined : Number(statusFilter)
      const data = await getTasks(status)
      setTasks(data)
    } catch (error) {
      setScreenError(getErrorMessage(error))
    } finally {
      setIsLoading(false)
    }
  }
handleSubmit function · typescript · L39-L60 (22 LOC)
frontend/src/features/tasks/TaskDashboard.tsx
  async function handleSubmit(payload: TaskPayload, taskId?: number): Promise<boolean> {
    setIsSubmitting(true)
    setFormError(null)

    try {
      if (typeof taskId === 'number') {
        const updatePayload: TaskUpdatePayload = { ...payload, id: taskId }
        await updateTask(taskId, updatePayload)
        setActiveTask(null)
      } else {
        await createTask(payload)
      }

      await loadTasks(selectedStatus)
      return true
    } catch (error) {
      setFormError(getErrorMessage(error))
      return false
    } finally {
      setIsSubmitting(false)
    }
  }
Repobility analyzer · published findings · https://repobility.com
handleDelete function · typescript · L62-L82 (21 LOC)
frontend/src/features/tasks/TaskDashboard.tsx
  async function handleDelete(task: Task) {
    const confirmed = window.confirm(`¿Eliminar la tarea "${task.name}"?`)
    if (!confirmed) {
      return
    }

    setBusyTaskId(task.id)
    setScreenError(null)

    try {
      await deleteTask(task.id)
      if (activeTask?.id === task.id) {
        setActiveTask(null)
      }
      await loadTasks(selectedStatus)
    } catch (error) {
      setScreenError(getErrorMessage(error))
    } finally {
      setBusyTaskId(null)
    }
  }
getFilterLabel function · typescript · L185-L195 (11 LOC)
frontend/src/features/tasks/TaskDashboard.tsx
function getFilterLabel(value: string): string {
  if (value === '1') {
    return 'Pendiente'
  }

  if (value === '2') {
    return 'Completada'
  }

  return 'Todas'
}
TaskForm function · typescript · L33-L254 (222 LOC)
frontend/src/features/tasks/TaskForm.tsx
export function TaskForm({
  activeTask,
  isSubmitting,
  formError,
  onCancelEdit,
  onSubmit,
}: TaskFormProps) {
  const [formState, setFormState] = useState<TaskFormState>(INITIAL_STATE)
  const [localError, setLocalError] = useState<string | null>(null)

  useEffect(() => {
    if (!activeTask) {
      setFormState(INITIAL_STATE)
      setLocalError(null)
      return
    }

    setFormState({
      name: activeTask.name,
      beginDate: formatApiDateToInput(activeTask.begin_date),
      endDate: formatApiDateToInput(activeTask.end_date),
      shortDescription: activeTask.short_description ?? '',
      longDescription: activeTask.long_description ?? '',
      status: String(activeTask.status),
    })
    setLocalError(null)
  }, [activeTask])

  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    setLocalError(null)

    const beginDate = formatInputDateToApi(formState.beginDate)
    const endDate = formatInputDateToApi(formState.end
handleSubmit function · typescript · L61-L92 (32 LOC)
frontend/src/features/tasks/TaskForm.tsx
  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    setLocalError(null)

    const beginDate = formatInputDateToApi(formState.beginDate)
    const endDate = formatInputDateToApi(formState.endDate)

    if (!formState.name.trim()) {
      setLocalError('El nombre de la tarea es obligatorio.')
      return
    }

    if (!isValidApiDate(beginDate) || !isValidApiDate(endDate)) {
      setLocalError('Las fechas deben existir y tener formato DD-MM-YYYY.')
      return
    }

    const payload: TaskPayload = {
      name: formState.name.trim(),
      begin_date: beginDate,
      end_date: endDate,
      short_description: formState.shortDescription.trim() || null,
      long_description: formState.longDescription.trim() || null,
      status: Number(formState.status),
    }

    const wasSuccessful = await onSubmit(payload, activeTask?.id)

    if (!activeTask && wasSuccessful) {
      setFormState(INITIAL_STATE)
    }
  }
handleChange function · typescript · L94-L99 (6 LOC)
frontend/src/features/tasks/TaskForm.tsx
  function handleChange<Key extends keyof TaskFormState>(key: Key, value: TaskFormState[Key]) {
    setFormState((current) => ({
      ...current,
      [key]: value,
    }))
  }
TaskStatusFilter function · typescript · L9-L30 (22 LOC)
frontend/src/features/tasks/TaskStatusFilter.tsx
export function TaskStatusFilter({ value, disabled = false, onChange }: TaskStatusFilterProps) {
  return (
    <div className="status-filter">
      <label className="status-filter__label" htmlFor="task-status-filter">
        Filtrar por estado
      </label>
      <select
        id="task-status-filter"
        className="select status-filter__select"
        value={value}
        disabled={disabled}
        onChange={(event) => onChange(event.target.value)}
      >
        {TASK_FILTER_OPTIONS.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
    </div>
  )
}
TaskTable function · typescript · L13-L90 (78 LOC)
frontend/src/features/tasks/TaskTable.tsx
export function TaskTable({ tasks, busyTaskId, isLoading, onEdit, onDelete }: TaskTableProps) {
  if (!isLoading && tasks.length === 0) {
    return (
      <div className="table-wrapper">
        <EmptyState
          title="No hay tareas para mostrar"
          description="Crea una nueva tarea o cambia el filtro para ver otros resultados."
        />
      </div>
    )
  }

  return (
    <div className="table-wrapper">
      <div className="table-scroll">
        <table className="task-table">
          <thead>
            <tr>
              <th>Tarea</th>
              <th>Fechas</th>
              <th>Estado</th>
              <th>Descripción larga</th>
              <th>Acciones</th>
            </tr>
          </thead>
          <tbody>
            {tasks.map((task) => {
              const isBusy = busyTaskId === task.id

              return (
                <tr key={task.id}>
                  <td>
                    <p className="task-title">{task.name}</p>
              
ApiError class · typescript · L8-L18 (11 LOC)
frontend/src/services/http.ts
export class ApiError extends Error {
  readonly status: number
  readonly detail: unknown

  constructor(message: string, status: number, detail: unknown) {
    super(message)
    this.name = 'ApiError'
    this.status = status
    this.detail = detail
  }
}
Repobility (the analyzer behind this table) · https://repobility.com
constructor method · typescript · L12-L17 (6 LOC)
frontend/src/services/http.ts
  constructor(message: string, status: number, detail: unknown) {
    super(message)
    this.name = 'ApiError'
    this.status = status
    this.detail = detail
  }
requestJson function · typescript · L20-L55 (36 LOC)
frontend/src/services/http.ts
export async function requestJson<T>(path: string, options: RequestOptions = {}): Promise<T> {
  const { expectedStatus, headers, ...requestInit } = options
  const response = await fetch(`${API_BASE_URL}${path}`, {
    ...requestInit,
    headers: {
      Accept: 'application/json',
      ...headers,
    },
  })

  const isJsonResponse = response.headers.get('content-type')?.includes('application/json') ?? false
  const responseBody = isJsonResponse ? await response.json() : null

  if (!response.ok) {
    const message =
      extractValidationMessage(responseBody) ||
      (typeof responseBody === 'object' &&
      responseBody !== null &&
      'detail' in responseBody &&
      typeof responseBody.detail === 'string'
        ? responseBody.detail
        : `La solicitud falló con estado ${response.status}.`)

    throw new ApiError(message, response.status, responseBody)
  }

  if (expectedStatus && !expectedStatus.includes(response.status)) {
    throw new ApiError(
      `La API 
extractValidationMessage function · typescript · L57-L68 (12 LOC)
frontend/src/services/http.ts
function extractValidationMessage(value: unknown): string | null {
  if (!value || typeof value !== 'object' || !('detail' in value)) {
    return null
  }

  const detail = (value as ValidationErrorResponse).detail
  if (!Array.isArray(detail) || detail.length === 0) {
    return null
  }

  return detail.map((issue) => issue.msg).join(' ')
}
getTasks function · typescript · L4-L13 (10 LOC)
frontend/src/services/tasksApi.ts
export async function getTasks(status?: number): Promise<Task[]> {
  const query = typeof status === 'number' ? `?status=${status}` : ''
  const response = await requestJson<unknown>(`/tasks${query}`, { method: 'GET' })

  if (!Array.isArray(response)) {
    return []
  }

  return response as Task[]
}
createTask function · typescript · L15-L24 (10 LOC)
frontend/src/services/tasksApi.ts
export async function createTask(payload: TaskPayload): Promise<CreateTaskResponse> {
  return requestJson<CreateTaskResponse>('/tasks', {
    method: 'POST',
    expectedStatus: [200, 201],
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(payload),
  })
}
updateTask function · typescript · L26-L35 (10 LOC)
frontend/src/services/tasksApi.ts
export async function updateTask(id: number, payload: TaskUpdatePayload): Promise<void> {
  await requestJson<null>(`/tasks/${id}`, {
    method: 'PUT',
    expectedStatus: [200, 204],
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(payload),
  })
}
deleteTask function · typescript · L37-L42 (6 LOC)
frontend/src/services/tasksApi.ts
export async function deleteTask(id: number): Promise<void> {
  await requestJson<null>(`/tasks/${id}`, {
    method: 'DELETE',
    expectedStatus: [200, 204],
  })
}
isValidApiDate function · typescript · L3-L17 (15 LOC)
frontend/src/utils/date.ts
export function isValidApiDate(value: string): boolean {
  const match = API_DATE_REGEX.exec(value)
  if (!match) {
    return false
  }

  const [, day, month, year] = match
  const parsedDate = new Date(Number(year), Number(month) - 1, Number(day))

  return (
    parsedDate.getFullYear() === Number(year) &&
    parsedDate.getMonth() === Number(month) - 1 &&
    parsedDate.getDate() === Number(day)
  )
}
Repobility · open methodology · https://repobility.com/research/
formatInputDateToApi function · typescript · L19-L27 (9 LOC)
frontend/src/utils/date.ts
export function formatInputDateToApi(value: string): string {
  if (!value) {
    return ''
  }

  const [year, month, day] = value.split('-')

  return `${day}-${month}-${year}`
}
formatApiDateToInput function · typescript · L29-L38 (10 LOC)
frontend/src/utils/date.ts
export function formatApiDateToInput(value: string): string {
  const match = API_DATE_REGEX.exec(value)
  if (!match) {
    return ''
  }

  const [, day, month, year] = match

  return `${year}-${month}-${day}`
}
getErrorMessage function · typescript · L3-L13 (11 LOC)
frontend/src/utils/error.ts
export function getErrorMessage(error: unknown): string {
  if (error instanceof ApiError) {
    return error.message
  }

  if (error instanceof Error) {
    return error.message
  }

  return 'Ocurrió un error inesperado. Intenta nuevamente.'
}
getTaskStatusLabel function · typescript · L1-L11 (11 LOC)
frontend/src/utils/status.ts
export function getTaskStatusLabel(status: number): string {
  if (status === 1) {
    return 'Pendiente'
  }

  if (status === 2) {
    return 'Completada'
  }

  return `Estado ${status}`
}
getTaskStatusTone function · typescript · L13-L23 (11 LOC)
frontend/src/utils/status.ts
export function getTaskStatusTone(status: number): string {
  if (status === 1) {
    return 'pending'
  }

  if (status === 2) {
    return 'done'
  }

  return 'unknown'
}
Task class · python · L3-L9 (7 LOC)
src/app/models/task.py
class Task(BaseModel):
    name: str
    begin_date: str
    end_date: str
    short_description: str | None
    long_description: str | None
    status: int
TaskUpdate class · python · L3-L10 (8 LOC)
src/app/models/task_update.py
class TaskUpdate(BaseModel):
    id: int
    name: str
    begin_date: str
    end_date: str
    short_description: str | None
    long_description: str | None
    status: int
BaseRepository class · python · L5-L43 (39 LOC)
src/app/repository/base_repository.py
class BaseRepository:
    def __enter__(self):
        # Se ejecuta al momento de abrir la conexión y crea la conexión y el cursor. Retorna el DAO
        self.connection = connect()
        self.cursor = self.connection.cursor()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        # Se ejecuta siempre al cierre de la operación; en caso de éxito hace commit, sino hace rollback. Para finalizar cierra conexión y cursor.
        if exc_type:
            self.connection.rollback()
        else:
            self.connection.commit()
        self.cursor.close()
        self.connection.close()

    def _execute_query(self, query, params=None, mode=None):
        """
        Ejecuta una consulta SQL.

        # Params:
        - query: la consulta SQL.
        - params: los parámetros para la consulta.
        - mode: 'one' para fetchone, 'all' para fetchall, None para operaciones tipo INSERT/UPDATE/DELETE.
        """
        try:
            if params is None:
Repobility · MCP-ready · https://repobility.com
__enter__ method · python · L6-L10 (5 LOC)
src/app/repository/base_repository.py
    def __enter__(self):
        # Se ejecuta al momento de abrir la conexión y crea la conexión y el cursor. Retorna el DAO
        self.connection = connect()
        self.cursor = self.connection.cursor()
        return self
__exit__ method · python · L12-L19 (8 LOC)
src/app/repository/base_repository.py
    def __exit__(self, exc_type, exc_value, traceback):
        # Se ejecuta siempre al cierre de la operación; en caso de éxito hace commit, sino hace rollback. Para finalizar cierra conexión y cursor.
        if exc_type:
            self.connection.rollback()
        else:
            self.connection.commit()
        self.cursor.close()
        self.connection.close()
_execute_query method · python · L21-L43 (23 LOC)
src/app/repository/base_repository.py
    def _execute_query(self, query, params=None, mode=None):
        """
        Ejecuta una consulta SQL.

        # Params:
        - query: la consulta SQL.
        - params: los parámetros para la consulta.
        - mode: 'one' para fetchone, 'all' para fetchall, None para operaciones tipo INSERT/UPDATE/DELETE.
        """
        try:
            if params is None:
                self.cursor.execute(query)
            else:
                self.cursor.execute(query, params)

            if mode == "one":
                return fetch_one(self.cursor)
            elif mode == "all":
                return fetch_all(self.cursor)
            elif mode is None:
                return {"rowcount": self.cursor.rowcount, "lastrowid": self.cursor.lastrowid}
        except:
            raise
TasksRepository class · python · L3-L40 (38 LOC)
src/app/repository/task_repository.py
class TasksRepository(BaseRepository):
    def get_tasks(self):
        query = """SELECT * FROM tasks;"""
        return self._execute_query(query, mode="all")

    def get_task_by_id(self, id: int):
        query = """SELECT * FROM tasks WHERE id = ?;"""
        return self._execute_query(query, params=(id,), mode="one")

    def get_tasks_by_status(self, status: int):
        query = """SELECT * FROM tasks WHERE status = ?"""
        return self._execute_query(query, params=(status,), mode="all")

    def create_task(self, name: str, begin_date: str, end_date: str, short_description: str, long_description: str, status: int):
        query = """
                INSERT INTO tasks (name, begin_date, end_date, short_description, long_description, status)
                VALUES (?, ?, ?, ?, ?, ?);
                """
        try:
            data = self._execute_query(query, mode=None, params=(name, begin_date, end_date, short_description, long_description, status))
            if data["
get_tasks method · python · L4-L6 (3 LOC)
src/app/repository/task_repository.py
    def get_tasks(self):
        query = """SELECT * FROM tasks;"""
        return self._execute_query(query, mode="all")
get_task_by_id method · python · L8-L10 (3 LOC)
src/app/repository/task_repository.py
    def get_task_by_id(self, id: int):
        query = """SELECT * FROM tasks WHERE id = ?;"""
        return self._execute_query(query, params=(id,), mode="one")
get_tasks_by_status method · python · L12-L14 (3 LOC)
src/app/repository/task_repository.py
    def get_tasks_by_status(self, status: int):
        query = """SELECT * FROM tasks WHERE status = ?"""
        return self._execute_query(query, params=(status,), mode="all")
create_task method · python · L16-L26 (11 LOC)
src/app/repository/task_repository.py
    def create_task(self, name: str, begin_date: str, end_date: str, short_description: str, long_description: str, status: int):
        query = """
                INSERT INTO tasks (name, begin_date, end_date, short_description, long_description, status)
                VALUES (?, ?, ?, ?, ?, ?);
                """
        try:
            data = self._execute_query(query, mode=None, params=(name, begin_date, end_date, short_description, long_description, status))
            if data["rowcount"] == 1:
                return {"id": data["lastrowid"]}
        except Exception:
            raise
Repobility analyzer · published findings · https://repobility.com
delete_task method · python · L28-L31 (4 LOC)
src/app/repository/task_repository.py
    def delete_task(self, id: int):
        query = """DELETE FROM tasks WHERE id = ?;"""
        data = self._execute_query(query, (id,))
        return data
update_task method · python · L33-L40 (8 LOC)
src/app/repository/task_repository.py
    def update_task(self, id: int, name: str, begin_date: str, end_date: str, short_description: str, long_description: str, status: int):
        query = """
                UPDATE tasks
                SET name = ?, begin_date = ?, end_date = ?,
                short_description = ?, long_description = ?, status = ?
                WHERE id = ?
                """
        return self._execute_query(query, (name, begin_date, end_date, short_description, long_description, status, id))
get_tasks function · python · L20-L31 (12 LOC)
src/app/routers/tasks.py
async def get_tasks(status: int | None = None):
    with TasksRepository() as repo:
        service = TasksService(repo)
        data = None
        if status is not None:
            try:
                data = service.list_tasks_by_status(status)
            except ValueError as e:
                raise HTTPException(400, detail=f"{e}")
        else:
            data = service.list_tasks()
        return data
create_task function · python · L38-L54 (17 LOC)
src/app/routers/tasks.py
async def create_task(task: Task):
    with TasksRepository() as repo:
        service = TasksService(repo)
        try:
            task = service.create_task_service(
                                    task.name,
                                    task.begin_date,
                                    task.end_date,
                                    task.short_description,
                                    task.long_description,
                                    task.status
                                    )
            return JSONResponse(content={"id": task}, status_code=201, headers={"Location": f"/tasks/{task}"})
        except ValueError as e:
            raise HTTPException(400, detail=str(e))
        except Exception as e:
            raise HTTPException(500, detail=str(e))
delete_task function · python · L61-L71 (11 LOC)
src/app/routers/tasks.py
async def delete_task(id: int):
    with TasksRepository() as repo:
        service = TasksService(repo)

        try:
            task = service.get_task(id)
        except NotFoundError:
            raise HTTPException(status_code=404, detail=f"No existe la tarea con ID: {id}")

        service.delete_task_service(task["id"])
        return Response(status_code=204)
update_task function · python · L78-L95 (18 LOC)
src/app/routers/tasks.py
async def update_task(task: TaskUpdate):
    try:
        with TasksRepository() as repo:
            service = TasksService(repo)
            service.update_task_service(
                task.id,
                task.name,
                task.begin_date,
                task.end_date,
                task.short_description,
                task.long_description,
                task.status
            )
            return Response(status_code=204)
    except ValueError as e:
        raise HTTPException(400, detail=str(e))
    except NotFoundError as e:
        raise HTTPException(404, detail=str(e))
TasksService class · python · L5-L70 (66 LOC)
src/app/services/tasks_service.py
class TasksService:
    def __init__(self, repo: TasksRepository):
        self.repo = repo

    def list_tasks(self):
        return self.repo.get_tasks()

    def get_task(self, id: int):
        task = self.repo.get_task_by_id(id)
        if not task:
            raise NotFoundError("La tarea no existe.")
        return task

    def list_tasks_by_status(self, status: int):
        if status not in (0, 1, 2):
            raise ValueError("Estado inválido.")
        return self.repo.get_tasks_by_status(status)

    def create_task_service(self, name: str, begin_date: str, end_date: str, short_description: str, long_description: str, status: int):
        if not name:
            raise ValueError("La tarea debe tener un nombre")

        if not validate_date(begin_date):
            raise ValueError("La fecha de inicio no es válida.")

        if not validate_date(end_date):
            raise ValueError("La fecha de finalización no es válida.")

        if status not in (0, 1, 2):
   
get_task method · python · L12-L16 (5 LOC)
src/app/services/tasks_service.py
    def get_task(self, id: int):
        task = self.repo.get_task_by_id(id)
        if not task:
            raise NotFoundError("La tarea no existe.")
        return task
Repobility (the analyzer behind this table) · https://repobility.com
list_tasks_by_status method · python · L18-L21 (4 LOC)
src/app/services/tasks_service.py
    def list_tasks_by_status(self, status: int):
        if status not in (0, 1, 2):
            raise ValueError("Estado inválido.")
        return self.repo.get_tasks_by_status(status)
create_task_service method · python · L23-L42 (20 LOC)
src/app/services/tasks_service.py
    def create_task_service(self, name: str, begin_date: str, end_date: str, short_description: str, long_description: str, status: int):
        if not name:
            raise ValueError("La tarea debe tener un nombre")

        if not validate_date(begin_date):
            raise ValueError("La fecha de inicio no es válida.")

        if not validate_date(end_date):
            raise ValueError("La fecha de finalización no es válida.")

        if status not in (0, 1, 2):
            raise ValueError("Estado inválido.")

        try:
            data = self.repo.create_task(name, begin_date, end_date, short_description, long_description, status)
            lastrowid = data.get("id")
            if lastrowid:
                return lastrowid
        except Exception:
            raise
delete_task_service method · python · L44-L52 (9 LOC)
src/app/services/tasks_service.py
    def delete_task_service(self, id: int):
        try:
            data = self.repo.delete_task(id)
            rowcount = data["rowcount"]
            if rowcount == 0:
                raise NotFoundError("La tarea no existe en la base de datos.")
            return True
        except Exception:
            raise
page 1 / 2next ›