git_contribution_analyzer/
export.rs

1use crate::app::App;
2use std::{error::Error, fs, path::Path};
3
4pub fn export_html_report(app: &App, output_path: &Path) -> Result<(), Box<dyn Error>> {
5    let mut html = String::from(
6        r#"<!DOCTYPE html>
7<html lang="en">
8<head>
9    <meta charset="UTF-8">
10    <meta name="viewport" content="width=device-width, initial-scale=1.0">
11    <title>Git Contribution Analysis Report</title>
12    <style>
13        body {
14            font-family: Arial, sans-serif;
15            line-height: 1.6;
16            margin: 0;
17            padding: 20px;
18            color: #333;
19        }
20        h1, h2 {
21            color: #2c3e50;
22        }
23        table {
24            border-collapse: collapse;
25            width: 100%;
26            margin-bottom: 20px;
27        }
28        th, td {
29            text-align: left;
30            padding: 12px;
31            border-bottom: 1px solid #ddd;
32        }
33        th {
34            background-color: #f2f2f2;
35            font-weight: bold;
36        }
37        tr:hover {
38            background-color: #f5f5f5;
39        }
40        .report-date {
41            color: #7f8c8d;
42            font-style: italic;
43            margin-bottom: 30px;
44        }
45        .container {
46            max-width: 1200px;
47            margin: 0 auto;
48        }
49        .repo-section {
50            margin-bottom: 40px;
51            border: 1px solid #eee;
52            padding: 20px;
53            border-radius: 5px;
54        }
55    </style>
56</head>
57<body>
58    <div class="container">
59        <h1>Git Contribution Analysis Report</h1>
60        <p class="report-date">Generated on: "#,
61    )
62    .to_string();
63
64    use chrono::Local;
65    html.push_str(&Local::now().format("%Y-%m-%d %H:%M:%S").to_string());
66
67    html.push_str(
68        r#"</p>
69        
70        <div class="repo-section">
71            <h2>Summary Across All Repositories</h2>
72            <table>
73                <thead>
74                    <tr>
75                        <th>Author</th>
76                        <th>Email</th>
77                        <th>Total Commits</th>
78                        <th>Lines Added</th>
79                        <th>Lines Deleted</th>
80                        <th>Overall %</th>
81                        <th>Preferred Repo</th>
82                        <th>Preferred %</th>
83                    </tr>
84                </thead>
85                <tbody>
86"#,
87    );
88
89    for summary in &app.author_summaries {
90        html.push_str(&format!(
91            r#"
92                    <tr>
93                        <td>{}</td>
94                        <td>{}</td>
95                        <td>{}</td>
96                        <td>{}</td>
97                        <td>{}</td>
98                        <td>{:.2}%</td>
99                        <td>{}</td>
100                        <td>{:.2}%</td>
101                    </tr>
102"#,
103            summary.author,
104            summary.email,
105            summary.total_commits,
106            summary.total_lines_added,
107            summary.total_lines_deleted,
108            summary.overall_contribution_percent,
109            summary.preferred_repo,
110            summary.preferred_repo_percent
111        ));
112    }
113
114    html.push_str(
115        r#"
116                </tbody>
117            </table>
118        </div>
119"#,
120    );
121
122    for repo_name in &app.repositories {
123        html.push_str(&format!(
124            r#"
125        <div class="repo-section">
126            <h2>Repository: {}</h2>
127            <table>
128                <thead>
129                    <tr>
130                        <th>Author</th>
131                        <th>Email</th>
132                        <th>Commits</th>
133                        <th>Lines Added</th>
134                        <th>Lines Deleted</th>
135                        <th>Contribution %</th>
136                    </tr>
137                </thead>
138                <tbody>
139"#,
140            repo_name
141        ));
142
143        if let Some(contributions) = app.contributions.get(repo_name) {
144            for contrib in contributions {
145                html.push_str(&format!(
146                    r#"
147                    <tr>
148                        <td>{}</td>
149                        <td>{}</td>
150                        <td>{}</td>
151                        <td>{}</td>
152                        <td>{}</td>
153                        <td>{:.2}%</td>
154                    </tr>
155"#,
156                    contrib.author,
157                    contrib.email,
158                    contrib.commits,
159                    contrib.lines_added,
160                    contrib.lines_deleted,
161                    contrib.contribution_percent
162                ));
163            }
164        }
165
166        html.push_str(
167            r#"
168                </tbody>
169            </table>
170        </div>
171"#,
172        );
173    }
174
175    html.push_str(
176        r#"
177    </div>
178</body>
179</html>
180"#,
181    );
182
183    fs::write(output_path, html)?;
184
185    Ok(())
186}