1) При переходе к странице поиска выдает сразу всех артистов
2) При попытке выбрать артиста или группа (критерии поиска) выбор сбрасывается, а url начинает множить: http://localhost:3000/search?query=&role=Artist&role=Artist%2C
3) При нажатии кнопки поиска при пустом поле url также начинает множить: http://localhost:3000/search?query=&role=&role=%2C%2C%2C%2C%2C%2C%2C%2C%2CArtist%2CArtist%2C
4) При поиске по имени или жанру возникает ошибка: ReferenceError: role is not defined

app.js:
const express = require("express");
const fs = require("fs");
const session = require("express-session");
const fileUpload = require("express-fileupload");
const app = express();


app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(express.urlencoded({ extended: true }));
app.use(fileUpload());
app.use(session({
  secret: "mysecretkey",
  resave: false,
  saveUninitialized: false
}));

const predefinedGenres = ['Rock', 'Pop', 'Jazz', 'Hip Hop', 'Electronic', 'Blues'];

function getMusicianById(id) {
  const data = fs.readFileSync("./db/musicians.json");
  const musicians = JSON.parse(data);

  return musicians.musicians.find(musician => musician.id === id);
}

function requireLogin(req, res, next) {
  if (req.session.musicianId) {
    next();
  } else {
    res.redirect("/login");
  }
}

function search(query, hiddenRole) {
  const data = fs.readFileSync('./db/musicians.json');
  const musicians = JSON.parse(data).musicians.map(musician => {
    return {
      name: musician.name,
      genre: musician.genre,
      originalName: musician.name,
      profileLink: `/profile/${musician.id}`,
      thumbnail: musician.thumbnail,
      soundcloud: musician.soundcloud
    };
  });
  let results = musicians;
  if (query) {
    const lowerQuery = query.toLowerCase();
    results = musicians.filter(musician => {
      const nameScore = musician.name.toLowerCase().startsWith(lowerQuery) ? 2 : musician.name.toLowerCase().includes(lowerQuery) ? 1 : 0;
      const genreScore = musician.genre.toLowerCase().startsWith(lowerQuery) ? 2 : musician.genre.toLowerCase().includes(lowerQuery) ? 1 : 0;
      return nameScore + genreScore > 0 && (role === '' || musician.role === role);
    }).sort((a, b) => {
      const aNameScore = a.name.toLowerCase().startsWith(lowerQuery) ? 2 : a.name.toLowerCase().includes(lowerQuery) ? 1 : 0;
      const bNameScore = b.name.toLowerCase().startsWith(lowerQuery) ? 2 : b.name.toLowerCase().includes(lowerQuery) ? 1 : 0;
      const aGenreScore = a.genre.toLowerCase().startsWith(lowerQuery) ? 2 : a.genre.toLowerCase().includes(lowerQuery) ? 1 : 0;
      const bGenreScore = b.genre.toLowerCase().startsWith(lowerQuery) ? 2 : b.genre.toLowerCase().includes(lowerQuery) ? 1 : 0;
      return (bNameScore + bGenreScore) - (aNameScore + aGenreScore);
    });
  }
  return results;
}

app.use((req, res, next) => {
  if (req.session.musicianId) {
    const musician = getMusicianById(req.session.musicianId);
    res.locals.musician = musician;
    res.locals.userLoggedIn = true;
    res.locals.username = musician.name;
  } else {
    res.locals.userLoggedIn = false;
  }

  next();
});

app.get("/", (req, res) => {
  const data = fs.readFileSync("./db/musicians.json");
  const musicians = JSON.parse(data);

  res.render("index", { musicians: musicians.musicians });
});

app.get("/register", (req, res) => {
  if (req.session.musicianId) {
    const musician = getMusicianById(req.session.musicianId);
    res.redirect("/profile/" + musician.id);
  } else {
    res.render("register");
  }
});

app.post("/register", (req, res) => {
  if (req.session.musicianId) {
    const musician = getMusicianById(req.session.musicianId);
    res.redirect("/profile/" + musician.id);
  } else {
    const data = fs.readFileSync("./db/musicians.json");
    const musicians = JSON.parse(data);

    const newMusician = {
      id: musicians.musicians.length + 1,
      name: req.body.name,
      genre: req.body.genre,
      instrument: req.body.instrument,
      soundcloud: req.body.soundcloud,
      password: req.body.password,
      location: req.body.location,
	  role: req.body.role,
      login: req.body.login
    };

    if (req.files && req.files.thumbnail) {
      const file = req.files.thumbnail;
      const filename = "musician_" + newMusician.id + "_" + file.name;
      file.mv("./public/img/" + filename);

      newMusician.thumbnail = filename;
    }

    musicians.musicians.push(newMusician);
    fs.writeFileSync("./db/musicians.json", JSON.stringify(musicians));

    req.session.musicianId = newMusician.id;
    res.redirect("/profile/" + newMusician.id);
  }
});

app.get("/profile/:id", (req, res) => {
  const musician = getMusicianById(parseInt(req.params.id));

  if (musician) {
    res.render("profile", { musician: musician });
  } else {
    res.status(404).send("Musician not found");
  }
});

app.get("/login", (req, res) => {
  res.render("login");
});

app.post("/login", (req, res) => {
  const data = fs.readFileSync("./db/musicians.json");
  const musicians = JSON.parse(data);

  const musician = musicians.musicians.find(musician => musician.login === req.body.login && musician.password === req.body.password);

  if (musician) {
    req.session.musicianId = musician.id;
    res.redirect("/profile/" + musician.id);

  } else {
    res.render("login", { error: "Invalid login or password" });
  }
});

app.get("/logout", (req, res) => {
  req.session.destroy();
  res.redirect("/");
});

app.get('/search', (req, res) => {
const query = req.query.query || '';
const role = req.query.role || '';
const musicians = search(query, role);
res.locals.predefinedGenres = predefinedGenres;
res.render('search', { musicians, query, role });
});

app.get("/profile/:id/edit", requireLogin, (req, res) => {
  const musician = getMusicianById(parseInt(req.params.id));

  if (musician) {
    if (req.session.musicianId === musician.id) { // Check if the logged-in user is the owner of the profile
      res.render("edit-profile", { musician: musician });
    } else {
      res.status(403).send("Access denied");
    }
  } else {
    res.status(404).send("Musician not found");
  }
});





app.post('/profile/:id/edit', requireLogin, (req, res) => {
  const musician = getMusicianById(parseInt(req.params.id));

  if (musician) {
    if (!req.body.name || !req.body.genre) {
      res.status(400).send('Please fill out all fields');
    
    } else {
      musician.name = req.body.name;
      musician.genre = req.body.genre;
      musician.instrument = req.body.instrument;
      musician.soundcloud = req.body.soundcloud;
	  musician.soundcloud1 = req.body.soundcloud1;
  musician.soundcloud2 = req.body.soundcloud2;
      musician.location = req.body.location;
	  musician.role = req.body.role;
      musician.bio = req.body.bio;

      if (req.files && req.files.thumbnail) {
        const file = req.files.thumbnail;
        const filename = 'musician_' + musician.id + '_' + file.name;
        file.mv('./public/img/' + filename);
        musician.thumbnail = filename;
      }

      const data = fs.readFileSync('./db/musicians.json');
      const musicians = JSON.parse(data);
      const index = musicians.musicians.findIndex(m => m.id === musician.id);
      musicians.musicians[index] = musician;

      fs.writeFileSync('./db/musicians.json', JSON.stringify(musicians));

      res.redirect('/profile/' + musician.id);
    }
  } else {
    res.status(404).send('Musician not found');
  }
  
  
});

function isValidSoundCloudUrl(url) {
  return url.startsWith('https://soundcloud.com/');
}

app.listen(3000, () => {
  console.log("Server started on port 3000");
});

search.ejs:

<!DOCTYPE html>
<html>
  <head>
    <title>Search Musicians</title>
  </head>
  <body>
    <h1>Search Musicians</h1>
    <form method="get">
      <label for="query">Search by name or genre:</label>
      <input type="text" id="query" name="query" value="<%= query %>">
      <br><br>
      <label for="role">Search by role:</label>
      <select id="role" name="role">
        <option value="">All</option>
        <option value="Band" <% if (role === 'Band') { %>selected<% } %>>Band</option>
        <option value="Artist" <% if (role === 'Artist') { %>selected<% } %>>Artist</option>
      </select>
      <!-- Исправлен атрибут name -->
      <input type="hidden" id="role" name="role" value="<%= role %>">
      <br><br>
      <button type="submit">Search</button>
    </form>
    <% if (musicians.length > 0) { %>
      <h2>Results:</h2>
      <ul>
        <% musicians.forEach(musician => { %>
          <li>
            <a href="<%= musician.profileLink %>">
              <%= musician.name %>
              <% if (musician.thumbnail) { %>
                <img src="/img/<%= musician.thumbnail %>" alt="<%= musician.name %>">
              <% } %>
            </a>
            - <%= musician.genre %>
            <% if (musician.soundcloud) { %>
              <a href="<%= musician.soundcloud %>">SoundCloud</a>
            <% } %>
          </li>
        <% }); %>
      </ul>
    <% } else if (query || role) { %>
      <p>No musicians found.</p>
    <% } %>

    <script>
      document.querySelector('#role').addEventListener('change', function() {
const form = document.querySelector('form');
const query = document.querySelector('#query').value;
const role = this.value;
const url = '/search?query=' + encodeURIComponent(query) + '&role=' + encodeURIComponent(role);
form.action = url;
form.submit();
});
    </script>
  </body>
</html>