How can I reset the counter to 1 each time my labels changes?

I have this code that is supposed act as a breathing exercise counting as follow:

8 second inhale 
8 second "hold inhale"
12 second "exhale"
8 second "hold exhale" 

everything is working fine except the counter will increment without resetting to 1. it should be, e. g. 1 to 8 and then 1 to 8 again and then 1 to 12 and so on.

// Function to start the timer
function startTimer() {
  var timer = document.getElementById('timer');
  var label = document.getElementById('label');
  var count = 1;

  // Interval for the timer
  var interval = setInterval(function() {
    // Update the timer display and label
    timer.textContent = count;

    if (count <= 8) {
      label.textContent = 'Inhale';
    } else if (count <= 16) {
      label.textContent = 'Pause Inhale';
    } else if (count <= 28) {
      label.textContent = 'Exhale';
    } else if (count <= 36) {
      label.textContent = 'Pause Exhale';
    }

    // Increment count
    count++;

    // Stop the timer after reaching 8, 8, 12, 8 pattern
    if (count === 45) {
      clearInterval(interval);
      startTimer();
    }
  }, 1000); // 1000 milliseconds = 1 second
}

// Start the timer initially
startTimer();
body {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  margin: 0;
  font-family: Arial, sans-serif;
  text-align: center;
}

h1 {
  font-size: 24px;
  font-weight: bold;
}

p {
  font-size: 18px;
}
<h1>Special Timer</h1>
<p id="timer"></p>
<p id="label"></p>

Why does running multiple loops in this tic tac toe game logic function result in an error?

I am working on the logic for checking for a winner in a Tic Tac Toe game.
I copied the logic from here:

Connect Four Game Checking for Wins JS

This win check logic was for a connect four game, so i modified it.

If i just run a single loop, for example, the loop checking for down wins, it runs as expected.
but if i run both loops, i get this error.

TTT.js:121 Uncaught TypeError: Cannot read properties of undefined (reading '0')
    at Object.checkWinner (TTT.js:121)
    at <anonymous>:1:4

Googling this error wasnt helpful.

function gameController(
  playerOneName = "Player One",
  playerTwoName = "Player Two"
) {

  const players = [{
      name: playerOneName,
      token: 1
    },
    {
      name: playerTwoName,
      token: 2
    }
  ];

  function checkLine(a, b, c) {
    return ((a != 0) && (a == b) && (a == c));
  }

  function checkWinner(bd) { // check win logic
    // check down
    for (r = 0; r < 3; r++)
      for (c = 0; c < 3; c++)
        if (checkLine(bd[r][c], bd[r + 1][c], bd[r + 2][c])) {
          return bd[r][c];
        }
    // check right, works but not if down check is enabled
    for (r = 0; r < 3; r++)
      for (c = 0; c < 3; c++)
        if (checkLine(bd[r][c], bd[r][c + 1], bd[r][c + 2])) {
          return bd[r][c];
        }

    return 0;
  };

  const playRound = (row, column) => {
    gameBoard.playMove(row, column, getActivePlayer().token);
    switchPlayerTurn();
    printNewRound();
  }

  return {
    activePlayer,
    switchPlayerTurn,
    getActivePlayer,
    players,
    printNewRound,
    playRound,
    checkWinner
  };
}

const gc = gameController();

// right check
gc.playRound(0, 0); //p1
gc.playRound(1, 0); //p2
gc.playRound(0, 1); //p1
gc.playRound(2, 2); //p2
gc.playRound(0, 2); //p1

/*
// down check
gc.playRound(0,0);  //p1
gc.playRound(0,1); //p2
gc.playRound(1,0); //p1
gc.playRound(2,2); //p2
gc.playRound(2,0); //p1
*/

I have some code at the bottom to automatically fill the array with player tokens in the console.
Example:

(3) [Array(3), Array(3), Array(3)]
0: (3) [1, 1, 1]
1: (3) [2, 0, 0]
2: (3) [0, 0, 2]

Again, these loops work on there own. but if i were to run both on the example above, with the down check supposed to run first, then right check to run next, it results in the above error.

Why am i unable to run both loops?

TypeError: client.player.createQueue is not a function – How to fix this error in Discord.js bots? Discord.js/v.14

I have a problem generating my music bot for discord, as it is displaying the following error when running the bot. (Discord.js/v.14)

Line(50): const queue = await client.player.createQueue(interaction.guild)

Code:

const { SlashCommandBuilder, EmbedBuilder } = require('@discordjs/builders')
const { QueryType } = require('discord-player')

module.exports = {
  data: new SlashCommandBuilder()
    .setName('play')
    .setDescription('Plays a song.')
    .addSubcommand((subcommand) => {
      return subcommand
        .setName('search')
        .setDescription('Searches for a song.')
        .addStringOption((option) => {
          return option
            .setName('searchterms')
            .setDescription('Search keywords.')
            .setRequired(true)
        })
    })
    .addSubcommand((subcommand) => {
      return subcommand
        .setName('playlist')
        .setDescription('Plays playlist from Youtube.')
        .addStringOption((option) => {
          return option
            .setName('url')
            .setDescription('Playlist URL.')
            .setRequired(true)
        })
    })
    .addSubcommand((subcommand) => {
      return subcommand
        .setName('song')
        .setDescription('Plays song from Youtube.')
        .addStringOption((option) => {
          return option
            .setName('url')
            .setDescription('URL of the song.')
            .setRequired(true)
        })
    }),

  async execute({ client, interaction }) {
    if (!interaction.member.voice.channel) {
      await interaction.reply(
        'You must be in a voice channel to uso this command.',
      )
      return
    }

    const queue = await client.player.createQueue(interaction.guild)

    if (!queue.connection) await queue.connect(interaction.member.voice.channel)

    const embed = new EmbedBuilder()

    if (interaction.options.getSubcommand() === 'song') {
      const url = interaction.options.getString('url')

      const result = await client.player.search(url, {
        requestedBy: interaction.user,
        searchEngine: QueryType.YOUTUBE_VIDEO,
      })

      if (result.tracks.length === 0) {
        await interaction.reply('No results found...')
        return
      }

      const song = result.tracks[0]
      await queue.addTrack(song)

      embed
        .setDescription(`Added **[${song.title}](${song.url})** to the queue.`)
        .setThumbnail(song.thumbnail)
        .setFooter({ text: `Duration: ${song.duration}` })
    } else if (interaction.options.getSubcommand() === 'playlist') {
      const url = interaction.options.getString('url')

      const result = await client.player.search(url, {
        requestedBy: interaction.user,
        searchEngine: QueryType.YOUTUBE_PLAYLIST,
      })

      if (result.tracks.length === 0) {
        await interaction.reply('No playlist found...')
        return
      }

      const playlist = result.tracks[0]
      await queue.addTracks(playlist)

      embed
        .setDescription(
          `Added **[${playlist.title}](${playlist.url})** to the queue.`,
        )
        .setThumbnail(playlist.thumbnail)
        .setFooter({ text: `Duration: ${playlist.duration}` })
    } else if (interaction.options.getSubcommand() === 'search') {
      const url = interaction.options.getString('searchterms')

      const result = await client.player.search(url, {
        requestedBy: interaction.user,
        searchEngine: QueryType.AUTO,
      })

      if (result.tracks.length === 0) {
        await interaction.reply('No results found...')
        return
      }

      const song = result.tracks[0]
      await queue.addTrack(song)

      embed
        .setDescription(`Added **[${song.title}](${song.url})** to the queue.`)
        .setThumbnail(song.thumbnail)
        .setFooter({ text: `Duration: ${song.duration}` })
    }

    if (!queue.playing) await queue.play()

    await interaction.reply({
      embeds: ,
    })
  },
}

Error: TypeError: client.player.createQueue is not a function

I’ve tried doing some research involving this issue, but haven’t had any answers that help me.

I believe that there may also be a problem with getQueue(), but the first problem I encountered was this one.

I would like a solution to resolve this.

How to resolve ‘Error: Cannot find module ‘request’ Require stack:’ running JS Code in Zapier

I’m trying to complete an integration using Zapier’s JS Code action and one of their predefined triggers. In this example I’m using their HubSpot tool to trigger whenever a new contact is created and to initiate a POST containing their data, creating the same contact in the other software. I copied the NodeJS Request below from Postman where it works correctly:

var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://examplewebsite.com/authtoken',
  'headers': {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "LeadInfo": "Lead Info",
    "CustomerFID": null,
    "RegCommunityFID": "202",
    "NameLast": "Bobby",
    "NameMiddle": "N",
    "NameFirst": "INTEGRATION2",
    "Title": "Mr",
    "NameLast2": "TEST",
    "NameMiddle2": "K",
    "NameFirst2": "Bo",
    "Title2": "",
    "Suffix2": "",
    "StreetAddress": "Batman Plaza",
    "City": "Illinois",
    "ZipCode": "12345",
    "StateCode": "IL",
    "PhoneHome": "(889) 442-0124",
    "EmailHome": "[email protected]",
    "Rating": "Rating",
    "LeadSource": "LeadSource",
    "RegistrationNotes": "string",
    "ExternalID": "EXID",
    "Status": "Status",
    "ProspectNumber": "2",
    "WCCustBuyerInfo": {
      "ContractName": "ThisContract",
      "WCBuyers": [
        {}
      ]
    }
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

When I test the code in Zapier I get the following error message

Failed to run your JavaScript code
Error: Cannot find module 'request' Require stack: - /var/task/index.js - /var/runtime/UserFunction.js - /var/runtime/Runtime.js - /var/runtime/index.js

What is the nature of this error and how do I resolve it?

The desired output would be a JSON payload containing the data captured from HubSpot. The Zapier input data tool works very well but I’m not able to see it in action.

Router middleware not working properly in Nodejs

I am working on Nodejs and using “Express js”, Right now i am working on “Router Middleware” function With following code,whenever i hit “http://localhost:3000” then “router middle” working/executed, but i want whenever i hit “http://localhost:3000/api/” (api route) only then “router middleware” should active/execute.Here is my current code

const express = require('express');
const app = express();

// Create a router instance
const router = express.Router();

// Define a middleware function specific to the router
const routerMiddleware = (req, res, next) => {
  // Perform some operations on the request or response
  console.log('Router middleware executed');
  next();
};

// Apply the middleware to the router
router.use(routerMiddleware);

// Define a route on the router
router.get('/example', (req, res) => {
  res.send('Hello from the router');
});

// Mount the router on the app
app.use('/api', router);

// Start the server
app.listen(3000, () => {
  console.log('Server started on port 3000');
});

NGINX Django DRF Vue.js POST method returns Method Get not allowed 405

I am building an ecommerce site. Everything works well, except the forms. When I try to post something, it returns me 405 method get not allowed. Why is it giving GET error when I am trying to do POST? It works on some forms, like for example checkout. But when I try to use contact form and press send axios.post(‘/api/v1/contacto/’, data) it gets me this error 405. BTW, when I am using this e-commerce running it on my local machine, it works well.

Here is my sites-available:

upstream ecologic_app_server {
    server unix:/webapps/ecologic/backend/venv/run/gunicorn.sock fail_timeout=0;
}

server {
    listen 8000;
    listen [::]:8000;
    server_name myiphere;

    client_max_body_size 40M;


    location / {
        root /webapps/ecologic/frontend;
        try_files $uri /index.html;
        index index.html index.htm;
    }

    location /static/ {
        root /webapps/ecologic/backend;
    }

    location /media/ {
        root /webapps/ecologic/backend;
    }


    location /api/v1/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header Host $http_host;
        proxy_pass http://ecologic_app_server/api/v1/;
        proxy_ssl_session_reuse off;
        proxy_redirect off;
    }

    location /admin/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://ecologic_app_server/admin/;
        proxy_ssl_session_reuse off;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

}

This is my urls.py:

from django.urls import path, include
from . import views

urlpatterns = [
    path('contacto/', views.contact_form_post),
    path('reclamo/', views.complaints_form_post),
]

Here is my code for contact form:

@api_view(['POST'])
def contact_form_post(request):
    if request.method == "POST":
        serializer = ContactForm(data=request.data)
        if serializer.is_valid():

            first_name = serializer.validated_data['first_name']
            last_name = serializer.validated_data['last_name']
            phone = serializer.validated_data['phone']
            email = serializer.validated_data['email']
            subject = serializer.validated_data['subject']
            message = serializer.validated_data['message']

            print(first_name, last_name, phone, email, subject, message)

            context = {
                'first_name': first_name,
                'last_name': last_name,
                'phone': phone,
                'email': email,
                'subject': subject,
                'message': message
            }

            html = render_to_string('emails/contact.html', context)
            text = render_to_string('emails/contact.txt', context)

            recipient = MainSettings.objects.first().contact_email


            send_mail(
                subject,
                message=text,
                html_message=html,
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[recipient],
                fail_silently=False,
                # auth_user=None, auth_password=None, connection=None, html_message=None
            )
            serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

What could be the problem? Thank you.

dropdown menu doesn’t close when I click it again at menu mobile responsive user

I’m working on a website navigation bar that includes a dropdown menu in responsive. However, I’m facing an issue where the dropdown menu doesn’t close when I click outside of it. I’ve tried adding the data-bs-auto-close=”outside” attribute to the dropdown toggle element, but it doesn’t seem to be working.

Here’s the relevant code snippet:

  <!-- Navbar code omitted for brevity -->

  <div class="navbar-collapse collapse show" id="navbarCollapse" style="">
    <div class="container-fluid gx-0">
      <div class="row gx-0 px-lg-2 py-lg-1">
        <div class="col-lg-1 d-flex align-items-center order-lg-1 order-2">
          <!-- Social media icons omitted for brevity -->
        </div>
        <div class="col-lg-11 order-lg-2 order-1 px-2 float-right mb-md-0 mb-1">
          <div class="navbar-nav gap-0 navlinks mt-lg-0 mt-4 nav justify-content-end">
            <!-- Other navigation links omitted for brevity -->
            <a href="#" class="nav-link dropdown-toggle dropdownMenu" id="dropdownMenu" data-bs-auto-close="outside" role="button" data-bs-toggle="dropdown" aria-expanded="false">Menu</a>
            <div class="dropdown-menu mega-menu" aria-labelledby="dropdownMenu">
              <!-- Dropdown menu content omitted for brevity -->
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</nav>```

<script src="<?=base_url()?>/<?=$publicimagepath?>frontdesign/js/jquery-3.4.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>

dropdown menu doesn't close when I click it again at menu mobile user

I'm working on a website navigation bar that includes a dropdown menu in responsive. However, I'm facing an issue where the dropdown menu doesn't close when I click outside of it. I've tried adding the data-bs-auto-close="outside" attribute to the dropdown toggle element, but it doesn't seem to be working.

Is there an equivalent to kbhit in JS?

I’m a beginner programmer who needs to make a simple game using JS. I’ve done a similar game in c++ where the character (i.e. a pixel) moves depending on the value of the input. In that project I used kbhit to get the inputs but in JS, I’m at a loss.

I tried looking around for a bit and found the scanner function but it didn’t quite make sense to me and it didn’t seem like the right thing to use.

Any tips?

How to slow background pan on hover in JavaScript

I have a div background pan that I want to slow on hover:

@keyframes backgroundScroll {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
div {
  width: 30vw;
  height: 30vh;
  background: repeating-linear-gradient(
    45deg,
    #EE0000,
    #EE0000 10px,
    #990000 10px,
    #990000 20px
  );
  background-size: 150%;
  background-position: 50% 50%;
  animation: backgroundScroll 3s linear infinite;
}
div:hover{
  animation: backgroundScroll 20s;
}
<div></div>

In theory, something like this would work, but it doesen’t retain the state. I went digging and found it is possible to retain the animation state: StackOverflow-Change Animation speed on hover. After disection, I found it uses an illusion, which reduced to my purposes is this. I am wondering if there is a way to apply this to the original code.

Local Storage not working on my little project

i hope someone can help me with this issue. Im working on this personal todo app, and everything was going fine until i tried to save my tasks in Local Storage. Im setting a line of code at line 74 to do so, and i works ok.

But from line 29 to line 45 im trying to print all the tasks that are previously saved when content is loaded, but doesnt work at all. I also realized that it’s not setting the empty array [ ]; If i delete everything in local storage and reload, it does not set the empty array in local storage.

I also realized it throws an error in the stackoverflow console and that’s why i had to comment that piece of code, but in the browser it shows no error at all without commenting that piece of code.

thanks for reading!

// Javascript Input Form

    const form = {
        taskname: '',
        description: '',
        time1: '',
        time2: ''
    }

    // Validar
    
    // Variables

    const inputName = document.querySelector('#taskname');
    const inputDescription = document.querySelector('#description');
    const inputTime1 = document.querySelector('#time1');
    const inputTime2 = document.querySelector('#time2');
    const createButton = document.querySelector('#create');
    const cancelButton = document.querySelector('#cancel');
    const mainForm = document.querySelector('form');
    const closeButton = document.querySelector('#close-button');
    const formContainer = document.querySelector('#create-task-container');
    const emptyButton = document.querySelector('.section-empty');
    const ctaButton = document.querySelector('.cta');
    const section3 = document.querySelector('.section-3')
    
    //MAIN ARRAY

// HERE COMES THE ISSUE

    // let tasks = [];
    // let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
    
    /*document.addEventListener('DOMContentLoaded', () => {

        tasks = JSON.parse(localStorage.getItem('tasks')) || [];
        
        // if(localStorage.getItem('tasks')){
        //     tasks.map((tasks) => {
        //         imprimirTask(tasks);
        //     });
        // };
    });*/
    
// ENDS ISSUE 

    // Eventos

    mainForm.addEventListener('submit', crearTask);
    inputName.addEventListener('blur', validarForm);
    inputDescription.addEventListener('blur', validarForm);
    cancelButton.addEventListener('click', cerrarForm);
    closeButton.addEventListener('click', cerrarForm);
    emptyButton.onclick = () => aparecer();
    ctaButton.onclick = () => aparecer();


    // Funciones

    function crearTask(e){
        e.preventDefault();
        console.log('creando task');

        const datosTask = {
            id: Date.now(),
            name: inputName.value.trim(),
            description: inputDescription.value.trim(),
            time1: inputTime1.value.trim(),
            time2: inputTime2.value.trim(),
            allDayTask: false,
            isCompleted: false,
        }
        tasks = [...tasks, datosTask];
        // localStorage.setItem('tasks', JSON.stringify(tasks));
        console.log(tasks);
        mainForm.reset();
        quitarEstilos();
        imprimirTask(e, datosTask);
    };

    function imprimirTask(e, tasks){
        const taskEl = document.createElement('div');
        taskEl.classList.add('task');
        taskEl.setAttribute('id', tasks.id);
        console.log('div creado');
        cerrarForm(e);
        if(tasks.isCompleted){
            taskEl.classList.add('done');
        }

        const taskElHtml = `
                <div class="header-task">
                <div>
                    <h4 contenteditable="true" class="name">${tasks.name}</h4>
                    <span>${tasks.description}</span>
                </div>
                <div>
                    <button class="check">
                        <input type="checkbox" class="checkbox" ${tasks.isCompleted ? 'checked' : ''}>  
                    </button>
                </div>
            </div>
            <div class="footer-task">
                <div>
                    <p>Today</p>
                    <span>${tasks.time1} - ${tasks.time2}</span>
                </div>
                <button id="trash">
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M16 6V5.2C16 4.0799 16 3.51984 15.782 3.09202C15.5903 2.71569 15.2843 2.40973 14.908 2.21799C14.4802 2 13.9201 2 12.8 2H11.2C10.0799 2 9.51984 2 9.09202 2.21799C8.71569 2.40973 8.40973 2.71569 8.21799 3.09202C8 3.51984 8 4.0799 8 5.2V6M10 11.5V16.5M14 11.5V16.5M3 6H21M19 6V17.2C19 18.8802 19 19.7202 18.673 20.362C18.3854 20.9265 17.9265 21.3854 17.362 21.673C16.7202 22 15.8802 22 14.2 22H9.8C8.11984 22 7.27976 22 6.63803 21.673C6.07354 21.3854 5.6146 20.9265 5.32698 20.362C5 19.7202 5 18.8802 5 17.2V6" stroke="#888888" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    </svg>
                </button>   
            </div>
        `;
        taskEl.innerHTML = taskElHtml;
        section3.appendChild(taskEl);
    }

    function validarForm(e){
        validarTodo();
        if(e.target.value.trim() === ''){
            e.target.classList.add('failed');
            alerta("This field can't be empty", e.target.parentElement);
            form[e.target.id] = ''
            return;
        }
        
        form[e.target.id] = e.target.value.trim();
        e.target.classList.remove('failed');
        e.target.classList.add('succeed');
        quitarAlerta(e.target.parentElement);
        // validarTodo();
        console.log(form);
    };

    function alerta(mensaje, referencia){
        quitarAlerta(referencia);
        const createSpan = document.createElement('span');
        createSpan.textContent = mensaje;
        createSpan.classList.add('failed-span');
        referencia.appendChild(createSpan);

    };

    function quitarAlerta(referencia){
        const alerta = referencia.querySelector('.failed-span')
        if(alerta){
            alerta.remove();
        };
    };

    function cerrarForm(e){
        e.preventDefault();
        formContainer.classList.add('hide');
        createButton.classList.remove('click-me');
        createButton.setAttribute('disabled', 'true');
        
        setTimeout(() => {
            formContainer.style.display = 'none';
            formContainer.style.opacity = '0';
            formContainer.style.visibility = 'hidden';
            formContainer.classList.remove('hide');
            console.log('Cerró todo');
        }, 450);
        mainForm.reset();
        resetObj();
        console.log(form);
        quitarEstilos();
        
    }

    function validarTodo(){
        if(inputName.value.trim() === '' || inputDescription.value.trim() === ''){
            createButton.style.opacity = '.8';
            console.log('Cta NO está disponible');
            createButton.classList.remove('click-me');
            createButton.setAttribute('disabled', 'true');
        } else{
            console.log('Cta está disponible');
            // createButton.style.opacity = '1';
            createButton.classList.add('click-me');
            createButton.removeAttribute('disabled');
        };
    };

    function quitarEstilos(){
        if(inputName.classList.contains('succeed') || inputName.classList.contains('failed')){
            inputName.classList.remove('succeed');
            inputName.classList.remove('failed');
            quitarAlerta(document);
            // return;
        }
        if(inputDescription.classList.contains('succeed') || inputDescription.classList.contains('failed')){
            inputDescription.classList.remove('succeed');
            inputDescription.classList.remove('failed');
            quitarAlerta(document);
            return;
        }
    }

    function aparecer(){
        formContainer.style.opacity = '1';
        formContainer.style.visibility = 'visible';
        formContainer.style.display = 'grid';
        inputName.focus();
    };

    function resetObj(){
        form.taskname = '';
        form.description = '';
        form.time1 = '';
        form.time2 = '';
    }
:root{
    --tamaño-1: 28px;
    --tamaño-2: 19px;
    --tamaño-3: 18px;
    --tamaño-4: 16px;
    --verde-fondo: #205b52;
    --verde-claro: #D3FEE4;
    --azul-letra: #2368dd;
    --color-texto-1: #000;
    --color-texto-2: #888888;
    --color-texto-3: #bababa;
    --blanco-fondo: #fff;

    --rojo-fondo: #ffeaef;
    --rojo: #f7345e;
    --verde-input-fondo: #e7f5ec;
    --verde: #34d39d;

}

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Figtree', sans-serif;
    cursor: default;
}

button{
    background: none;
    border:none;
}
path{
    transition: .3s;
}
/* body{
    background-color: #d0d1da;
} */

.main-div{
    max-width: 500px;
    margin:0 auto;
    background-color: #f9f9f9;
    padding: 40px 30px;
    /* height: 100vh; */
    border-radius: 20px;
    box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.1), 0px 1px 3px 0px rgba(0, 0, 0, 0.08);
}

header{
    display: flex;
    justify-content: space-between;
    padding: 35px;
}


main .header-2 .first{
    display: grid;
    place-content: center;
    margin-bottom: 20px;
}

.section-1{
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}
h1, h5{
    font-size: var(--tamaño-1);
    font-weight: 600;
    color: var(--color-texto-1);
}
h2{
    font-weight: 500;
}
h3{
    font-size: 20px;
    font-weight: 500;
}
#cta{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 12px 20px;
    font-size: var(--tamaño-4);
    /* font-weight: 500; */
    border-radius: 12px;
    background-color: var(--verde-fondo);
    color: var(--blanco-fondo);
    border: none;
    transition: .3s;
}
#cta:is(:hover){
    opacity: .9 !important;
}

#plus{
    stroke: var(--azul-letra);
}

#trash:is(:hover) > svg >path{
    stroke: #f7345e;
}
.check:is(:hover) > svg >path{
    stroke: var(--verde-fondo);
}

.second{
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.second span{
    color: var(--color-texto-2);
    font-weight: 400;
}

.section-2{
    margin-bottom: 40px;
}
.section-2 ul{
    display: flex;
    align-items: center;
    /* font-weight: 500; */
    color: var(--color-texto-2);
    text-decoration: none;
    list-style-type: none;
    gap: 15px;
}

.section-2 ul li{
    display: flex;
    align-items: center;
    gap: 7px;
}
.section-2 ul li span{
    background-color: var(--azul-letra);
    color: #fff;
    padding: 5px;
    border-radius: 45%;
    font-size: 12px;
}
.section-2 ul #separador{
    width: 2px;
    background: var(--color-texto-3);
    border-radius: 10px;
    height: 16px;
}


/* TASKS */

.task{
    background-color: var(--blanco-fondo);
    margin-bottom: 20px;
    padding: 20px;
    border-radius: 12px;
    box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.1), 0px 1px 3px 0px rgba(0, 0, 0, 0.08);
}

.header-task{
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--color-texto-3);
}
.header-task div{
    display: flex;
    flex-direction: column;
    /* gap: 5px; */
}
.header-task div span{
    color: var(--color-texto-2);
    font-size: 15px;
    cursor: text;
}
.footer-task{
    display: flex;
    justify-content: space-between;
    margin-top: 20px;
}
.footer-task div{
    display: flex;
    justify-content: space-between;
    gap: 10px;
    align-items: center;
}
.footer-task button, .header-task div button{
    height: 30px;
    width: 30px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
}
.footer-task div p{
    color: var(--color-texto-2);
    font-size: 15px;
}

.footer-task div span{
    color: var(--color-texto-2);
    font-size: 15px;
}

h4, label{
    font-size: var(--tamaño-2);
    font-weight: 500;
}
h4{
    padding: 5px 5px 5px 0px;
    border-radius: 6px;
    transition: all .2s ease-in-out;
    cursor: text;
}
h4[contenteditable]:hover{
    /* background-color: #f0faf9; */
    /* background-color: #B9F3D0; */
    background-color: #D3FEE4;
}
h4[contenteditable]:focus-visible, h4[contenteditable]:focus, h4[contenteditable]:active, h4[contenteditable]:focus-within{
    /* background-color: #f0faf9; */
    /* background-color: #B9F3D0; */
    background-color: #D3FEE4;
    outline: none;
}

/* // container cta */

.container{
    display: grid;
    place-content: center;
    gap: 7px;
    padding: 10px;
    text-align: center;
    border: 2px dashed var(--color-texto-3);
    height: 30vh;
    border-radius: 12px;
    transition: .2s;
    /* cursor: pointer; */
}
.container p{
    font-size: 15px;
    font-weight: 500;
    color: var(--verde-fondo);
    padding: 0px 20px;
}
.container:is(:hover){
    /* border: 2px dashed var(--color-texto-2); */
    border: 2px dashed var(--verde-fondo);
}

/* // Create task form */

.create-task{
    margin: 0 auto;
    max-width: 500px;
    padding: 40px 30px;
    /* margin-top: 40px; */
    background-color: #f9f9f9;
    border-radius: 20px;
    box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.1), 0px 1px 3px 0px rgba(0, 0, 0, 0.08);
    animation-name: fade-in;
    animation-iteration-count: 1;
    animation-duration: 500ms;
}
.create-task div form div{
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.create-task div, button{
    /* display: grid; */
    place-content: start;
}
.grid{
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas: 
        "n n"
        "d d"
        "t1 t2"
        "r r"
        "b b";
    gap: 15px;
}
.name{
    grid-area: n;
}
.description{
    grid-area: d;
}
.time1{
    grid-area: t1;
}
.time2{
    grid-area: t2;
}
.grid-container .grid{
    margin-top: 15px;
}
.header-form{
    display: flex;
    justify-content: space-between !important;
    align-items: center;
}
.header-form span{
    display: flex;
    align-items: center;
    justify-content: flex-end;
    height: 30px;
    width: 30px;
}
span:is(:hover) > svg >path{
    stroke: var(--color-texto-1);
}
label{
    font-size: 15px;
}
.radio{
    display: flex;
    align-items: center;
    grid-area: r;
    flex-direction: row !important;
}
.buttons{
    display: grid !important;
    grid-area: b;
    gap: 15px !important;
    grid-template-columns: 1fr;
    grid-template-areas:
    "create"
    "cancel";
    flex-direction: row-reverse !important;
    /* border-top: 1px solid var(--color-texto-3); */
}
.buttons button{
    display: flex;
    justify-content: center;
    padding: 13px 0px;
    background-color: var(--blanco-fondo);
    transition: .2s;
    border-radius: 12px;
}
#cancel{
    display: flex;
    align-items: center;
    grid-area: cancel;
    background-color: transparent;
    border: 2px solid var(--color-texto-2);
    transition: .2s;
    font-size: 15px;
}
#cancel:is(:hover){
    background-color: #f9f9f9;
    border: 2px solid var(--color-texto-1);
}
#create{
    display: flex;
    align-items: center;
    grid-area: create;
    font-size: 15px;
    border: 2px solid var(--verde-fondo);
    background-color: var(--verde-fondo);
    transition: .2s;
    color: var(--blanco-fondo);
    opacity: .8;
}
input{
    padding: 13px 0px;
    border-radius: 10px;
    border: 2px solid var(--color-texto-2);
    transition: .2s;
    background-color: var(--blanco-fondo);
    color: var(--color-texto-1);
    padding-left: 13px;
    font-weight: 500;
}
input:focus-visible{
    outline: none;
}
input:focus{
    border: 2px solid var(--color-texto-1);
    background-color: var(--blanco-fondo);
}
input[placeholder]{
    font-size: 14px;
    font-weight: 500;
    padding-left: 13px;
}
input[type="checkbox"]{
    appearance: none;
    background-color: transparent;
    margin: 0;
    width: 24px;
    height: 24px;
    border: 2px solid var(--color-texto-2);
    border-radius: 100%;
    padding: 0px;
    display: grid;
    place-content: center;
    transition: all .2s ease-in-out;
}
input[type="checkbox"]::before{
    content: url("data:image/svg+xml,%3Csvg width='12' height='10' viexBox='0 0 12 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 1L4.5 9L1.5 5.5' stroke='%23fff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
    transform: scale(0);
    transition: all .2s ease-in-out;
}
input[type="checkbox"]:checked{
    background-color: var(--verde-fondo);
    border-color: var(--verde-fondo);
}
input[type="checkbox"]:checked::before{
    transform: scale(1);
}

#create-task-container{
    
    display: none;
    visibility: hidden;
    opacity: 1;
    place-content: center;
    background-color: rgba(0, 0, 0, 0.6);
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
}

footer{
    display: grid;
    place-content: center;
    margin: 20px;
    cursor: default;
}
footer p{
    color: var(--color-texto-2);
    font-size: 13px;
}
/* footer p span{
    text-decoration: underline;
} */

/* // Clases para javascript */




.done{
    background-color: var(--verde-claro) ;
}
.tacho{
    text-decoration: line-through;
}
.succeed{
    background-color: var(--verde-input-fondo);
    border: 2px solid var(--verde);
}
.hide{
    animation-name: fade-out;
    animation-iteration-count: 1;
    animation-duration: 500ms;
}
.failed{
    background-color: var(--rojo-fondo);
    border: 2px solid var(--rojo);
}
.failed-span{
    color: var(--rojo);
    font-size: 14px;
    font-weight: 500;
    transition: .2s;
}
/* .click-me{
    opacity: 1;
} */
.buttons button.click-me{
    opacity: 1 !important;
}
.buttons button.click-me:hover{
    opacity: .9 !important;
}







/* // Media Queries */

@media screen and (min-width: 550px){

    .buttons{
        grid-template-columns: 1fr 1fr;
        grid-template-areas:
        "cancel create"
        ;
    }

    .create-task{
        min-width: 500px;
    }
}

/* //Keyframes */

 @-webkit-keyframes fade-in {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @keyframes fade-in {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }

  @-webkit-keyframes fade-out {
    0% {
      opacity: .9;
    }
    100% {
      opacity: 0;
    }
  }
  @keyframes fade-out {
    0% {
      opacity: .9;
    }
    100% {
      opacity: 0;
    }
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="styles.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;800&display=swap" rel="stylesheet">
</head>
<body>
    <header>
        <h2>TicTac</h2>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M12 2V4M12 20V22M4 12H2M6.31412 6.31412L4.8999 4.8999M17.6859 6.31412L19.1001 4.8999M6.31412 17.69L4.8999 19.1042M17.6859 17.69L19.1001 19.1042M22 12H20M17 12C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12C7 9.23858 9.23858 7 12 7C14.7614 7 17 9.23858 17 12Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
        </svg>
    </header>

    <main>
        <div class="header-2">
            <div class="first">
                <h3>Today's Task</h3>
            </div>

            <div class="main-div">
                <div class="section-1">
                    <div class="second">
                        <h1>Today's Task</h1>
                        <span>Thursday, 18 May</span>
                    </div>
                    <div class="cta">
                        <button id="cta">
                            <svg id="plus" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M12 5V19M5 12H19" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                         New Task</button>
                    </div>
                </div>
                
                <div class="section-2">
                    <ul>
                        <li>All</li>
                        <li id="separador"></li>
                        <li>Remaining</li>
                        <li>Completed</li>
                    </ul>
                </div>

                <div class="section-3">
                    
                </div>
                <div class="section-empty">
                    <div class="container">
                        <div>
                            <svg width="50" height="50" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M20 10.5V6.8C20 5.11984 20 4.27976 19.673 3.63803C19.3854 3.07354 18.9265 2.6146 18.362 2.32698C17.7202 2 16.8802 2 15.2 2H8.8C7.11984 2 6.27976 2 5.63803 2.32698C5.07354 2.6146 4.6146 3.07354 4.32698 3.63803C4 4.27976 4 5.11984 4 6.8V17.2C4 18.8802 4 19.7202 4.32698 20.362C4.6146 20.9265 5.07354 21.3854 5.63803 21.673C6.27976 22 7.11984 22 8.8 22H12M14 11H8M10 15H8M16 7H8M18 21V15M15 18H21" stroke="#205b52" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg> 
                        </div>
                        <p>Such empty. Get started by creating a new task</p>
                        
                    </div>
                </div>
            </div>
        </div>
    </main>

    <div id="create-task-container">
        <div class="create-task">
            <div class="grid-container">
                <div class="header-form">
                    <h5>Create a Task</h5>
                    <span id="close-button">
                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M18 6L6 18M6 6L18 18" stroke="#888888" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                        </svg>
                    </span>
        
                </div>
                <form class="grid">
                    <div class="name">
                        <label for="taskname">What's your goal today?</label>
                        <input id="taskname" placeholder="" type="text">
                    </div>
                    <div class="description">
                        <label for="description">Description</label>
                        <input id="description" placeholder="Add a short description to your task" type="text">
                    </div>
                    <div class="time1">
                        <label for="time1">Time-From</label>
                        <input id="time1" type="time">
                    </div>
                    <div class="time2">
                        <label for="time2">Time-To</label>
                        <input id="time2" type="time">
                    </div>
                    <div class="radio">
                        <input type="checkbox" class="checkbox" id="radio">
                        <label for="radio">It's gonna be an all day task instead.</label>
                    </div>
                    <div class="buttons">
                        <button id="cancel">Cancel</button>
                        <button type="submit" disabled id="create">Create Task</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

    <footer>
        <!-- <p>Developed by <span>Gabriel Maestre.</span></p> -->
        <p>Developed by Gabriel Maestre.</p>
    </footer>
    
    <script src="app.js"></script>
</body>
</html>

JS routing issue

I have tried my best but yet to find out why my routing isn’t working.
I am trying to create a local android app.
Here’s my src/app files if needed
app.component.spec.ts suset.jpeg login app.component.css main-page app.component.ts app.module.ts

Here’s my code:
This is the main page (for the login) – app.components.ts:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';

@Component({
    selector: 'my-app',
    template: `
        <div class="login-container">
            <div class="logo">
                <h1 class="logo-text">DIGITAL PAY</h1>
            </div>
            <h1 class="login-heading label-text">LOGIN</h1>

            <div class="input-group">
                <label for="username" class="label-text">Username:</label>
                <input type="text" id="username" [(ngModel)]="username" class="login-input" />
            </div>

            <div class="input-group">
                <label for="password" class="label-text">Password:</label>
                <input type="password" id="password" [(ngModel)]="password" class="login-input" />
            </div>

            <button class="login-button" (click)="login()">Login</button>

            <p *ngIf="errorMessage" class="error-message">{{ errorMessage }}</p>
            <p *ngIf="response" class="response-message">{{ response }}</p>
            <div class="signup-link label-text">
                Don't have an account? <a (click)="goToSignUp()">Sign up</a>
            </div>
        </div>
    `,
})
export class AppComponent {
    username: string;
    password: string;
    errorMessage: string;
    response: any;

    constructor(private http: HttpClient, private router: Router) {
        this.username = '';
        this.password = '';
        this.errorMessage = '';
        this.response = '';
    }


    login() {
        const url = 'http://localhost:5000/login';
        // const url = 'http://10.0.2.2:5000/login';
        const data = { username: this.username, password: this.password };

        this.http.post(url, data).subscribe(
            (response: any) => {
                const user_id = response.user_id;
                if (user_id === "None") {
                    this.response = '';
                    this.errorMessage = 'Invalid username or password.';
                } else {
                    this.errorMessage = '';
                    this.response = user_id;
                    this.router.navigate(['/main-page']);
                }
            },
            (error) => {
                this.errorMessage = "error";
            }
        );
    }
    goToSignUp() {
        // this.router.navigate(['/signup']);
        this.response = "Under maintenance!"
    }
}

This is the app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule }   from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { MainPageComponent } from './main-page/main-page.component';
import {RouterModule} from "@angular/router";

@NgModule({
  declarations: [
    AppComponent,
    MainPageComponent
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
    FormsModule,
    RouterModule.forRoot([
      { path: 'main-page', component: MainPageComponent }
    ], { enableTracing: true })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

I don’t understand why the route to ‘/main’ doesn’t work.
The login is succefully but it isn’t moving to the next page (the main)

Typescript 5.0, importing .ts files and building project?

Is there any way with Typescript 5.0 to both import Typescript modules using the .ts extension and have the code transpiled to the dist folder?

In our Typescript 5.0 project we are importing our typescript modules using ‘.js’ file extensions, such that:

import InvalidValueError from '../errors/InvalidValueError.js'

rather than:

import InvalidValueError from '../errors/InvalidValueError.ts'

We can do the import of the ‘.ts’ file if we add the following to the compilerOptions
section tsconfig.json file:

  "noEmit": true,
  "allowImportingTsExtensions": true

With this we get errors of the form:

An import path can only end with a ‘.ts’ extension when ‘allowImportingTsExtensions’ is enabled

The issue here is that while it does allow importing, running tsc -p . no longer generates the Javascript files in out dist folder.

The reason we are wanting to explicitly import using the ‘.ts’ extension is that it makes more sense the developer to be importing the file as presented on the file system and leaving any further transformation to the transpiler. The opposite would be seen as the ‘C’ equivalent of including ‘.o’ files, rather than ‘.h’ or ‘.c’ files.