ASP.NET Core Razor page favorite list with localstorage

Who can help me create a favorite list of teams for example that I can then display on another page and do this with local storage? The list comes from a SQL database.

At the end of the list (table) there is a heart icon, which you can click on. When you click on the heart icon it changes into another icon. But when I refresh the page I want to see the selected items again. Also, when I open another page, I get a list of my selected items.

teams.cshtml:

@page
@model organizer.Pages.TeamsModel
@using Microsoft.AspNetCore.Http
@addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers

@{
    Layout = "_Layout2";
}

<div class="eigentabel">
    <h3 class="text-end"> @Model.variabelTNaam</h3>
    @foreach (var itemD in Model.listDivisieD)
    {           
    //hier zetten we de titel op de pagina
        <span><h2>@itemD.naam </h2></span>
        <table id="" class="display">
        @{
        Model.nummer = 0;  
        }
        <thead>
            <tr>
                    <th style="width: 2%">#</th>
                <th style ="text-align: center; width: 2%"></th>
                <th style="text-align: left; width: 10%">Team name</th>
                <th style="width: 5%">Country</th>
                <th style="width: 5%">Payed on</th>
                <th style="width: 5%">Like</th>
            </tr>
        </thead>
                <tbody>

            @foreach (var itemT in Model.listTeamT)
            {
            if (itemT.divisie == @itemD.naam)
            {
            <tr>
            @{
            Model.nummer = Model.nummer + 1; 
            }

                    <td>@Model.nummer</td>
                    <td><img src="https://@itemT.vlag" width="20" height="13"></td>
                    <td><a asp-page-handler="Team" asp-route-varTeamId="@itemT.id">@itemT.naam</a></td>
                    <td>@itemT.land</td>
                    <td>@itemT.betaling</td>
                    <td><i onclick="myFunction(this)" id="hartje" class="fa fa-heart-o"></i></td>
            </tr>
            }
        }
        </tbody>
        </table>
    }
</div>

teams.cshtml.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Data.SqlClient;

namespace organizer.Pages
{
    public class TeamsModel : PageModel
    {
        public String? variabelTNaam;
        public List<TeamInfoT> listTeamT = new();
        public List<DivisieInfoD> listDivisieD = new();
        public string? sessionvarTorId;
        public int nummer;
        private readonly IConfiguration _configuration;

        //Dit moeten we hier zetten en de variabele instellen
        public void OnGetTeamAsync(Guid? varTeamId)
        {
            HttpContext.Session.SetString("SessionTeamId", varTeamId.ToString());
            Response.Redirect("/Team_detail"); 
        }

        public TeamsModel(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public void OnGet()
        {
            // Set value in Session object.
            if (HttpContext.Session.GetString("SessionTorId") != null)
                sessionvarTorId = HttpContext.Session.GetString("SessionTorId");
                
            try
            {
                string connString = _configuration.GetConnectionString("DefaultConnection");
                using SqlConnection connection = new(connString);
                connection.Open();
                String sqlD = "SELECT  .....";
                String sqlT = "SELECT ...";
                String sql1 = "SELECT ...";

                using SqlCommand command1 = new(sql1, connection);
                variabelTNaam = (string)command1.ExecuteScalar();

                using (SqlCommand commandD = new(sqlD, connection))
                {
                    using SqlDataReader readerD = commandD.ExecuteReader();

                    while (readerD.Read())
                    {
                        DivisieInfoD divisieInfoD = new()
                        {
                            id = readerD.GetGuid(0),
                            naam = readerD.GetString(2),
                            maxTeams = readerD.GetInt32(14),
                        };

                        listDivisieD.Add(divisieInfoD);
                    }
                }

                using SqlCommand commandT = new(sqlT, connection);
                { 
                    using SqlDataReader readerT = commandT.ExecuteReader();

                    while (readerT.Read())
                    {
                        TeamInfoT teamInfoT = new()
                        {
                            id = readerT.GetGuid(0),
                            naam = readerT.GetString(1),
                            land = readerT.GetString(2),
                            vlag = readerT.GetString(3).ToString().ToLower().Replace(" ", "_"),
                            betaling = readerT.IsDBNull(4) ? "-" : readerT.GetDateTime(4).ToString("dd-MMM-yyyy"),
                            divisie = readerT.GetString(5),
                        };
                    
                        listTeamT.Add(teamInfoT);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("NOT Connected"); 
                Console.WriteLine("Exception: connectie NIET ok " + ex.Message);
            }
        }
    }

    public class DivisieInfoD
    {
        public String? naam;
        public Guid? id;
        public int maxTeams;
    }

    public class TeamInfoT
    {
        public Guid id;
        public String? naam;
        public String? land;
        public String? vlag;
        public String? betaling;
        public String? divisie;
    }
}

_layout2.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - TEST</title>

    <!-- DataTables -->
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap.min.css" />
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
    <link rel="stylesheet" href="~/js/datatables.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" />
    <link href="~/css/site.css" rel="stylesheet" />
    <!-- Font Awesome CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
   
<body>
    <header>
     <div class="fixed-top"> 
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm bg-primary navbar-dark border-bottom box-shadow mb-3 ">
            <div class="container-fluid">
                <div class="navbar-left">
                    <a class="navbar-brand"  target="_blank">                     
                    </a>
                </div>
                <div class="navbar-right">
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                
                    <div class="navbar-collapse collapse d-sm-inline-flex justify-content-end">
                        <ul class="navbar-nav flex-grow-1">
                            <li class="nav-item">
                                <a class="nav-link text-light " style="margin-left:1em" asp-area="" asp-page="/Index"><span class="fa fa-home"></span> Home</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link text-light " style="margin-left:1em" asp-area="" asp-page="/Tornooi_Algemeen"><span class="fa fa-dashboard"></span> Dashboard</a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </nav>
    </div>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy;  - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    <script type="text/javascript">
        //function changing heart
        function myFunction(x) {
            x.classList.toggle("fa-thumbs-up");
            window.localStorage.setItem("FavoriteTeam", "test");
        }

        // Initialize the DataTable
        $(document).ready(function () {
            $('table.display').DataTable({
                // Set the number of rows to be
                // displayed per page on the DataTable
                pageLength: 25,
                lengthMenu: [25, 50]
            });
        });

        // Initialize the DataTable
        $(document).ready(function () {
            $('table.display2').DataTable({
 
        "dom": "<'row'<'col-lg-10 col-md-10 col-xs-12'f><'col-lg-2 col-md-2 col-xs-12'l>>" +
                    "<'row'<'col-sm-12'tr>>" +
                    "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",

                // Set the number of rows to be
                // displayed per page on the DataTable
                pageLength: 25,
                lengthMenu: [25, 50, 100]
            });
        });
    </script>

    <!-- Google tag (gtag.js) -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-4CPZWF653F"></script>
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag() { dataLayer.push(arguments); }
        gtag('js', new Date());

        gtag('config', 'G-4CPZWF653F');
    </script>



    <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>

    @await RenderSectionAsync("Scripts", required: false)

</body>
</html>

Upvotes: -2

Views: 193

Answers (1)

Jalpa Panchal
Jalpa Panchal

Reputation: 12789

You could try below code:

Data/ApplicationDbContext.cs:

using Microsoft.EntityFrameworkCore;
using System.Text.Json.Serialization;

namespace FavoriteTeams.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
               : base(options)
        {
        }

        public DbSet<Team> Teams { get; set; }
        public DbSet<Division> Divisions { get; set; }
    }

    public class Team
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Country { get; set; }
        public string Flag { get; set; }
        public DateTime? Payment { get; set; }
        public Guid DivisionId { get; set; }

        [JsonIgnore]
        public Division Division { get; set; }
    }

    public class Division
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public int MaxTeams { get; set; }

        [JsonIgnore]
        public ICollection<Team> Teams { get; set; }
    }

}

Data/DbInitializer.cs:

using Microsoft.EntityFrameworkCore;

namespace FavoriteTeams.Data
{
    public class DbInitializer
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            using (var context = new ApplicationDbContext(
                serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>()))
            {
                if (context.Divisions.Any() || context.Teams.Any())
                {
                    return;   // DB has been seeded
                }

                var divisions = new Division[]
                {
                       new Division { Id = Guid.NewGuid(), Name = "Division 1", MaxTeams = 10 },
                       new Division { Id = Guid.NewGuid(), Name = "Division 2", MaxTeams = 10 }
                };

                foreach (var d in divisions)
                {
                    context.Divisions.Add(d);
                }

                context.SaveChanges();

                var teams = new Team[]
                {
                       new Team { Id = Guid.NewGuid(), Name = "Team 1", Country = "Country 1", Flag = "flag_url_1", Payment = DateTime.Now, DivisionId = divisions[0].Id },
                       new Team { Id = Guid.NewGuid(), Name = "Team 2", Country = "Country 2", Flag = "flag_url_2", Payment = DateTime.Now, DivisionId = divisions[1].Id }
                };

                foreach (var t in teams)
                {
                    context.Teams.Add(t);
                }

                context.SaveChanges();
            }
        }
    }

}

Pages/Shared/_Layout.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - FavoriteTeams</title>
   @*  <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> *@
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/FavoriteTeams.styles.css" asp-append-version="true" />

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap.min.css" />
    <!-- DataTables CSS -->
    <link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
    <!-- Font Awesome CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">FavoriteTeams</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - FavoriteTeams - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    @* <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script> *@

    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- Bootstrap JS -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.bundle.min.js"></script>
    <!-- DataTables JS -->
    <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>


    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Pages/Teams.cshtml:

@page
@model FavoriteTeams.Pages.TeamsModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@{
    Layout = "_Layout";
}

<div class="eigentabel">
    <h3 class="text-end">Teams Overview</h3>
    @foreach (var division in Model.Divisions)
    {
        <span><h2>@division.Name </h2></span>
        <table id="[email protected]" class="display">
            <thead>
                <tr>
                    <th style="width: 2%">#</th>
                    <th style="text-align: center; width: 2%"></th>
                    <th style="text-align: left; width: 10%">Team name</th>
                    <th style="width: 5%">Country</th>
                    <th style="width: 5%">Payed on</th>
                    <th style="width: 5%">Like</th>
                </tr>
            </thead>
            <tbody>
                @{
                    var num = 0;
                }
                @foreach (var team in Model.Teams.Where(t => t.DivisionId == division.Id))
                {
                    <tr>
                        <td>@(++num)</td>
                        <td><img src="https://@team.Flag" width="20" height="13"></td>
                        <td>@team.Name</td>
                        <td>@team.Country</td>
                        <td>@(team.Payment.HasValue ? team.Payment.Value.ToString("dd-MMM-yyyy") : "-")</td>
                        <td><i onclick="toggleFavorite('@team.Id', this)" class="fa fa-heart-o heart-icon" data-team-id="@team.Id"></i></td>
                    </tr>
                }
            </tbody>
        </table>
    }
</div>

@section Scripts {
    <script type="text/javascript">
        function toggleFavorite(teamId, element) {
            const favorites = JSON.parse(localStorage.getItem('favoriteTeams')) || [];
            const index = favorites.indexOf(teamId);

            if (index === -1) {
                favorites.push(teamId);
                element.classList.remove("fa-heart-o");
                element.classList.add("fa-heart");
            } else {
                favorites.splice(index, 1);
                element.classList.remove("fa-heart");
                element.classList.add("fa-heart-o");
            }

            localStorage.setItem('favoriteTeams', JSON.stringify(favorites));
        }

        document.addEventListener("DOMContentLoaded", function () {
            const favorites = JSON.parse(localStorage.getItem('favoriteTeams')) || [];
            const icons = document.querySelectorAll('.heart-icon');

            icons.forEach(icon => {
                const teamId = icon.getAttribute('data-team-id');
                if (favorites.includes(teamId)) {
                    icon.classList.remove('fa-heart-o');
                    icon.classList.add('fa-heart');
                }
            });
        });
    </script>
}

Teams.cshtml.cs:

using FavoriteTeams.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;

namespace FavoriteTeams.Pages
{
    public class TeamsModel : PageModel
    {
        private readonly ApplicationDbContext _context;

        public TeamsModel(ApplicationDbContext context)
        {
            _context = context;
        }

        public IList<Team> Teams { get; set; }
        public IList<Division> Divisions { get; set; }

        public async Task OnGetAsync()
        {
            Teams = await _context.Teams.Include(t => t.Division).ToListAsync();
            Divisions = await _context.Divisions.ToListAsync();
        }


    }
}

Pages/FavoriteTeams.cshtml:

@page
@model FavoriteTeams.Pages.FavoriteTeamsModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@{
    Layout = "_Layout";
}


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Favorite Teams</title>
</head>
<body>
    <h1>Favorite Teams</h1>
    <div id="favoriteTeamsContainer"></div>
</body>
</html>

@section Scripts {
    <script type="text/javascript">
        document.addEventListener("DOMContentLoaded", () => {
            const favorites = JSON.parse(localStorage.getItem('favoriteTeams')) || [];
            console.log('Favorites from local storage:', favorites);

            const allTeams = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Teams));
            console.log('All Teams:', allTeams);

            // Log the structure of allTeams
            console.log('Structure of allTeams:', JSON.stringify(allTeams, null, 2));

            if (Array.isArray(allTeams)) {
                favorites.forEach(favoriteId => {
                    console.log('Processing favorite teamId:', favoriteId);
                    const team = allTeams.find(t => {
                        console.log('Checking team:', t);
                        console.log('Favorite Team ID:', favoriteId);
                        if (t && t.Id) {
                            console.log('Current Team ID:', t.Id);
                            const idsMatch = t.Id.toLowerCase() === favoriteId.toLowerCase();
                            console.log('IDs match:', idsMatch);
                            return idsMatch;
                        } else {
                            console.error('Team or Team ID is undefined:', t);
                            return false;
                        }
                    });
                    console.log('Found team:', team);
                    if (team) {
                        const teamElement = document.createElement('div');
                        teamElement.innerHTML = `
                                    <div>
                                        <img src="https://${team.Flag}" width="20" height="13">
                                        <a href="/Team_detail?varTeamId=${team.Id}">${team.Name}</a>
                                        <span>${team.Country}</span>
                                        <span>${team.Payment}</span>
                                    </div>
                                `;
                        console.log('Appending team element to container:', teamElement);
                        document.getElementById('favoriteTeamsContainer').appendChild(teamElement);
                    } else {
                        console.error('Team not found:', favoriteId);
                    }
                });
            } else {
                console.error('allTeams is not an array');
            }
        });
    </script>
}

FavoriteTeams.cshtml.cs:

using FavoriteTeams.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;

namespace FavoriteTeams.Pages
{
    public class FavoriteTeamsModel : PageModel
    {
        private readonly ApplicationDbContext _context;

        public List<Team> Teams { get; set; }

        public FavoriteTeamsModel(ApplicationDbContext context)
        {
            _context = context;
        }

        public void OnGet()
        {
            Teams = _context.Teams.Include(t => t.Division).ToList();
        }


    }
}

Program.cs:

using FavoriteTeams.Data;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

builder.Services.AddDbContext<ApplicationDbContext>(options =>
       options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddSession();


var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

SeedDatabase(app);


app.Run();
static void SeedDatabase(IApplicationBuilder app)
{
    using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        DbInitializer.Initialize(serviceScope.ServiceProvider);
    }
}

enter image description here

enter image description here

Upvotes: 0

Related Questions