# `PhoenixLiveGantt.Task`
[🔗](https://github.com/mdon/phoenix_live_gantt/blob/v0.4.0/lib/phoenix_live_gantt/task.ex#L1)

A Gantt task — one row in the chart, rendered as a horizontal bar
on the time axis.

The struct intentionally carries ONLY Gantt-relevant fields. Use
the `:extra` map for everything else — badges, action buttons,
sub-project metadata, custom rendering hints, application-specific
data — without bloating the core type.

## Required fields

  * `:id` — unique identifier within the chart (string or atom)
  * `:start` — `Date` (or `DateTime` / `NaiveDateTime` if you want
    time-of-day precision later)

## Optional schedule fields

  * `:end` — date the task ends.
    * `nil` AND no children → milestone (zero-duration; renders as
      a diamond)
    * `nil` AND has children (via `extra.parent_id` on other tasks)
      → date range is rolled up from descendants
    * otherwise → bar spans `start..end`

## Display

  * `:title` — label rendered in the sidebar
  * `:description` — optional longer text (not rendered by default)
  * `:color` — background CSS class (e.g. `"bg-primary"`)
  * `:text_color` — override CSS class; falls back to a contrast
    pick from `:color`
  * `:icon` — short inline glyph rendered next to the title
  * `:class` — extra CSS classes appended to the bar

## Project metadata

  * `:category` — phase / group label; tasks sharing a category
    cluster under a group header in the sidebar
  * `:status` — one of `:active`, `:tentative`, `:cancelled`,
    `:pending_approval`, `:blocked`, `:no_show` — drives bar
    opacity / line-through / pulse / etc.
  * `:progress_pct` — completion % (0-100); fills the bar
  * `:assignee` — owner name; shown in popover subtitle

## Extra map keys recognised by the renderer

  * `parent_id` — id of another task. If set, this task is a child
    of the referenced sub-project; the parent rolls up over its
    children's date range and can be expanded/collapsed.
  * `badges` — list of `%{content, corner, color, flash, ...}`
    maps drawn in the bar's corners.
  * `actions` — list of `%{icon, tooltip, phx_click, ...}` maps
    rendered as buttons inside the click popover.
  * `bus_stagger_outgoing_px` / `bus_stagger_incoming_px` —
    per-task override for the connector stagger width.
  * `bus_attach_mode` — per-task override for which side of the bar
    arrows connect to.

Anything you put in `:extra` that the renderer doesn't recognise
is silently passed through, so consumers can stuff their own
metadata next to it freely.

# `status`

```elixir
@type status() ::
  :active | :tentative | :cancelled | :pending_approval | :blocked | :no_show
```

# `t`

```elixir
@type t() :: %PhoenixLiveGantt.Task{
  assignee: String.t() | nil,
  category: String.t() | nil,
  class: String.t() | nil,
  color: String.t() | nil,
  description: String.t() | nil,
  end: Date.t() | DateTime.t() | NaiveDateTime.t() | nil,
  extra: map(),
  icon: String.t() | nil,
  id: term(),
  progress_pct: number() | nil,
  start: Date.t() | DateTime.t() | NaiveDateTime.t() | nil,
  status: status(),
  text_color: String.t() | nil,
  title: String.t() | nil
}
```

# `effective_end`

```elixir
@spec effective_end(t()) :: Date.t() | DateTime.t() | NaiveDateTime.t() | nil
```

Returns the effective end of a task — what the renderer uses to
compute the bar's right edge. Handles three cases:

  * Explicit `:end` set → returned as-is.
  * `:end` is nil with a `Date` start → start + 1 day (so a
    one-day task gets a visible bar).
  * `:end` is nil with a `DateTime` / `NaiveDateTime` start → start
    + 30 minutes (matches calendar semantics for time-of-day tasks).

# `new`

```elixir
@spec new(term(), term(), keyword()) :: t()
```

Convenience constructor: `PhoenixLiveGantt.Task.new("id", start_date, opts)`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
