(container: HTMLElement, projects: ProjectStats[])
| 1180 | } |
| 1181 | |
| 1182 | private async renderProjectStats(container: HTMLElement, projects: ProjectStats[]) { |
| 1183 | container.empty(); |
| 1184 | |
| 1185 | if (projects.length === 0) { |
| 1186 | container.createDiv({ |
| 1187 | cls: "stats-no-data stats-view__no-data", |
| 1188 | text: this.plugin.i18n.translate("views.stats.noProjectData"), |
| 1189 | }); |
| 1190 | return; |
| 1191 | } |
| 1192 | |
| 1193 | const formatTime = (minutes: number): string => { |
| 1194 | if (minutes < 60) return `${Math.round(minutes)}m`; |
| 1195 | const hours = Math.floor(minutes / 60); |
| 1196 | const mins = Math.round(minutes % 60); |
| 1197 | return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`; |
| 1198 | }; |
| 1199 | |
| 1200 | const formatDate = (dateString?: string): string => { |
| 1201 | if (!dateString) return this.plugin.i18n.translate("views.stats.notAvailable"); |
| 1202 | try { |
| 1203 | const date = new Date(dateString); |
| 1204 | return format(date, "MMM d, yyyy"); |
| 1205 | } catch { |
| 1206 | return this.plugin.i18n.translate("views.stats.notAvailable"); |
| 1207 | } |
| 1208 | }; |
| 1209 | |
| 1210 | for (const project of projects) { |
| 1211 | const projectClasses = [ |
| 1212 | "stats-project-item", |
| 1213 | "stats-view__project-item", |
| 1214 | "stats-view__project-item--clickable", |
| 1215 | ]; |
| 1216 | |
| 1217 | // Add special class for "No Project" items |
| 1218 | if (project.projectName === this.plugin.i18n.translate("views.stats.noProject")) { |
| 1219 | projectClasses.push("stats-view__project-item--no-project"); |
| 1220 | } |
| 1221 | |
| 1222 | const projectEl = container.createDiv({ |
| 1223 | cls: projectClasses.join(" "), |
| 1224 | }); |
| 1225 | |
| 1226 | // Make project clickable for drill-down |
| 1227 | this.registerDomEvent(projectEl, "click", () => { |
| 1228 | void this.openProjectDrilldown(project.projectName); |
| 1229 | }); |
| 1230 | |
| 1231 | // Project header with name and completion rate |
| 1232 | const headerEl = projectEl.createDiv({ cls: "stats-view__project-header" }); |
| 1233 | |
| 1234 | const nameEl = headerEl.createDiv({ cls: "project-name stats-view__project-name" }); |
| 1235 | nameEl.textContent = project.projectName; |
| 1236 | |
| 1237 | // Add click indicator |
| 1238 | headerEl.createDiv({ |
| 1239 | cls: "stats-view__click-indicator", |
no test coverage detected