summaryrefslogtreecommitdiff
path: root/templates
diff options
context:
space:
mode:
authorT <t@tjp.lol>2026-02-23 11:27:12 -0700
committerT <t@tjp.lol>2026-02-23 11:30:58 -0700
commitf9b23f5c12eda13c6014f6291bdeecb77bb40141 (patch)
tree85a8cd0b4a44830c0176dfe3b81240a81bb21c8f /templates
parentb53c952fc8a054d935d90db2ccf3f0b897e6c771 (diff)
PDF design tweaksHEADmain
Diffstat (limited to 'templates')
-rw-r--r--templates/invoice.typ18
-rw-r--r--templates/timesheet.typ74
2 files changed, 39 insertions, 53 deletions
diff --git a/templates/invoice.typ b/templates/invoice.typ
index 7dacc59..b23f64b 100644
--- a/templates/invoice.typ
+++ b/templates/invoice.typ
@@ -44,7 +44,9 @@
]
]
- v(3em)
+ v(0.5em)
+ line(length: 100%, stroke: 0.4pt + rgb("#d1d5db"))
+ v(2em)
// Invoice title and number
grid(
@@ -91,16 +93,16 @@
#let professional-table() = {
table(
columns: (1fr, auto, auto, auto),
- stroke: (x, y) => if y == 0 or y == 1 { (bottom: 0.8pt + black) } else { none },
- inset: (x: 8pt, y: 12pt),
+ stroke: (x, y) => if y == 0 { (bottom: 0.8pt + black) } else if y > 1 { (top: 0.4pt + rgb("#e5e7eb")) } else { none },
+ inset: (x: 10pt, y: 12pt),
align: (left, center, center, right),
- column-gutter: 12pt,
+ fill: (x, y) => if y == 0 { rgb("#f8f9fa") } else { none },
// Header
- table.cell(fill: rgb("#f8f9fa"))[#text(weight: "bold", size: 9pt)[DESCRIPTION]],
- table.cell(fill: rgb("#f8f9fa"))[#text(weight: "bold", size: 9pt)[HOURS]],
- table.cell(fill: rgb("#f8f9fa"))[#text(weight: "bold", size: 9pt)[RATE]],
- table.cell(fill: rgb("#f8f9fa"))[#text(weight: "bold", size: 9pt)[AMOUNT]],
+ text(weight: "bold", size: 9pt)[DESCRIPTION],
+ text(weight: "bold", size: 9pt)[HOURS],
+ text(weight: "bold", size: 9pt)[RATE],
+ text(weight: "bold", size: 9pt)[AMOUNT],
// Line items
..data.line_items.map(item => (
diff --git a/templates/timesheet.typ b/templates/timesheet.typ
index e888615..d008bbf 100644
--- a/templates/timesheet.typ
+++ b/templates/timesheet.typ
@@ -35,7 +35,9 @@
]
]
- v(3em)
+ v(0.5em)
+ line(length: 100%, stroke: 0.4pt + rgb("#d1d5db"))
+ v(2em)
// Timesheet title
grid(
@@ -83,58 +85,40 @@
#let timesheet-table() = {
let grouped = group-by-date(data.entries)
let sorted-dates = grouped.keys().sorted()
-
- // Table header
+
table(
- columns: (auto, auto, auto, auto, 1fr, 1fr),
- stroke: (x, y) => if y == 0 { (bottom: 0.8pt + black) } else { none },
- inset: (x: 8pt, y: 4pt),
- align: (center, center, center, center, left, left),
- column-gutter: 8pt,
-
- // Header row with extra vertical padding
- table.cell(fill: rgb("#f8f9fa"), inset: (x: 8pt, y: 12pt))[#text(weight: "bold", size: 9pt)[DATE]],
- table.cell(fill: rgb("#f8f9fa"), inset: (x: 8pt, y: 12pt))[#text(weight: "bold", size: 9pt)[START]],
- table.cell(fill: rgb("#f8f9fa"), inset: (x: 8pt, y: 12pt))[#text(weight: "bold", size: 9pt)[END]],
- table.cell(fill: rgb("#f8f9fa"), inset: (x: 8pt, y: 12pt))[#text(weight: "bold", size: 9pt)[DURATION]],
- table.cell(fill: rgb("#f8f9fa"), inset: (x: 8pt, y: 12pt))[#text(weight: "bold", size: 9pt)[PROJECT]],
- table.cell(fill: rgb("#f8f9fa"), inset: (x: 8pt, y: 12pt))[#text(weight: "bold", size: 9pt)[DESCRIPTION]],
-
- // Data rows grouped by date
+ columns: (auto, auto, 1fr, 2fr),
+ stroke: none,
+ inset: (x: 10pt, y: 4pt),
+ align: (center, left, left, left),
+ fill: (x, y) => if y == 0 { rgb("#f8f9fa") } else { none },
+
+ // Header row
+ table.cell(inset: (x: 10pt, y: 12pt))[#text(weight: "bold", size: 9pt)[DATE]],
+ table.cell(inset: (x: 10pt, y: 12pt))[#text(weight: "bold", size: 9pt)[DURATION]],
+ table.cell(inset: (x: 10pt, y: 12pt))[#text(weight: "bold", size: 9pt)[PROJECT]],
+ table.cell(inset: (x: 10pt, y: 12pt))[#text(weight: "bold", size: 9pt)[DESCRIPTION]],
+
+ table.hline(stroke: 0.8pt + black),
+
..for date in sorted-dates {
let entries = grouped.at(date)
- let daily-total = entries.map(entry => entry.hours).sum()
-
- // Create rows for this date
- let date-rows = ()
-
- // Add all entries for this date
+ let rows = ()
for (i, entry) in entries.enumerate() {
- let date-text = if i == 0 { date } else { "" }
-
- date-rows.push((
- text(size: 9pt, weight: "medium")[#date-text],
- text(size: 9pt)[#entry.start_time],
- text(size: 9pt)[#entry.end_time],
- text(size: 9pt)[#entry.duration],
+ rows.push((
+ text(size: 9pt, weight: "medium")[#if i == 0 { date }],
+ text(size: 9pt)[#entry.duration #text(fill: gray)[(#entry.start_time–#entry.end_time)]],
text(size: 9pt)[#entry.project_name],
- text(size: 9pt)[#entry.description]
+ text(size: 9pt)[#entry.description],
))
}
-
- // Add daily subtotal row
- date-rows.push((
- table.cell(colspan: 3, align: right)[#text(size: 9pt, weight: "medium", fill: gray)[Daily Total:]],
- text(size: 9pt, weight: "medium")[#format-hours(daily-total)],
- table.cell(colspan: 2)[]
+ // Thin separator between days
+ rows.push((
+ table.cell(colspan: 4, inset: (x: 0pt, y: 0pt))[
+ #line(length: 100%, stroke: 0.4pt + rgb("#e5e7eb"))
+ ],
))
-
- // Add separator line after each day
- date-rows.push((
- table.cell(colspan: 6, stroke: (top: 0.5pt + gray))[#v(0.1em)],
- ))
-
- date-rows
+ rows
}.flatten()
)
}