Guest User

Untitled

a guest
Jan 16th, 2024
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.07 KB | None | 0 0
  1. import { Component, Input, OnChanges, OnInit, ViewChild } from '@angular/core';
  2. import { ChartComponent as ApexChartComponent } from "ng-apexcharts";
  3. import {
  4. ApexOptions,
  5. ApexXAxis,
  6. ApexDataLabels,
  7. ApexTooltip,
  8. ApexStroke,
  9. ApexAxisChartSeries,
  10. ApexChart,
  11. ChartType,
  12. ChartComponent
  13. } from "ng-apexcharts";
  14. import { GraphData } from 'src/app/models/item.model';
  15.  
  16. interface CustomApexChart extends ApexChart {
  17. type: ChartType;
  18. }
  19.  
  20. export type ChartOptions = {
  21. series: ApexAxisChartSeries;
  22. chart: CustomApexChart;
  23. xaxis: Partial<ApexXAxis>;
  24. stroke: Partial<ApexStroke>;
  25. tooltip: Partial<ApexTooltip>;
  26. dataLabels: Partial<ApexDataLabels>;
  27. };
  28.  
  29. @Component({
  30. selector: 'app-line-chart',
  31. template: '<div #lineChart><apx-chart [series]="chartOptions.series" [chart]="chartOptions.chart" [xaxis]="chartOptions.xaxis" [stroke]="chartOptions.stroke" [tooltip]="chartOptions.tooltip" [dataLabels]="chartOptions.dataLabels"></apx-chart></div>',
  32. })
  33. export class LineChartComponent implements OnChanges, OnInit {
  34. @ViewChild('lineChart', { static: true }) lineChart!: ApexChartComponent;
  35. public chartOptions: ChartOptions = {
  36. series: [
  37. {
  38. name: 'Revenus',
  39. data: [0, 0, 0, 0, 0, 0, 0]
  40. }
  41. ],
  42. chart: {
  43. height: 350,
  44. type: 'line' as ChartType,
  45. zoom: {
  46. enabled: false
  47. },
  48. toolbar: {
  49. show: false
  50. },
  51. animations: {
  52. enabled: false
  53. }
  54. },
  55. dataLabels: {
  56. enabled: false
  57. },
  58. stroke: {
  59. curve: 'smooth',
  60. width: 2
  61. },
  62. xaxis: {
  63. type: 'datetime',
  64. categories: ['01/01', '02/01', '03/01', '04/01', '05/01', '06/01', '07/01'],
  65. },
  66. tooltip: {
  67. enabled: true,
  68. x: {
  69. show: true,
  70. format: 'dd MMM'
  71. }
  72. }
  73. } as ChartOptions;
  74.  
  75. @Input() data!: GraphData | null | undefined;
  76. @Input() graphScale!: string | null | undefined;
  77.  
  78.  
  79. ngOnChanges(): void {
  80. console.log(this.data);
  81. this.initializeChartOptions();
  82. }
  83.  
  84. ngOnInit(): void {
  85. console.log(this.data);
  86. this.initializeChartOptions();
  87. }
  88.  
  89. private initializeChartOptions(): void {
  90. if (!this.data || !this.data.data || !this.data.data.events) {
  91. return;
  92. }
  93.  
  94. let { montants: revenues, dates: labels } = this.convertirListe(this.cleanData(this.data.data.events, this.graphScale || 'week'));
  95. revenues = this.smoothData(revenues);
  96. labels.sort(this.compareDates);
  97.  
  98. labels = this.formatLabels(labels, this.graphScale || 'week');
  99.  
  100. this.chartOptions.series = [
  101. {
  102. name: 'Revenus',
  103. data: revenues
  104. }
  105. ];
  106. this.chartOptions.xaxis.categories = labels;
  107. }
  108.  
  109.  
  110. constructor() {
  111. if (!this.data || !this.data.data || !this.data.data.events) {
  112. return;
  113. }
  114.  
  115. let { montants: revenues, dates: labels } = this.convertirListe(this.cleanData(this.data.data.events, this.graphScale || 'week'));
  116. revenues = this.smoothData(revenues);
  117. labels.sort(this.compareDates);
  118.  
  119. labels = this.formatLabels(labels, this.graphScale || 'week');
  120.  
  121. this.chartOptions = {
  122. series: [
  123. {
  124. name: 'Revenus',
  125. data: revenues
  126. }
  127. ],
  128. chart: {
  129. height: 350,
  130. type: 'line',
  131. zoom: {
  132. enabled: false
  133. },
  134. toolbar: {
  135. show: false
  136. },
  137. animations: {
  138. enabled: false
  139. }
  140. },
  141. dataLabels: {
  142. enabled: false
  143. },
  144. stroke: {
  145. curve: 'smooth',
  146. width: 2
  147. },
  148. xaxis: {
  149. type: 'datetime',
  150. categories: labels,
  151. },
  152. tooltip: {
  153. enabled: true,
  154. x: {
  155. show: true,
  156. format: 'dd MMM'
  157. }
  158. }
  159. } as ChartOptions;
  160. }
  161.  
  162.  
  163. public cleanData(data: any, scale: string): any {
  164. if (scale == 'year') {
  165. return this.yearStats(data);
  166. } else if (scale == 'month') {
  167. return this.monthStats(data);
  168. } else if (scale == 'week') {
  169. return this.weekStats(data);
  170. }
  171.  
  172. return data;
  173. }
  174.  
  175. public monthToDay(month: number, year: number): number {
  176. if (month == 2) {
  177. if (year % 4 == 0) {
  178. return 29;
  179. } else {
  180. return 28;
  181. }
  182. }
  183.  
  184. if (month == 4 || month == 6 || month == 9 || month == 11) {
  185. return 30;
  186. }
  187.  
  188. return 31;
  189. }
  190.  
  191. private yearStats(events: { amount: number; created_at: string }[]) {
  192. let monthlyTotals: { [key: string]: number } = {};
  193.  
  194. for (const event of events) {
  195. const time = new Date(event.created_at);
  196. const formattedDate = `${time.getMonth() + 1}/${time.getFullYear()}`;
  197. if (!monthlyTotals[formattedDate]) {
  198. monthlyTotals[formattedDate] = 0;
  199. }
  200. monthlyTotals[formattedDate] = event.amount;
  201.  
  202. }
  203.  
  204. for (let i = 1; i <= 12; i++) {
  205. const monthYear = `${i}/${new Date().getFullYear()}`;
  206. if (!monthlyTotals[monthYear]) {
  207. if (this.getPreviousMonth(monthYear) in monthlyTotals) {
  208. monthlyTotals[monthYear] = monthlyTotals[this.getPreviousMonth(monthYear)];
  209. } else {
  210. monthlyTotals[monthYear] = 0;
  211. }
  212. }
  213. }
  214. const sortedMonths = Object.keys(monthlyTotals).map(key => {
  215. const [month, year] = key.split('/').map(Number);
  216. return new Date(year, month - 1);
  217. }).sort((a, b) => a.getTime() - b.getTime());
  218.  
  219. //order by month
  220. let ordered: { [key: string]: number } = {};
  221. sortedMonths.forEach(date => {
  222. const monthYearKey = `${date.getMonth() + 1}/${date.getFullYear()}`;
  223. ordered[monthYearKey] = monthlyTotals[monthYearKey];
  224. });
  225.  
  226. monthlyTotals = ordered;
  227.  
  228. return Object.keys(monthlyTotals).map(key => {
  229. return { amount: monthlyTotals[key], created_at: key };
  230. });
  231. }
  232.  
  233. public getPreviousMonth(monthYear: string): string {
  234. const [month, year] = monthYear.split('/').map(Number);
  235.  
  236. if (month === 1) {
  237. return `12/${year - 1}`;
  238. } else {
  239. return `${month - 1}/${year}`;
  240. }
  241. }
  242.  
  243. public getNextMonth(monthYear: string): string {
  244. const [month, year] = monthYear.split('/').map(Number);
  245.  
  246. if (month === 12) {
  247. return `1/${year + 1}`;
  248. } else {
  249. return `${month + 1}/${year}`;
  250. }
  251. }
  252.  
  253. public monthStats(events: { amount: number; created_at: string }[]) {
  254. const currentDate = new Date();
  255. const oneDayMilliseconds = 24 * 60 * 60 * 1000; // Milliseconds in a day
  256.  
  257. // Create a dictionary to store daily amounts
  258. const dict: { [key: string]: number } = {};
  259.  
  260. // Update dictionary with actual amounts from events
  261. for (const event of events) {
  262. const time = new Date(event.created_at);
  263. const formattedDate = `${time.getDate()}/${time.getMonth() + 1}/${time.getFullYear()}`;
  264. dict[formattedDate] = event.amount;
  265. }
  266.  
  267. // Initialize dictionary with 0 values for the last 31 days
  268. for (let i = 30; i >= 0; i--) {
  269. const day = new Date(currentDate.getTime() - i * oneDayMilliseconds);
  270. const formattedDate = `${day.getDate()}/${day.getMonth() + 1}/${day.getFullYear()}`;
  271. if (!dict[formattedDate]) {
  272. dict[formattedDate] = 0;
  273. }
  274. }
  275.  
  276. // Convert dictionary to array of objects
  277. const result = Object.keys(dict).map((key) => {
  278. return { amount: dict[key], created_at: key };
  279. });
  280.  
  281. // Sort the array by date using timestamp for comparison
  282. result.sort((a, b) => {
  283. const partsA = a.created_at.split('/');
  284. const partsB = b.created_at.split('/');
  285. const dateA = new Date(parseInt(partsA[2]), parseInt(partsA[1]) - 1, parseInt(partsA[0])).getTime();
  286. const dateB = new Date(parseInt(partsB[2]), parseInt(partsB[1]) - 1, parseInt(partsB[0])).getTime();
  287. return dateB - dateA;
  288. });
  289.  
  290. console.log(result);
  291. //invert the array, by using a loop
  292. const results = [];
  293. for (let i = result.length - 1; i >= 0; i--) {
  294. results.push(result[i]);
  295. }
  296. console.log(results);
  297. return results;
  298. }
  299.  
  300. public weekStats(events: { amount: number; created_at: string }[]) {
  301. const currentDate = new Date();
  302. const oneDayMilliseconds = 24 * 60 * 60 * 1000;
  303.  
  304. const dict: { [key: string]: number } = {};
  305.  
  306. for (let i = 6; i >= 0; i--) {
  307. const day = new Date(currentDate.getTime() - i * oneDayMilliseconds);
  308. const formattedDate = `${day.getDate()}/${day.getMonth() + 1}`;
  309. dict[formattedDate] = 0;
  310. }
  311.  
  312. for (const event of events) {
  313. const time = new Date(event.created_at);
  314. const formattedDate = `${time.getDate()}/${time.getMonth() + 1}`;
  315. dict[formattedDate] += event.amount;
  316. }
  317.  
  318.  
  319. let result = Object.keys(dict).map((key) => {
  320. return { amount: dict[key] || 0, created_at: key };
  321. });
  322.  
  323. result.sort((a, b) => {
  324. const dateA = new Date(`${currentDate.getFullYear()}/${a.created_at}`).getTime();
  325. const dateB = new Date(`${currentDate.getFullYear()}/${b.created_at}`).getTime();
  326. return dateA - dateB;
  327. });
  328.  
  329. result = result.slice(result.length - 1).concat(result.slice(0, result.length - 1));
  330.  
  331. return result;
  332. }
  333.  
  334. public convertirListe(liste: { amount: number; created_at: string }[]): { montants: number[]; dates: string[] } {
  335. const montants: number[] = [];
  336. const dates: string[] = [];
  337.  
  338. for (const transaction of liste) {
  339. montants.push(transaction.amount);
  340. dates.push(transaction.created_at);
  341. }
  342.  
  343. return { montants, dates };
  344. }
  345.  
  346. public smoothData(data: any): any {
  347. const smoothData: any = [];
  348.  
  349. for (let i = 0; i < data.length; i++) {
  350. if (data[i] == 0) {
  351. smoothData.push(smoothData[i - 1] || 0);
  352. } else {
  353. smoothData.push(data[i]);
  354. }
  355. }
  356.  
  357. return smoothData;
  358. }
  359.  
  360. public formatLabels(labels: string[], scale: string): string[] {
  361. if (scale == 'week') {
  362. return this.formatWeekLabels(labels);
  363. } else if (scale == 'month') {
  364. return this.formatMonthLabels(labels);
  365. } else if (scale == 'year') {
  366. return this.formatYearLabels(labels);
  367. }
  368.  
  369. return labels;
  370. }
  371.  
  372. public formatWeekLabels(dates: string[]): string[] {
  373. const jours = [
  374. 'Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'
  375. ];
  376.  
  377. const datesFormatees: string[] = [];
  378.  
  379. for (let i = 0; i < dates.length; i++) {
  380. const [jour, mois] = dates[i].split('/');
  381. const dateObj = new Date(`${mois}/${jour}/${new Date().getFullYear()}`);
  382. const dateFormatee = `${jours[dateObj.getDay()]} ${jour.padStart(2, '0')}`;
  383. datesFormatees.push(dateFormatee);
  384. }
  385.  
  386. return datesFormatees;
  387. }
  388.  
  389. public formatMonthLabels(dates: string[]): string[] {
  390. const mois = [
  391. 'Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc'
  392. ];
  393.  
  394. const datesFormatees: string[] = [];
  395.  
  396. for (let i = 0; i < dates.length; i++) {
  397. const [jour, moisIndex, annee] = dates[i].split('/');
  398. const dateObj = new Date(`${annee}/${moisIndex}/${jour}`);
  399. const dateFormatee = `${jour.padStart(2, '0')} ${mois[dateObj.getMonth()]}.`;
  400. datesFormatees.push(dateFormatee);
  401. }
  402.  
  403. return datesFormatees;
  404. }
  405.  
  406. public formatYearLabels(dates: string[]): string[] {
  407. const listeMois = [
  408. 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet',
  409. 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'
  410. ];
  411. const datesFormatees: string[] = [];
  412.  
  413. for (let i = 0; i < dates.length; i++) {
  414. const [mois, annee] = dates[i].split('/');
  415. const dateFormatee = `${listeMois[parseInt(mois) - 1]}`;
  416. datesFormatees.push(dateFormatee);
  417. }
  418.  
  419. return datesFormatees.slice(0, 13)
  420. }
  421.  
  422. public compareDates(date1: string, date2: string): number {
  423. const [jour1, mois1, annee1] = date1.split('/').map(Number);
  424. const [jour2, mois2, annee2] = date2.split('/').map(Number);
  425.  
  426. if (annee1 < annee2) {
  427. return -1;
  428. } else if (annee1 > annee2) {
  429. return 1;
  430. } else {
  431. if (mois1 < mois2) {
  432. return -1;
  433. } else if (mois1 > mois2) {
  434. return 1;
  435. } else {
  436. if (jour1 < jour2) {
  437. return -1;
  438. } else if (jour1 > jour2) {
  439. return 1;
  440. } else {
  441. return 0;
  442. }
  443. }
  444. }
  445. }
  446. }
  447.  
Advertisement
Add Comment
Please, Sign In to add comment