Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Planning.ts 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright (c) 2019 - 2020 Arnaud Vergnet.
  3. *
  4. * This file is part of Campus INSAT.
  5. *
  6. * Campus INSAT is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Campus INSAT is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. export type PlanningEventType = {
  20. id: number;
  21. title: string;
  22. date_begin: string;
  23. club: string;
  24. category_id: number;
  25. description: string;
  26. place: string;
  27. url: string;
  28. logo: string | null;
  29. };
  30. // Regex used to check date string validity
  31. const dateRegExp = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
  32. /**
  33. * Checks if the given date string is in the format
  34. * YYYY-MM-DD HH:MM
  35. *
  36. * @param dateString The string to check
  37. * @return {boolean}
  38. */
  39. export function isEventDateStringFormatValid(dateString?: string): boolean {
  40. return (
  41. dateString !== undefined &&
  42. dateString !== null &&
  43. dateRegExp.test(dateString)
  44. );
  45. }
  46. /**
  47. * Converts the given date string to a date object.<br>
  48. * Accepted format: YYYY-MM-DD HH:MM
  49. *
  50. * @param dateString The string to convert
  51. * @return {Date|null} The date object or null if the given string is invalid
  52. */
  53. export function stringToDate(dateString: string): Date | null {
  54. let date: Date | null = new Date();
  55. if (isEventDateStringFormatValid(dateString)) {
  56. const stringArray = dateString.split(' ');
  57. const dateArray = stringArray[0].split('-');
  58. const timeArray = stringArray[1].split(':');
  59. date.setFullYear(
  60. parseInt(dateArray[0], 10),
  61. parseInt(dateArray[1], 10) - 1, // Month range from 0 to 11
  62. parseInt(dateArray[2], 10),
  63. );
  64. date.setHours(parseInt(timeArray[0], 10), parseInt(timeArray[1], 10), 0, 0);
  65. } else {
  66. date = null;
  67. }
  68. return date;
  69. }
  70. /**
  71. * Converts a date object to a string in the format
  72. * YYYY-MM-DD HH-MM
  73. *
  74. * @param date The date object to convert
  75. * @param isUTC Whether to treat the date as UTC
  76. * @return {string} The converted string
  77. */
  78. export function dateToString(date: Date, isUTC: boolean): string {
  79. const day = String(date.getDate()).padStart(2, '0');
  80. const month = String(date.getMonth() + 1).padStart(2, '0'); // January is 0!
  81. const year = date.getFullYear();
  82. const h = isUTC ? date.getUTCHours() : date.getHours();
  83. const hours = String(h).padStart(2, '0');
  84. const minutes = String(date.getMinutes()).padStart(2, '0');
  85. return `${year}-${month}-${day} ${hours}:${minutes}`;
  86. }
  87. /**
  88. * Gets the current day string representation in the format
  89. * YYYY-MM-DD
  90. *
  91. * @return {string} The string representation
  92. */
  93. export function getCurrentDateString(): string {
  94. return dateToString(new Date(Date.now()), false);
  95. }
  96. /**
  97. * Checks if the given date is before the other.
  98. *
  99. * @param event1Date Event 1 date in format YYYY-MM-DD HH:MM
  100. * @param event2Date Event 2 date in format YYYY-MM-DD HH:MM
  101. * @return {boolean}
  102. */
  103. export function isEventBefore(event1Date: string, event2Date: string): boolean {
  104. const date1 = stringToDate(event1Date);
  105. const date2 = stringToDate(event2Date);
  106. if (date1 !== null && date2 !== null) {
  107. return date1 < date2;
  108. }
  109. return false;
  110. }
  111. /**
  112. * Gets only the date part of the given event date string in the format
  113. * YYYY-MM-DD HH:MM
  114. *
  115. * @param dateString The string to get the date from
  116. * @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
  117. */
  118. export function getDateOnlyString(dateString: string): string | null {
  119. if (isEventDateStringFormatValid(dateString)) {
  120. return dateString.split(' ')[0];
  121. }
  122. return null;
  123. }
  124. /**
  125. * Gets only the time part of the given event date string in the format
  126. * YYYY-MM-DD HH:MM
  127. *
  128. * @param dateString The string to get the date from
  129. * @return {string|null} Time in format HH:MM or null if given string is invalid
  130. */
  131. export function getTimeOnlyString(dateString: string): string | null {
  132. if (isEventDateStringFormatValid(dateString)) {
  133. return dateString.split(' ')[1];
  134. }
  135. return null;
  136. }
  137. /**
  138. * Checks if the given description can be considered empty.
  139. * <br>
  140. * An empty description is composed only of whitespace, <b>br</b> or <b>p</b> tags
  141. *
  142. *
  143. * @param description The text to check
  144. * @return {boolean}
  145. */
  146. export function isDescriptionEmpty(description?: string): boolean {
  147. if (description !== undefined && description !== null) {
  148. return (
  149. description
  150. .split('<p>')
  151. .join('') // Equivalent to a replace all
  152. .split('</p>')
  153. .join('')
  154. .split('<br>')
  155. .join('')
  156. .trim() === ''
  157. );
  158. }
  159. return true;
  160. }
  161. /**
  162. * Generates an object with an empty array for each key.
  163. * Each key is a date string in the format
  164. * YYYY-MM-DD
  165. *
  166. * @param numberOfMonths The number of months to create, starting from the current date
  167. * @return {Object}
  168. */
  169. export function generateEmptyCalendar(
  170. numberOfMonths: number,
  171. ): {[key: string]: Array<PlanningEventType>} {
  172. const end = new Date(Date.now());
  173. end.setMonth(end.getMonth() + numberOfMonths);
  174. const daysOfYear: {[key: string]: Array<PlanningEventType>} = {};
  175. for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
  176. const dateString = getDateOnlyString(dateToString(new Date(d), false));
  177. if (dateString !== null) {
  178. daysOfYear[dateString] = [];
  179. }
  180. }
  181. return daysOfYear;
  182. }
  183. /**
  184. * Adds events to the given array depending on their starting date.
  185. *
  186. * Events starting before are added at the front.
  187. *
  188. * @param eventArray The array to hold sorted events
  189. * @param event The event to add to the array
  190. */
  191. export function pushEventInOrder(
  192. eventArray: Array<PlanningEventType>,
  193. event: PlanningEventType,
  194. ) {
  195. if (eventArray.length === 0) {
  196. eventArray.push(event);
  197. } else {
  198. for (let i = 0; i < eventArray.length; i += 1) {
  199. if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
  200. eventArray.splice(i, 0, event);
  201. break;
  202. } else if (i === eventArray.length - 1) {
  203. eventArray.push(event);
  204. break;
  205. }
  206. }
  207. }
  208. }
  209. /**
  210. * Generates an object with an array of eventObject at each key.
  211. * Each key is a date string in the format
  212. * YYYY-MM-DD.
  213. *
  214. * If no event is available at the given key, the array will be empty
  215. *
  216. * @param eventList The list of events to map to the agenda
  217. * @param numberOfMonths The number of months to create the agenda for
  218. * @return {Object}
  219. */
  220. export function generateEventAgenda(
  221. eventList: Array<PlanningEventType>,
  222. numberOfMonths: number,
  223. ): {[key: string]: Array<PlanningEventType>} {
  224. const agendaItems = generateEmptyCalendar(numberOfMonths);
  225. for (let i = 0; i < eventList.length; i += 1) {
  226. const dateString = getDateOnlyString(eventList[i].date_begin);
  227. if (dateString != null) {
  228. const eventArray = agendaItems[dateString];
  229. if (eventArray != null) {
  230. pushEventInOrder(eventArray, eventList[i]);
  231. }
  232. }
  233. }
  234. return agendaItems;
  235. }