using QuestPDF.Fluent; using QuestPDF.Infrastructure; using QuestPDF.Helpers; using Google.Protobuf.WellKnownTypes; using PSTW_CentralSystem.Models; using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator { public class TarBallPDF ( string stateName, string stationID, string locationName, string longitude, string latitude, string dateSample, string timeSample, string classifyID, //bool tarBallYes, bool tarBallNo, bool isSand, bool isNonSandy, bool isCoquina, string photoPath1, string photoPath2, string photoPath3, string photoPath4, string? photoPath5, string? photoPath6, string? photoPath7, string? photoPath8, string? optionalName1, string? optionalName2, string? optionalName3, string? optionalName4, string firstSampler, string fullName, string levelName ) : IDocument { //have to be arranged accordingly(?) private readonly string _stateName = stateName; private readonly string _stationId = stationID; private readonly string _locationName = locationName; private readonly string _longitude = longitude; private readonly string _latitude = latitude; private readonly string _dateSample = dateSample; private readonly string _timeSample = timeSample; private readonly string _classifyID = classifyID; //private bool TarBallYes => _classifyID != "NO"; //private bool TarBallNo => _classifyID == "NO"; //private bool IsSand => _classifyID == "SD"; //private bool IsNonSandy => _classifyID == "NS"; //private bool IsCoquina => _classifyID == "CO"; private readonly string _photoPath1 = photoPath1; private readonly string _photoPath2 = photoPath2; private readonly string _photoPath3 = photoPath3; private readonly string _photoPath4 = photoPath4; private readonly string? _photoPath5 = photoPath5; private readonly string? _photoPath6 = photoPath6; private readonly string? _photoPath7 = photoPath7; private readonly string? _photoPath8 = photoPath8; private readonly string? _optionalName1 = optionalName1; private readonly string? _optionalName2 = optionalName2; private readonly string? _optionalName3 = optionalName3; private readonly string? _optionalName4 = optionalName4; private readonly string _firstSampler = firstSampler; private readonly string _fullName = fullName; private readonly string _levelName = levelName; private Image? LoadImage(string? imagePath) { if (string.IsNullOrEmpty(imagePath)) //check if photo is missing { return null; // returns 'nothing' (safe) } try { return Image.FromFile(imagePath); //load photo } catch { return null; //if loading fails, returns 'nothing' (safe) } } public DocumentMetadata GetMetadata() => new() { Title = "TARBALL SAMPLING FORM", Author = "PAKAR SCIENO TW Integrated Environmental Solutions", Subject = "Environmental Survey and Observations" }; // Compose the PDF content public void Compose(IDocumentContainer container) { container.Page(page => { // Page Setup page.Size(PageSizes.A4); page.Margin(1.1f, Unit.Centimetre); page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10)); //HEADER SECTION ========================================================================== //will be included in each page page.Header().Row(row => { row.RelativeItem(1).Element(CellStyle) .AlignMiddle() .AlignCenter() .Image("wwwroot/assets/images/pstw-logo.jpg") .FitArea(); row.RelativeItem(1).Element(CellStyle) .AlignMiddle() .AlignCenter() .Text("TARBALL SAMPLING FORM") .FontSize(16) .FontColor("#4B0082"); row.RelativeItem(1).Column(column => { column.Spacing(0); column.Item().Row(innerRow => { innerRow.RelativeItem(1).Element(CellStyle).Text("Document:") .AlignLeft(); innerRow.RelativeItem(1).Element(CellStyle).Text("F-MM06") .AlignLeft().Bold(); }); column.Item().Row(innerRow => { innerRow.RelativeItem(1).Element(CellStyle).Text("Effective Date:") .AlignLeft(); innerRow.RelativeItem(1).Element(CellStyle).Text("1 April 2025") .AlignLeft(); }); column.Item().Row(innerRow => { innerRow.RelativeItem(1).Element(CellStyle).Text("Revision No.") .AlignLeft(); innerRow.RelativeItem(1).Element(CellStyle).Text("02") .AlignLeft(); }); }); static IContainer CellStyle(IContainer container) => container.Border(0.5f).Padding(5); }); //HEADER SECTION END ========================================================================== // CONTENT SECTION ============================================================================ page.Content().Column(column => { // Observations Table column.Item().Element(container => { container .PaddingTop(20) .PaddingBottom(10) .Text("Please be informed that we have observed the following conditions:"); }); column.Item().Table(table => { column.Spacing(0); table.ColumnsDefinition(columns => { columns.RelativeColumn(3); columns.RelativeColumn(3); }); table.Cell() .Background(Colors.Grey.Lighten2).Element(CellStyle).Text("STATE") .Bold(); table.Cell().Element(CellStyle).Text(_stateName); table.Cell() .Background(Colors.Grey.Lighten2).Element(CellStyle).Text("STATION ID") .Bold(); table.Cell().Element(CellStyle).Text(_stationId); table.Cell() .Background(Colors.Grey.Lighten2).Element(CellStyle).Text("LOCATION") .Bold(); table.Cell().Element(CellStyle).Text(_locationName); table.Cell() .Background(Colors.Grey.Lighten2).Element(CellStyle).Text("TARBALL SURVEY LOCATION LONGITUDE & LATITUDE") .Bold(); table.Cell().Element(CellStyle).Text($"{_longitude}, {_latitude}"); table.Cell() .Background(Colors.Grey.Lighten2).Element(CellStyle).Text("DATE / TIME") .Bold(); table.Cell().Element(CellStyle).Text($"{_dateSample:yyyy-MM-dd} {_timeSample:hh\\:mm\\:ss}"); }); column.Spacing(3); // Survey Findings ======================================================================================= column.Item() .PaddingTop(10) .PaddingBottom(10) .Text("SURVEY FINDING:") .Bold().FontSize(12); column.Item() .PaddingBottom(10) .Text(text => { text.Span("Tar Ball: ").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "NO" ? " ☐ YES ☑ NO" : " ☑ YES ☐ NO").Style(TextStyle.Default.FontSize(10)); }); column.Item() .PaddingBottom(10) .Text("If YES, Tar Ball falls under the Classification of:") .FontSize(10); column.Item() .PaddingBottom(10) .Text(text => { text.Span(_classifyID == "SD" ? "☑ Sand " : "☐ Sand ").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "NS" ? " ☑ Non-sandy " : " ☐ Non-sandy ").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "CQ" ? "☑ Coquina" : "☐ Coquina").Style(TextStyle.Default.FontSize(10)); }); column.Item() .PaddingBottom(10) .Text("*tick wherever applicable") .Italic(); // Photos Section Title column.Item() .PaddingBottom(5) .Text("PHOTOGRAPHS OF SAMPLING") .AlignCenter() .Bold() .FontSize(14); // Photos Section column.Item().Table(table => { column.Spacing(0); table.ColumnsDefinition(columns => { columns.RelativeColumn(1); columns.RelativeColumn(1); }); // Row 1: Photos ==================================== table.Cell().Element(CellStyle).Height(150) .Image(LoadImage(_photoPath1) ?? null) // Loads image or uses null. if exist, fill cell. if null, cell stay empty .FitArea(); table.Cell().Element(CellStyle).Height(150) .Image(LoadImage(_photoPath2) ?? null) .FitArea(); // Row 2: Captions for figure 1 & 2 ================= table.Cell().Element(CellStyle) .Text("Figure 1: Left Side Coastal View") .FontSize(12).AlignLeft(); table.Cell().Element(CellStyle) .Text("Figure 2: Right Side Coastal View") .FontSize(12).AlignLeft(); // Row 3 ============================================= table.Cell().Element(CellStyle).Height(150) .Image(LoadImage(_photoPath3) ?? null) // Just pass null if no image .FitArea(); table.Cell().Element(CellStyle).Height(150) .Image(LoadImage(_photoPath4) ?? null) // Just pass null if no image .FitArea(); // Row 4: Captions for figure 3 & 4 ================= table.Cell().Element(CellStyle) .Text("Figure 3: Drawing Vertical Lines") .FontSize(12).AlignLeft(); table.Cell().Element(CellStyle) .Text("Figure 4: Drawing Horizontal Lines (Racking)") .FontSize(12).AlignLeft(); }); // Page Break column.Item().PageBreak(); column.Spacing(3); // Additional Photos Section column.Item().Table(table => { column.Spacing(3); table.ColumnsDefinition(columns => { columns.RelativeColumn(1); columns.RelativeColumn(1); }); // Helper function to safely add image cells void AddOptionalImageCell(string imagePath) { table.Cell().Element(CellStyle).Height(150).Element(cell => { var image = LoadImage(imagePath); if (image != null) { cell.Image(image).FitArea(); } // If null, leaves an empty cell }); } // Row 1: Optional images 5 & 6 AddOptionalImageCell(_photoPath5); AddOptionalImageCell(_photoPath6); // Row 2: Captions table.Cell().Element(CellStyle) .Text(string.IsNullOrEmpty(_photoPath5) ? "" : $"Figure 5: {_optionalName1}") .FontSize(12).AlignLeft(); table.Cell().Element(CellStyle) .Text(string.IsNullOrEmpty(_photoPath6) ? "" : $"Figure 6: {_optionalName2}") .FontSize(12).AlignLeft(); // Row 3: Optional images 7 & 8 AddOptionalImageCell(_photoPath7); AddOptionalImageCell(_photoPath8); // Row 4: Captions table.Cell().Element(CellStyle) .Text(string.IsNullOrEmpty(_photoPath7) ? "" : $"Figure 7: {_optionalName3}") .FontSize(12).AlignLeft(); table.Cell().Element(CellStyle) .Text(string.IsNullOrEmpty(_photoPath8) ? "" : $"Figure 8: {_optionalName4}") .FontSize(12).AlignLeft(); }); // Note Section column.Item() .PaddingTop(10) .PaddingBottom(20) .Text("* If there are any event observe at the current station it is compulsory to add optional photo with description (figure 5 to figure 8)") .Bold() .FontSize(10) .AlignLeft(); // Signature Section column.Item().Table(table => { table.ColumnsDefinition(columns => { //the overall layout of the authorization section columns.RelativeColumn(2); columns.RelativeColumn(1); columns.RelativeColumn(2); columns.RelativeColumn(1); columns.RelativeColumn(1); }); table.Cell().RowSpan(2).Element(CellStyle) .Text(text => { text.Span("REPORTED BY: ").Bold().FontSize(12); text.Span(_firstSampler).FontSize(12); }); table.Cell().Element(CellStyle).Text("Signature").FontSize(12); table.Cell().Element(CellStyle).Text(""); table.Cell().Element(CellStyle).Text("Date").FontSize(12); table.Cell().Element(CellStyle).Text($"{_dateSample:yyyyMMdd}").FontSize(12); table.Cell().Element(CellStyle).Text("Designation").FontSize(12); table.Cell().ColumnSpan(3).Element(CellStyle).Text(_levelName).FontSize(12); table.Cell().RowSpan(2).Element(CellStyle) .Text(text => { text.Span("CHECKED BY: ").Bold().FontSize(12); text.Span("RIFAIE AZHARI").FontSize(12); }); table.Cell().Element(CellStyle).Text("Signature").FontSize(12); table.Cell().ColumnSpan(2).Element(CellStyle).Text(""); table.Cell().Element(CellStyle).Text(""); table.Cell().Element(CellStyle).Text("Designation").FontSize(12); table.Cell().ColumnSpan(3).Element(CellStyle).Text("Executive").FontSize(12); table.Cell().RowSpan(2).Element(CellStyle) .Text(text => { text.Span("VERIFIED BY: ").Bold().FontSize(12); text.Span("J SOMU").FontSize(12); }); table.Cell().Element(CellStyle).Text("Signature").FontSize(12); table.Cell().ColumnSpan(2).Element(CellStyle).Text(""); table.Cell().Element(CellStyle).Text(""); table.Cell().Element(CellStyle).Text("Designation").FontSize(12); table.Cell().ColumnSpan(3).Element(CellStyle).Text("Technical Manager").FontSize(12); }); }); // Footer Section page.Footer().AlignCenter().Text(text => { }); static IContainer CellStyle(IContainer container) => container.Border(0.5f).Padding(5); }); } } }