|
1 | 1 | package service |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "api/types" |
| 4 | + "bytes" |
5 | 5 | "context" |
6 | 6 | "fmt" |
7 | 7 | "sort" |
8 | 8 | "strings" |
| 9 | + |
| 10 | + "api/types" |
| 11 | + |
| 12 | + "github.com/go-pdf/fpdf" |
9 | 13 | ) |
10 | 14 |
|
11 | 15 | func (s *Service) ConvertRetrospectiveToMarkdown(ctx context.Context, retro *types.Retrospective) string { |
@@ -44,3 +48,73 @@ func (s *Service) ConvertRetrospectiveToMarkdown(ctx context.Context, retro *typ |
44 | 48 |
|
45 | 49 | return sb.String() |
46 | 50 | } |
| 51 | + |
| 52 | +func (s *Service) ConvertRetrospectiveToPDF(ctx context.Context, retro *types.Retrospective) ([]byte, error) { |
| 53 | + pdf := fpdf.New("P", "mm", "A4", "") |
| 54 | + pdf.SetMargins(20, 20, 20) |
| 55 | + pdf.AddPage() |
| 56 | + |
| 57 | + // Title |
| 58 | + pdf.SetFont("Arial", "B", 24) |
| 59 | + pdf.Cell(0, 12, "Simple Retro") |
| 60 | + pdf.Ln(16) |
| 61 | + |
| 62 | + // Subtitle (retrospective name) |
| 63 | + pdf.SetFont("Arial", "B", 18) |
| 64 | + pdf.Cell(0, 10, retro.Name) |
| 65 | + pdf.Ln(12) |
| 66 | + |
| 67 | + // Description |
| 68 | + if retro.Description != "" { |
| 69 | + pdf.SetFont("Arial", "", 12) |
| 70 | + pdf.MultiCell(0, 6, retro.Description, "", "", false) |
| 71 | + pdf.Ln(4) |
| 72 | + } |
| 73 | + |
| 74 | + // Created at |
| 75 | + pdf.SetFont("Arial", "I", 10) |
| 76 | + pdf.SetTextColor(128, 128, 128) |
| 77 | + pdf.Cell(0, 6, "Created on "+retro.CreatedAt.Format("January 2, 2006 at 3:04 PM")) |
| 78 | + pdf.Ln(10) |
| 79 | + pdf.SetTextColor(0, 0, 0) |
| 80 | + |
| 81 | + // Separator line |
| 82 | + pdf.Line(20, pdf.GetY(), 190, pdf.GetY()) |
| 83 | + pdf.Ln(8) |
| 84 | + |
| 85 | + // Questions and answers |
| 86 | + for _, question := range retro.Questions { |
| 87 | + // Question title |
| 88 | + pdf.SetFont("Arial", "B", 14) |
| 89 | + pdf.MultiCell(0, 8, question.Text, "", "", false) |
| 90 | + pdf.Ln(4) |
| 91 | + |
| 92 | + // Sort answers by position |
| 93 | + answers := make([]types.Answer, len(question.Answers)) |
| 94 | + copy(answers, question.Answers) |
| 95 | + sort.Slice(answers, func(i, j int) bool { |
| 96 | + return answers[i].Position < answers[j].Position |
| 97 | + }) |
| 98 | + |
| 99 | + pdf.SetFont("Arial", "", 11) |
| 100 | + for _, answer := range answers { |
| 101 | + var text string |
| 102 | + if answer.Votes > 0 { |
| 103 | + text = fmt.Sprintf(" - %s (%d votes)", answer.Text, answer.Votes) |
| 104 | + } else { |
| 105 | + text = fmt.Sprintf(" - %s", answer.Text) |
| 106 | + } |
| 107 | + pdf.MultiCell(0, 6, text, "", "", false) |
| 108 | + pdf.Ln(1) |
| 109 | + } |
| 110 | + pdf.Ln(6) |
| 111 | + } |
| 112 | + |
| 113 | + var buf bytes.Buffer |
| 114 | + err := pdf.Output(&buf) |
| 115 | + if err != nil { |
| 116 | + return nil, err |
| 117 | + } |
| 118 | + |
| 119 | + return buf.Bytes(), nil |
| 120 | +} |
0 commit comments