The shared durations→dates schedule walk behind the project show page's Timeline (gantt) and Calendar tabs.
Flattens a project's assignment tree (sub-project descendants included) and
lays every item out sequentially from the project's schedule anchor via
PhoenixLiveGantt.Layout.sequential/2 — each task starts where the previous
one ends, honoring the task's effective weekday/weekend rule through
Project.eta_from/3. Both tabs render from this one walk so they can never
disagree about which dates a task occupies.
The walk is hour-precise (NaiveDateTime spans in UTC, matching the
project's stored started_at) and zoom/display-independent; consumers decide
how to render the spans (bars on a date axis, all-day calendar chips, …).
Summary
Types
One flattened schedule item: the assignment, its owning project (a
sub-project descendant belongs to the CHILD project), and its
linking-assignment parent (nil at top level).
Functions
The estimated hours for an assignment: its own duration override if set,
otherwise the underlying task's duration (nil-safe). Weekends are honored
per task_counts_weekends?/2.
Whether an assignment counts weekends — its own override, falling back to the project's setting.
Flattens project's assignment tree and computes each item's scheduled
span. Returns {items, layout}: items in flattened tree order (each
sub-project parent immediately followed by its descendants), layout a
map of item uuid → %{start: NaiveDateTime, end: NaiveDateTime}.
Types
@type item() :: %{ uuid: String.t(), assignment: PhoenixKitProjects.Schemas.Assignment.t(), project: PhoenixKitProjects.Schemas.Project.t(), parent_uuid: String.t() | nil, position: integer() | nil }
One flattened schedule item: the assignment, its owning project (a
sub-project descendant belongs to the CHILD project), and its
linking-assignment parent (nil at top level).
@type span() :: %{start: NaiveDateTime.t(), end: NaiveDateTime.t()}
Functions
@spec assignment_hours( PhoenixKitProjects.Schemas.Assignment.t(), PhoenixKitProjects.Schemas.Project.t() ) :: number()
The estimated hours for an assignment: its own duration override if set,
otherwise the underlying task's duration (nil-safe). Weekends are honored
per task_counts_weekends?/2.
@spec task_counts_weekends?( PhoenixKitProjects.Schemas.Assignment.t(), PhoenixKitProjects.Schemas.Project.t() ) :: boolean()
Whether an assignment counts weekends — its own override, falling back to the project's setting.
@spec tree(PhoenixKitProjects.Schemas.Project.t()) :: {[item()], %{required(String.t()) => span()}}
Flattens project's assignment tree and computes each item's scheduled
span. Returns {items, layout}: items in flattened tree order (each
sub-project parent immediately followed by its descendants), layout a
map of item uuid → %{start: NaiveDateTime, end: NaiveDateTime}.
Tasks are laid out in the order the user gave them (drag position) — a
manual order that violates a dependency is rendered honestly by the
consumers, not reordered here. A sub-project's span covers its children's
walk, so top-level spans stay correct even when a consumer only renders
the top level.