Move invoice PAID stamp inline to header; add email to company block

- Remove watermark overlay layer; PAID badge now sits centered between
  the header row and the accent rule so it never obscures line items
- Add PrimaryContactEmail to company info block in header
- Remove ComposePaidStamp helper (no longer needed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 16:39:11 -04:00
parent b8057295ec
commit 66c3febd7a
@@ -98,12 +98,7 @@ public class PdfService : IPdfService
page.DefaultTextStyle(x => x.FontSize(10).FontFamily("Arial")); page.DefaultTextStyle(x => x.FontSize(10).FontFamily("Arial"));
page.Header().Element(c => ComposeInvoiceHeader(c, companyLogo, companyInfo, accentColor, invoiceDto)); page.Header().Element(c => ComposeInvoiceHeader(c, companyLogo, companyInfo, accentColor, invoiceDto));
page.Content().Layers(layers => page.Content().Element(c => ComposeInvoiceContent(c, invoiceDto, accentColor, template));
{
layers.PrimaryLayer().Element(c => ComposeInvoiceContent(c, invoiceDto, accentColor, template));
if (invoiceDto.Status == InvoiceStatus.Paid)
layers.Layer().Element(c => ComposePaidStamp(c));
});
page.Footer().AlignCenter().Text(text => page.Footer().AlignCenter().Text(text =>
{ {
text.CurrentPageNumber(); text.CurrentPageNumber();
@@ -148,6 +143,8 @@ public class PdfService : IPdfService
column.Item().Text(cityLine).FontSize(9).FontColor(Colors.Grey.Darken1); column.Item().Text(cityLine).FontSize(9).FontColor(Colors.Grey.Darken1);
if (!string.IsNullOrWhiteSpace(companyInfo.Phone)) if (!string.IsNullOrWhiteSpace(companyInfo.Phone))
column.Item().Text(FormatPhoneNumber(companyInfo.Phone)).FontSize(9).FontColor(Colors.Grey.Darken1); column.Item().Text(FormatPhoneNumber(companyInfo.Phone)).FontSize(9).FontColor(Colors.Grey.Darken1);
if (!string.IsNullOrWhiteSpace(companyInfo.PrimaryContactEmail))
column.Item().Text(companyInfo.PrimaryContactEmail).FontSize(9).FontColor(Colors.Grey.Darken1);
}); });
row.RelativeItem().AlignRight().Column(column => row.RelativeItem().AlignRight().Column(column =>
@@ -161,29 +158,18 @@ public class PdfService : IPdfService
}); });
}); });
col.Item().PaddingVertical(4).LineHorizontal(1).LineColor(accentColor); if (invoice.Status == InvoiceStatus.Paid)
{
col.Item().PaddingVertical(6).AlignCenter().Column(badge =>
{
badge.Item().AlignCenter().Border(2).BorderColor(Colors.Green.Darken1)
.PaddingVertical(4).PaddingHorizontal(24)
.Text("PAID").FontSize(18).Bold().FontColor(Colors.Green.Darken1).LetterSpacing(0.15f);
}); });
} }
/// <summary> col.Item().PaddingVertical(4).LineHorizontal(1).LineColor(accentColor);
/// Renders a semi-transparent angled PAID stamp centred over the invoice content layer. });
/// Uses QuestPDF layout primitives (AlignCenter, AlignMiddle, Rotate, Opacity) so no
/// external Skia/SkiaSharp dependency is needed.
/// </summary>
private static void ComposePaidStamp(IContainer container)
{
container
.AlignCenter()
.AlignMiddle()
.Rotate(-45f)
.Border(2)
.BorderColor(Colors.Green.Lighten2)
.PaddingVertical(10)
.PaddingHorizontal(20)
.Text("PAID")
.FontSize(52)
.Bold()
.FontColor(Colors.Green.Lighten2);
} }
/// <summary> /// <summary>