Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JACA] Add Angular Stopwatch and Countdown App generated by ChatGPT #22

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

sjaca10
Copy link

@sjaca10 sjaca10 commented Jun 19, 2024

Angular Stopwatch and Countdown App generated by Javier Arturo Cervantes Aguila

Demo

https://drive.google.com/file/d/12rYUMEB4S7NxaEF7eonD7lseuRorc89l/view?usp=sharing

Prompt

ChatGPT

Note: errors during transpilation and execution times were removed to reduce the lines in the file and allow the reviewer to focus in the important information.

Initial Prompt

Act as an expert Frontend Senior Software Engineer in the following technologies:
- HTML
- CSS
- JavaScript
- Angular
- Ant Design
- Jasmine

Build a website using Ant Design and Angular for a stopwatch and countdown application called "Clocklligence".

# Home Page
Clocklligence will have a home page with the following features:
- In a vertical order, using 75% of the width screen with a margin-bottom of 100px for the title and 50px for the rest of the elements:
  - The browser tab title and centered title "Clocklligence" have a clock emoji to the left and an hourglass emoji to the right.
  - Select the stopwatch feature by clicking the " Stopwatch " button with the clock emoji on both sides of the label.
  - Select the countdown feature by clicking the " Countdown " button with the hourglass emoji on both sides of the label.
  - A transparent button to use the application in full-screen mode labeled as "Go Full Screen" with a full-screen emoji on both sides of the label.

# Stopwatch Page
When the user clicks the "Stopwatch" button on the home page, it'll redirect to the page `/stopwatch` that contains the following elements in vertical alignment:
- An unlabeled "Back" button with only a Circled Back Arrow icon that will redirect to the home page.
- A digital clock "Stopwatch" will be displayed with hours, minutes, and seconds with the same font size, separated by the colon `:`, and the milliseconds will be displayed after seconds with a smaller size, separated by a period `.` that will have the following three states:
  - Initial
  - Running
  - Paused
- Under the "Stopwatch", the "Action Zone" will be displayed with three horizontally aligned buttons:
  - Aligned to the left, a Start/Pause button that can be triggered by click or "P" shortcut will act as follows:
    - Initially, it displays a Play icon; when clicked, it will be changed to a Pause icon, and the "Stopwatch" will change to Running.
    - Then, when the clock is Running and the user clicks the Pause icon button, it will change back to the Play icon, and the "Stopwatch" will change to Paused.
    - Then, when the clock is paused, and the user clicks the Play button, the icon will be changed to Pause, and the "Stopwatch" will continue the count and change its state to Running.
  - Aligned in the center, a Lapse button that can be triggered by click or "L" shortcut will act as follows:
    - The button will always display a Circled Arrow icon that, when clicked, will take the current time in the "Stopwatch" and be displayed in the enumerated Lapses list underneath.
  - Aligned to the right, a Stop button that can be triggered by click or "S" shortcut will act as follows:
    - The button will always display a Stop icon that will restart the "Stopwatch" to its initial 0 values.
- Under the "Action Zone" the "Lapses" list will be displayed, showing all the dates taken by the Lapse button in an enumerated list with the newest at the top.
  - When each item is added, it'll appear on the list using a fade-in-down entrance animation.

# Countdown Page
When the user clicks the "Countdown" button on the home page, it'll redirect to the page `/countdown` that contains the following elements:
- An unlabeled "Back" button with only a Circled Back Arrow icon that will redirect to the home page.
- A digital clock "Countdown" will be displayed with hours, minutes, and seconds with the same font size, separated by a colon `:`, and the milliseconds will be displayed after seconds with a smaller size, separated by a period `.` that will have the following three states:
  - Unset: initial or restarted state, waiting for user input
  - Set: the countdown time has been set and is ready to start running
  - Running: the user has started the Countdown
  - Paused: the user has paused the Countdown
  - Finished: the Countdown completes, counting down to 0
It will be possible to set the time through the following actions:
  - Using the numbers in the keyboard, when a number is set, that value will be placed in the first digit of seconds. The user presses a second number; then the first-second digit will be moved to the second following position, and the new number will be placed in the first digit of seconds; that process will be repeated until the last digit of hours is set. If the user continues pressing more numbers when all the digits have been placed, a toast error will be displayed showing the following text: "No more digits are allowed; clear the countdown before inserting a new value or use the manual controls".
  - Using arrows that will be placed in each digit number in the countdown clock:
    - Above each digit, an up arrow icon will be placed; when clicked, it will increment by one the value of the digit in the same position under it. The min value will be 0, and the max value will be 9; when the user reaches the min value and clicks again, the value will be changed to 9, and when the user reaches the max value and clicks again, the value will be changed to 0.
    - Below each digit, a down arrow icon will be placed; when clicked, it will decrease by one the value of the digit in the same position above it. The min value will be 0, and the max value will be 9; when the user reaches the min value and clicks again, the value will be changed to 9, and when the user reaches the max value and clicks again, the value will be changed to 0.
  - Behind the "Countdown", as part of the "Action Zone", a row of buttons, "Numeric Pad" from 0 to 9, will be displayed; the user will click on them to set the time; these will act in the same way as the number in the keyboard.
- Under the "Countdown", the "Action Zone" will be displayed with:
  - In the first row, the "Numeric Pad" as explained before.
  - In the second row, the "Actions" buttons with two buttons:
    - The "Set" button will transform the entered delta time into HH:MM:SS.mmm value will be displayed in the "Countdown" clock and will change the state of the Countdown from Unset to Set. When the state is Set, it'll hide the "Numeric Pad" and change the buttons "Set" and "Clear" to "Start" and "Stop":
      - The "Start" button will start the Countdown from its value to 0, reducing by milliseconds and displaying the new value in the Countdown clock. It will change the "Countdown" state to Running. The "Start" button will change its color and label to "Pause" which will put Pause in the "Countdown" and will change the status from Running to Paused.
      - The "Stop" button will stop the Countdown, changing the Countdown state from Running to Unset and displaying the "Numeric Pad" with the initial "Set" and "Clear" buttons.
      - When the "Countdown" finishes, it'll automatically change its status from Running to Finished; it will blink and reproduce a pleasant sound.
    - "Clear" button that will remove the entered value in the Countdown and will change the state of the "Countdown" to Unset

# Best Practices
The application should follow the best coding practices:
- DRY
- Separation of concerns
- Unit Tests using Jasmine
- Documentation in the code
- README documentation, including how to run the project, collaborate, and the prompts used in the AI to create this project.
- Graceful error handling
- Web Responsive
- i18n

Creating Angular Project

The command `ng new clocklligence` is asking:
Which stylesheet format would you like to use? (Use arrow keys)
❯ CSS             [ https://developer.mozilla.org/docs/Web/CSS                     ] 
  Sass (SCSS)     [ https://sass-lang.com/documentation/syntax#scss                ] 
  Sass (Indented) [ https://sass-lang.com/documentation/syntax#the-indented-syntax ] 
  Less            [ http://lesscss.org                                             ]

Which one should I select that is more appropriate to the generated code?
The command `ng new clocklligence` is asking:
Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? (y/N)

Which one should I select that is more appropriate to the generated code?

Installing Ant Design for Angular

The command `ng add ng-zorro-antd` is asking:
Enable icon dynamic loading [ Detail: https://ng.ant.design/components/icon/en ] (y/N)

What should I select that is more appropriate to the generated code?
The command `ng add ng-zorro-antd` is asking:
Set up custom theme file [ Detail: https://ng.ant.design/docs/customize-theme/en ] (y/N)

What should I select that is more appropriate to the generated code?
The command `ng add ng-zorro-antd` is asking:
Choose template to create project: (Use arrow keys)
❯ blank 
  sidemenu 

What should I select that is more appropriate to the generated code?

Starting the Project

After executing `ng serve`, the app is up and running. However, the home page is empty. Do I need to apply more changes?
The home page is still empty. I checked the code and I noticed these files
- `src/app/app.component.ts`
- `src/app/app.routes.ts`
- `src/main.ts`

Do I need to apply any changes to them?
`ng-serve` retrieved the following errors:

✘ [ERROR] TS2551: Property 'mozRequestFullScreen' does not exist on type 'HTMLElement'. Did you mean 'requestFullscreen'? [plugin angular-compiler]

    src/app/home/home.component.ts:12:40:
      12 │ ...se if (document.documentElement.mozRequestFullScreen) { // Firefox
         ╵                                    ~~~~~~~~~~~~~~~~~~~~

  'requestFullscreen' is declared here.

    node_modules/typescript/lib/lib.dom.d.ts:7842:4:
      7842 │     requestFullscreen(options?: FullscreenOptions): Promise<void>;
           ╵     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<More errors were removed>

Please solve them.
Similar errors are still throwing

✘ [ERROR] TS2551: Property 'webkitRequestFullscreen' does not exist on type 'HTMLElement'. Did you mean 'requestFullscreen'? [plugin angular-compiler]

    src/app/home/home.component.ts:22:19:
      22 │     } else if (doc.webkitRequestFullscreen) { // For older version...
         ╵                    ~~~~~~~~~~~~~~~~~~~~~~~

  'requestFullscreen' is declared here.

    node_modules/typescript/lib/lib.dom.d.ts:7842:4:
      7842 │     requestFullscreen(options?: FullscreenOptions): Promise<void>;
           ╵     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<More errors were removed>
Errors are still present
The errors persist
Some other errors are also present
✘ [ERROR] TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'CountdownComponent'.
  No index signature with a parameter of type 'string' was found on type 'CountdownComponent'. [plugin angular-compiler]

    src/app/countdown/countdown.component.ts:26:4:
      26 │     this[unit]++;
         ╵     ~~~~~~~~~~

<More errors were removed>
The following errors were thrown

✘ [ERROR] TS2365: Operator '>' cannot be applied to types 'number | number[] | ((unit: string) => void) | ((unit: string) => void) | ((number: number) => void) | (() => void) | (() => void)' and 'number'. [plugin angular-compiler]

    src/app/countdown/countdown.component.ts:27:8:
      27 │     if (this[unit as keyof CountdownComponent] > 9) {
         ╵         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<More errors were removed>
The issue persists, the actual code is:
> ```
export class CountdownComponent {
  hoursTens = 0;
  hoursOnes = 0;
  minutesTens = 0;
  minutesOnes = 0;
  secondsTens = 0;
  secondsOnes = 0;
  millisecondsHundreds = 0;
  millisecondsTens = 0;
  millisecondsOnes = 0;
  numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
  private interval: any;
  private totalTime = 0;

  constructor(private message: NzMessageService) {}

  increment(unit: keyof CountdownComponent) {
    this[unit]++;
    if (this[unit] > 9) {
      this[unit] = 0;
    }
  }

  decrement(unit: keyof CountdownComponent) {
    this[unit]--;
    if (this[unit] < 0) {
      this[unit] = 9;
    }
  }

  appendDigit(number: number) {
    // Implement the logic for appending digits
  }

  setCountdown() {
    this.totalTime = this.calculateTotalTime();
    if (this.totalTime > 0) {
      this.startCountdown();
    }
  }

  clearCountdown() {
    this.hoursTens = 0;
    this.hoursOnes = 0;
    this.minutesTens = 0;
    this.minutesOnes = 0;
    this.secondsTens = 0;
    this.secondsOnes = 0;
    this.millisecondsHundreds = 0;
    this.millisecondsTens = 0;
    this.millisecondsOnes = 0;
  }

  private calculateTotalTime(): number {
    return (
      (this.hoursTens * 10 + this.hoursOnes) * 3600000 +
      (this.minutesTens * 10 + this.minutesOnes) * 60000 +
      (this.secondsTens * 10 + this.secondsOnes) * 1000 +
      (this.millisecondsHundreds * 100 +
        this.millisecondsTens * 10 +
        this.millisecondsOnes)
    );
  }

  private startCountdown() {
    clearInterval(this.interval);
    this.interval = setInterval(() => {
      this.totalTime -= 10;
      if (this.totalTime <= 0) {
        clearInterval(this.interval);
        this.message.success('Countdown finished!');
        this.clearCountdown();
      } else {
        this.updateTime();
      }
    }, 10);
  }

  private updateTime() {
    const time = new Date(this.totalTime);
    this.hoursTens = Math.floor(time.getUTCHours() / 10);
    this.hoursOnes = time.getUTCHours() % 10;
    this.minutesTens = Math.floor(time.getUTCMinutes() / 10);
    this.minutesOnes = time.getUTCMinutes() % 10;
    this.secondsTens = Math.floor(time.getUTCSeconds() / 10);
    this.secondsOnes = time.getUTCSeconds() % 10;
    const milliseconds = time.getUTCMilliseconds();
    this.millisecondsHundreds = Math.floor(milliseconds / 100);
    this.millisecondsTens = Math.floor((milliseconds % 100) / 10);
    this.millisecondsOnes = milliseconds % 10;
  }
}
> ```
The TS error is still present:

Operator '>' cannot be applied to types 'number | (() => void) | ((unit: keyof CountdownComponent) => void) | ((unit: keyof CountdownComponent) => void) | ((number: number) => void) | (() => void)' and 'number'.
The error is not fixed yet.

Running the Project

Several icon errors were thrown in the Chrome console:

Uncaught Error: [@ant-design/icons-angular]:the icon arrow-left-o does not exist or is not registered.
    at IconNotFoundError (ant-design-icons-angular.mjs:92:10)
    at ant-design-icons-angular.mjs:233:15
    at map.js:7:37
    at OperatorSubscriber2._this._next (OperatorSubscriber.js:15:21)
    at Subscriber2.next (Subscriber.js:34:18)
    at Observable2._subscribe (innerFrom.js:51:24)
    at Observable2._trySubscribe (Observable.js:38:25)
    at Observable.js:32:31
    at errorContext (errorContext.js:19:9)
    at Observable2.subscribe (Observable.js:23:9)

<More errors were removed>

Improving the Stopwatch Result

In the "Stopwatch" page, apply the following changes:
- The clock and lapses list should use the Google Orbitron font.
- The clock font-size should be `10vw`.
- The buttons in the "Action Zone" should have width: `30vw` and height: `10vw` for each element. 
- The lapses list font-size should be `3vw`.
- The "Stop" button should have a light red background.
- The "Lapse" button should have a light blue background.
- The "Play" button should have a light green background.
- The size of the icons in the buttons should be `3vw`
In the "Stopwatch" page, apply the following change:
- The point and milliseconds (`.mmm`) value must be displayed in a new row just under the stopwatch clock aligned to the right without any margin.
- The milliseconds value font-size should be '2vw'.

Improving the Countdown Result

In the "Countdown" page, apply the following changes:
- The clock and arrows should use the Google Orbitron font.
- The clock and arrows font-size should be `3vw`.
- The up and down arrows for each digit must be above and below of each number accordingly.
- The buttons in the "Numeric Pad" section should have width: `5vw` for each element.
- The control buttons must be displayed in a centered row with:
  - The "Set" button should display a Step Forward icon instead of the text with light blue background.
  - The "Clear" button should display a Stop icon instead of the text with light red background.
  - The size of the icons in the buttons should be `3vw`.
In the "Countdown" page, apply the following changes:
- In the clock:
  - Arrow buttons should not have borders nor background. They should have a 35px height to have them tied to their corresponding number.
  - The colon symbols must be aligned with the numbers, not with the top arrows.
  - The point and milliseconds (`.mmm`) value must be displayed in a new row just under the stopwatch clock aligned to the right without any margin.
  - The milliseconds value font-size should be '2vw'.
In the "Countdown" page, the following functionality is not implemented:
- When click the "Set" button, the icon must be changed to Play icon and the countdown clock must be set to the HH:MM:SS format.
- When click the "Play" button, the icon must be changed to Pause icon and the countdown clock must be paused.
- When click the "Stop" button, it should stop the countdown clock and set the initial value, zeros.
In the "Countdown" page, the following functionality is missed:
- The countdown clock will blink and reproduce a pleasant sound for ten seconds
In the "Countdown" page, we need to improve the blinking functionality:
- The countdown clock will blink when the countdown completes and the user clicks the Stop button
In the "Countdown" page, the digit append functionality is missed:
- The "Numeric Pad" will allow the user to set the countdown time: when a number is set, that value will be placed in the first digit of seconds. The user presses a second number; then the first-second digit will be moved to the second following position, and the new number will be placed in the first digit of seconds; that process will be repeated until the last digit of hours is set. If the user continues pressing more numbers when all the digits have been placed, a toast error will be displayed showing the following text: "No more digits are allowed; clear the countdown before inserting a new value or use the manual controls".
In the "Countdown" page, the user should be able to introduce the time using the numbers in the keyboard.
Include the Go Full Screen button in the "Stopwatch" and "Countdown" pages next to the back button.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant