diff --git a/MauiStoreApp.sln b/MauiStoreApp.sln
index 4bad6d9..9bf00c6 100644
--- a/MauiStoreApp.sln
+++ b/MauiStoreApp.sln
@@ -3,7 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34024.191
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiStoreApp", "MauiStoreApp\MauiStoreApp.csproj", "{9D34B1B5-C517-43AD-A59C-D57426129FD8}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiStoreApp", "MauiStoreApp\MauiStoreApp.csproj", "{9D34B1B5-C517-43AD-A59C-D57426129FD8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6982EDC3-5252-4F81-8E3F-485E4134D54B}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/MauiStoreApp/MauiStoreApp.csproj b/MauiStoreApp/MauiStoreApp.csproj
index 2c8cd6a..edfab50 100644
--- a/MauiStoreApp/MauiStoreApp.csproj
+++ b/MauiStoreApp/MauiStoreApp.csproj
@@ -80,11 +80,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/MauiStoreApp/Models/Address.cs b/MauiStoreApp/Models/Address.cs
index 0c171ba..1352e69 100644
--- a/MauiStoreApp/Models/Address.cs
+++ b/MauiStoreApp/Models/Address.cs
@@ -1,28 +1,61 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents an address.
+ ///
public class Address
{
+ ///
+ /// Gets or sets the geolocation of the address.
+ ///
[JsonPropertyName("geolocation")]
public Geolocation Geolocation { get; set; }
+ ///
+ /// Gets or sets the city of the address.
+ ///
[JsonPropertyName("city")]
public string City { get; set; }
+ ///
+ /// Gets or sets the street of the address.
+ ///
[JsonPropertyName("street")]
public string Street { get; set; }
+ ///
+ /// Gets or sets the number of the address.
+ ///
[JsonPropertyName("number")]
public int Number { get; set; }
+ ///
+ /// Gets or sets the zipcode of the address.
+ ///
[JsonPropertyName("zipcode")]
public string Zipcode { get; set; }
+ ///
+ /// Gets the city with the first letter capitalized.
+ ///
public string CityCapitalized => $"{City?.ToUpper()[0]}{City?.ToLower()[1..]}";
+ ///
+ /// Gets the city and zipcode concatenated.
+ ///
public string CityAndZipcode => $"{CityCapitalized} {Zipcode}";
+ ///
+ /// Gets the full street with the first letter capitalized followed by the street number.
+ ///
public string FullStreet => $"{Street?.ToUpper()[0]}{Street?.ToLower()[1..]} {Number}";
}
}
diff --git a/MauiStoreApp/Models/Cart.cs b/MauiStoreApp/Models/Cart.cs
index 7ca0013..e31242f 100644
--- a/MauiStoreApp/Models/Cart.cs
+++ b/MauiStoreApp/Models/Cart.cs
@@ -1,21 +1,45 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a shopping cart.
+ ///
public class Cart
{
+ ///
+ /// Gets or sets the unique identifier of the cart.
+ ///
[JsonPropertyName("id")]
public int Id { get; set; }
+ ///
+ /// Gets or sets the unique identifier of the user to whom the cart belongs.
+ ///
[JsonPropertyName("userId")]
public int UserId { get; set; }
+ ///
+ /// Gets or sets the date the cart was created or last updated.
+ ///
[JsonPropertyName("date")]
public DateTime Date { get; set; }
+ ///
+ /// Gets or sets the list of products in the cart.
+ ///
[JsonPropertyName("products")]
public List Products { get; set; }
+ ///
+ /// Gets or sets the version of the cart.
+ ///
[JsonPropertyName("__v")]
public int Version { get; set; }
}
diff --git a/MauiStoreApp/Models/CartItemDetail.cs b/MauiStoreApp/Models/CartItemDetail.cs
index 6d4b855..d4af477 100644
--- a/MauiStoreApp/Models/CartItemDetail.cs
+++ b/MauiStoreApp/Models/CartItemDetail.cs
@@ -1,12 +1,24 @@
-using System.ComponentModel;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.ComponentModel;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents the details of an item in the shopping cart, including the product and quantity.
+ ///
public class CartItemDetail : INotifyPropertyChanged
{
private Product _product;
private int _quantity;
+ ///
+ /// Gets or sets the product in the cart item.
+ ///
public Product Product
{
get => _product;
@@ -20,6 +32,9 @@ public Product Product
}
}
+ ///
+ /// Gets or sets the quantity of the product in the cart item.
+ ///
public int Quantity
{
get => _quantity;
@@ -33,8 +48,15 @@ public int Quantity
}
}
+ ///
+ /// Occurs when a property value changes.
+ ///
public event PropertyChangedEventHandler PropertyChanged;
+ ///
+ /// Raises the PropertyChanged event for the specified property.
+ ///
+ /// The name of the property that has changed.
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
diff --git a/MauiStoreApp/Models/CartProduct.cs b/MauiStoreApp/Models/CartProduct.cs
index c1003c4..c41446e 100644
--- a/MauiStoreApp/Models/CartProduct.cs
+++ b/MauiStoreApp/Models/CartProduct.cs
@@ -1,12 +1,27 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a product in the shopping cart, including the product ID and quantity.
+ ///
public class CartProduct
{
+ ///
+ /// Gets or sets the ID of the product.
+ ///
[JsonPropertyName("productId")]
public int ProductId { get; set; }
+ ///
+ /// Gets or sets the quantity of the product in the cart.
+ ///
[JsonPropertyName("quantity")]
public int Quantity { get; set; }
}
diff --git a/MauiStoreApp/Models/Category.cs b/MauiStoreApp/Models/Category.cs
index eae37ea..2fbab85 100644
--- a/MauiStoreApp/Models/Category.cs
+++ b/MauiStoreApp/Models/Category.cs
@@ -1,9 +1,24 @@
-namespace MauiStoreApp.Models
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a product category with a name and associated image.
+ ///
public class Category
{
+ ///
+ /// Gets or sets the name of the category.
+ ///
public string Name { get; set; }
+ ///
+ /// Gets the filename of the image associated with the category.
+ ///
public string ImageName
{
get
@@ -13,7 +28,7 @@ public string ImageName
return null;
}
- string formattedName = Name.Replace(" ", "_").Replace("'", "").ToLower();
+ string formattedName = Name.Replace(" ", "_").Replace("'", string.Empty).ToLower();
return formattedName + ".jpg";
}
}
diff --git a/MauiStoreApp/Models/Geolocation.cs b/MauiStoreApp/Models/Geolocation.cs
index 3f9c850..213a25c 100644
--- a/MauiStoreApp/Models/Geolocation.cs
+++ b/MauiStoreApp/Models/Geolocation.cs
@@ -1,12 +1,27 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a geographical location with latitude and longitude.
+ ///
public class Geolocation
{
+ ///
+ /// Gets or sets the latitude of the geographical location.
+ ///
[JsonPropertyName("lat")]
public string Lat { get; set; }
+ ///
+ /// Gets or sets the longitude of the geographical location.
+ ///
[JsonPropertyName("long")]
public string Long { get; set; }
}
diff --git a/MauiStoreApp/Models/LoginRequest.cs b/MauiStoreApp/Models/LoginRequest.cs
index 0bca834..34ca292 100644
--- a/MauiStoreApp/Models/LoginRequest.cs
+++ b/MauiStoreApp/Models/LoginRequest.cs
@@ -1,12 +1,27 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a request for user login with username and password.
+ ///
public class LoginRequest
- {
+ {
+ ///
+ /// Gets or sets the username for login.
+ ///
[JsonPropertyName("username")]
public string Username { get; set; }
+ ///
+ /// Gets or sets the password for login.
+ ///
[JsonPropertyName("password")]
public string Password { get; set; }
}
diff --git a/MauiStoreApp/Models/LoginResponse.cs b/MauiStoreApp/Models/LoginResponse.cs
index 8641924..5e3fd50 100644
--- a/MauiStoreApp/Models/LoginResponse.cs
+++ b/MauiStoreApp/Models/LoginResponse.cs
@@ -1,12 +1,28 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents the response from a login attempt, including an authentication token and user ID.
+ ///
public class LoginResponse
{
+ ///
+ /// Gets or sets the authentication token for the user.
+ ///
[JsonPropertyName("token")]
public string Token { get; set; }
+ ///
+ /// Gets or sets the user ID.
+ ///
+ [JsonPropertyName("userId")]
public int UserId { get; set; }
}
}
diff --git a/MauiStoreApp/Models/Name.cs b/MauiStoreApp/Models/Name.cs
index 01a03fc..bbd5ddf 100644
--- a/MauiStoreApp/Models/Name.cs
+++ b/MauiStoreApp/Models/Name.cs
@@ -1,12 +1,27 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a person's first and last name.
+ ///
public class Name
{
+ ///
+ /// Gets or sets the first name of the person.
+ ///
[JsonPropertyName("firstname")]
public string Firstname { get; set; }
+ ///
+ /// Gets or sets the last name of the person.
+ ///
[JsonPropertyName("lastname")]
public string Lastname { get; set; }
}
diff --git a/MauiStoreApp/Models/Product.cs b/MauiStoreApp/Models/Product.cs
index bbe7709..c36259b 100644
--- a/MauiStoreApp/Models/Product.cs
+++ b/MauiStoreApp/Models/Product.cs
@@ -1,27 +1,57 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a product with its details.
+ ///
public class Product
{
+ ///
+ /// Gets or sets the identifier of the product.
+ ///
[JsonPropertyName("id")]
public int Id { get; set; }
+ ///
+ /// Gets or sets the title of the product.
+ ///
[JsonPropertyName("title")]
public string Title { get; set; }
+ ///
+ /// Gets or sets the price of the product.
+ ///
[JsonPropertyName("price")]
public decimal Price { get; set; }
+ ///
+ /// Gets or sets the description of the product.
+ ///
[JsonPropertyName("description")]
public string Description { get; set; }
+ ///
+ /// Gets or sets the category of the product.
+ ///
[JsonPropertyName("category")]
public string Category { get; set; }
+ ///
+ /// Gets or sets the image URL of the product.
+ ///
[JsonPropertyName("image")]
public string Image { get; set; }
+ ///
+ /// Gets or sets the rating of the product.
+ ///
[JsonPropertyName("rating")]
public Rating Rating { get; set; }
}
diff --git a/MauiStoreApp/Models/Rating.cs b/MauiStoreApp/Models/Rating.cs
index b7eb1dc..8b8ac6c 100644
--- a/MauiStoreApp/Models/Rating.cs
+++ b/MauiStoreApp/Models/Rating.cs
@@ -1,12 +1,27 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents the rating of a product.
+ ///
public class Rating
{
+ ///
+ /// Gets or sets the rate value of the product.
+ ///
[JsonPropertyName("rate")]
public double Rate { get; set; }
+ ///
+ /// Gets or sets the number of ratings for the product.
+ ///
[JsonPropertyName("count")]
public int Count { get; set; }
}
diff --git a/MauiStoreApp/Models/User.cs b/MauiStoreApp/Models/User.cs
index be847ed..fb22acc 100644
--- a/MauiStoreApp/Models/User.cs
+++ b/MauiStoreApp/Models/User.cs
@@ -1,32 +1,68 @@
-using System.Text.Json.Serialization;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Text.Json.Serialization;
namespace MauiStoreApp.Models
{
+ ///
+ /// Represents a user.
+ ///
public class User
{
+ ///
+ /// Gets or sets the user's identifier.
+ ///
[JsonPropertyName("id")]
public int Id { get; set; }
+ ///
+ /// Gets or sets the user's email address.
+ ///
[JsonPropertyName("email")]
public string Email { get; set; }
+ ///
+ /// Gets or sets the user's username.
+ ///
[JsonPropertyName("username")]
public string Username { get; set; }
+ ///
+ /// Gets or sets the user's password.
+ ///
[JsonPropertyName("password")]
public string Password { get; set; }
+ ///
+ /// Gets or sets the user's name information.
+ ///
[JsonPropertyName("name")]
public Name Name { get; set; }
+ ///
+ /// Gets or sets the user's phone number.
+ ///
[JsonPropertyName("phone")]
public string Phone { get; set; }
+ ///
+ /// Gets or sets the user's address information.
+ ///
[JsonPropertyName("address")]
public Address Address { get; set; }
+ ///
+ /// Gets the user's full name.
+ ///
public string FullName => $"{Name?.Firstname?.ToUpper()[0]}{Name?.Firstname?.ToLower()[1..]} {Name?.Lastname?.ToUpper()[0]}{Name?.Lastname?.ToLower()[1..]}";
+ ///
+ /// Gets the initials of the user's name.
+ ///
public string AvatarInitials => $"{Name?.Firstname?.ToUpper()[0]}{Name?.Lastname?.ToUpper()[0]}";
}
}
diff --git a/MauiStoreApp/Services/AuthService.cs b/MauiStoreApp/Services/AuthService.cs
index f8851eb..91af726 100644
--- a/MauiStoreApp/Services/AuthService.cs
+++ b/MauiStoreApp/Services/AuthService.cs
@@ -1,15 +1,33 @@
-using MauiStoreApp.Models;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
using System.Text;
using System.Text.Json;
+using MauiStoreApp.Models;
namespace MauiStoreApp.Services
{
+ ///
+ /// This class is responsible for authenticating the user and storing the token and userId in secure storage.
+ ///
public class AuthService : BaseService
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public AuthService()
{
}
+ ///
+ /// Gets or sets a value indicating whether the user is logged in.
+ ///
+ ///
+ /// Checks if the token is stored in secure storage. If set to false, removes the token and userId from secure storage.
+ ///
public bool IsUserLoggedIn
{
get
@@ -29,12 +47,18 @@ public bool IsUserLoggedIn
}
}
+ ///
+ /// Logs the user in.
+ ///
+ /// The username of the user.
+ /// The password of the user.
+ /// A task of type .
public async Task LoginAsync(string username, string password)
{
var request = new LoginRequest
{
Username = username,
- Password = password
+ Password = password,
};
var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
diff --git a/MauiStoreApp/Services/BaseService.cs b/MauiStoreApp/Services/BaseService.cs
index eef30ab..fcc9fcf 100644
--- a/MauiStoreApp/Services/BaseService.cs
+++ b/MauiStoreApp/Services/BaseService.cs
@@ -1,11 +1,26 @@
-using System.Diagnostics;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Diagnostics;
namespace MauiStoreApp.Services
{
+ ///
+ /// This class provides base functionality for other service classes.
+ ///
public class BaseService
{
+ ///
+ /// An instance of .
+ ///
protected readonly HttpClient _httpClient;
+ ///
+ /// Initializes a new instance of the class.
+ ///
public BaseService()
{
_httpClient = new HttpClient
@@ -14,6 +29,12 @@ public BaseService()
};
}
+ ///
+ /// Sends a GET request to the specified endpoint and returns the response as an instance of type .
+ ///
+ /// The type of the response object.
+ /// The endpoint to send the GET request to.
+ /// A task of type .
protected async Task GetAsync(string endpoint)
{
if (!IsInternetAvailable())
@@ -38,6 +59,11 @@ protected async Task GetAsync(string endpoint)
}
}
+ ///
+ /// Sends a DELETE request to the specified endpoint and returns the response.
+ ///
+ /// The endpoint to send the DELETE request to.
+ /// A task of type .
protected async Task DeleteAsync(string endpoint)
{
if (!IsInternetAvailable())
@@ -57,6 +83,10 @@ protected async Task DeleteAsync(string endpoint)
}
}
+ ///
+ /// Checks if an internet connection is available.
+ ///
+ /// true if an internet connection is available; otherwise, false.
private bool IsInternetAvailable()
{
NetworkAccess accessType = Connectivity.NetworkAccess;
@@ -66,10 +96,15 @@ private bool IsInternetAvailable()
if (Shell.Current != null)
{
if (accessType == NetworkAccess.ConstrainedInternet)
+ {
Shell.Current.DisplayAlert("Greška!", "Internet veza je ograničena.", "U redu");
+ }
else
+ {
Shell.Current.DisplayAlert("Greška!", "Internet veza nije dostupna.", "U redu");
+ }
}
+
return false;
}
diff --git a/MauiStoreApp/Services/CartService.cs b/MauiStoreApp/Services/CartService.cs
index 6d63302..7c3a18b 100644
--- a/MauiStoreApp/Services/CartService.cs
+++ b/MauiStoreApp/Services/CartService.cs
@@ -1,16 +1,29 @@
-using MauiStoreApp.Models;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using MauiStoreApp.Models;
namespace MauiStoreApp.Services
{
+ ///
+ /// Provides services for managing the shopping cart.
+ ///
public class CartService : BaseService
{
private readonly ProductService _productService;
private List _cartItems = new List(); // Internal cart items collection
private int? cartId = null;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The product service to use for retrieving product details.
public CartService(ProductService productService)
{
- _productService = productService;
+ _productService = productService ?? throw new ArgumentNullException(nameof(productService));
}
///
@@ -54,7 +67,7 @@ public async Task RefreshCartItemsByUserIdAsync(int userId)
_cartItems.Add(new CartItemDetail
{
Product = productDetails,
- Quantity = cartProduct.Quantity
+ Quantity = cartProduct.Quantity,
});
}
}
diff --git a/MauiStoreApp/Services/CategoryService.cs b/MauiStoreApp/Services/CategoryService.cs
index b374d35..fc7213a 100644
--- a/MauiStoreApp/Services/CategoryService.cs
+++ b/MauiStoreApp/Services/CategoryService.cs
@@ -1,14 +1,30 @@
-using MauiStoreApp.Models;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using MauiStoreApp.Models;
namespace MauiStoreApp.Services
{
+ ///
+ /// Provides services for managing and retrieving product categories.
+ ///
public class CategoryService : BaseService
{
+ ///
+ /// Asynchronously retrieves a collection of all available product categories.
+ ///
+ ///
+ /// A task that represents the asynchronous operation.
+ /// The task result contains an enumerable collection of objects.
+ ///
public async Task> GetCategoriesAsync()
{
var categories = await GetAsync>("products/categories");
- // Mapping each string to a Category object
+ // Maps each category name to a Category object.
var categoryList = new List();
foreach (var category in categories)
{
diff --git a/MauiStoreApp/Services/ProductService.cs b/MauiStoreApp/Services/ProductService.cs
index ba03934..d6bde1b 100644
--- a/MauiStoreApp/Services/ProductService.cs
+++ b/MauiStoreApp/Services/ProductService.cs
@@ -1,19 +1,53 @@
-using MauiStoreApp.Models;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using MauiStoreApp.Models;
namespace MauiStoreApp.Services
{
+ ///
+ /// Provides services for managing and retrieving products.
+ ///
public class ProductService : BaseService
{
+ ///
+ /// Asynchronously retrieves a collection of all available products, optionally sorted in a specific order.
+ ///
+ /// The order in which the products should be sorted. Defaults to "asc" for ascending.
+ ///
+ /// A task that represents the asynchronous operation.
+ /// The task result contains an enumerable collection of objects.
+ ///
public async Task> GetProductsAsync(string sortOrder = "asc")
{
return await GetAsync>($"products?sort={sortOrder}");
}
+ ///
+ /// Asynchronously retrieves a product by its ID.
+ ///
+ /// The ID of the product to retrieve.
+ ///
+ /// A task that represents the asynchronous operation.
+ /// The task result contains the object with the specified ID.
+ ///
public async Task GetProductByIdAsync(int id)
{
return await GetAsync($"products/{id}");
}
+ ///
+ /// Asynchronously retrieves a collection of products belonging to a specific category, optionally sorted in a specific order.
+ ///
+ /// The category of the products to retrieve.
+ /// The order in which the products should be sorted. Defaults to "asc" for ascending.
+ ///
+ /// A task that represents the asynchronous operation.
+ /// The task result contains an enumerable collection of objects belonging to the specified category.
+ ///
public async Task> GetProductsByCategoryAsync(string category, string sortOrder = "asc")
{
return await GetAsync>($"products/category/{category}?sort={sortOrder}");
diff --git a/MauiStoreApp/Services/RecentlyViewedProductsService.cs b/MauiStoreApp/Services/RecentlyViewedProductsService.cs
index a6c5017..98ee60a 100644
--- a/MauiStoreApp/Services/RecentlyViewedProductsService.cs
+++ b/MauiStoreApp/Services/RecentlyViewedProductsService.cs
@@ -1,19 +1,41 @@
-using CommunityToolkit.Mvvm.ComponentModel;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
using MauiStoreApp.Models;
using Newtonsoft.Json;
-using System.Collections.ObjectModel;
namespace MauiStoreApp.Services
{
- public partial class RecentlyViewedProductsService: ObservableObject
+ ///
+ /// Manages and persists the list of recently viewed products.
+ ///
+ public partial class RecentlyViewedProductsService : ObservableObject
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public RecentlyViewedProductsService()
{
}
+ ///
+ /// Gets or sets the list of recently viewed products.
+ ///
[ObservableProperty]
private Collection recentlyViewedProducts = new();
+ ///
+ /// Adds a product to the list of recently viewed products.
+ /// If the product already exists in the list, it is moved to the front.
+ /// The list is capped at 8 products, and older products are removed.
+ /// The list is then saved to persistent storage.
+ ///
+ /// The product to add.
public void AddProduct(Product product)
{
var existingProduct = RecentlyViewedProducts.FirstOrDefault(p => p.Id == product.Id);
@@ -32,6 +54,9 @@ public void AddProduct(Product product)
SaveProducts();
}
+ ///
+ /// Loads the list of recently viewed products from persistent storage.
+ ///
public void LoadProducts()
{
var productsJson = Preferences.Get("recently_viewed", string.Empty);
@@ -42,6 +67,9 @@ public void LoadProducts()
}
}
+ ///
+ /// Saves the list of recently viewed products to persistent storage.
+ ///
public void SaveProducts()
{
var productsJson = JsonConvert.SerializeObject(RecentlyViewedProducts);
diff --git a/MauiStoreApp/Services/UserService.cs b/MauiStoreApp/Services/UserService.cs
index 3f17825..c47244e 100644
--- a/MauiStoreApp/Services/UserService.cs
+++ b/MauiStoreApp/Services/UserService.cs
@@ -1,21 +1,44 @@
-using MauiStoreApp.Models;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using MauiStoreApp.Models;
namespace MauiStoreApp.Services
{
+ ///
+ /// Provides methods to interact with user data.
+ ///
public class UserService : BaseService
{
private readonly AuthService _authService;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An instance of the class used for authentication operations.
public UserService(AuthService authService)
{
_authService = authService;
}
+ ///
+ /// Retrieves user information by user ID.
+ ///
+ /// The ID of the user to retrieve information for.
+ /// A object representing the user's information.
public async Task GetUserAsync(int userId)
{
return await GetAsync($"users/{userId}");
}
+ ///
+ /// Deletes a user account by user ID.
+ ///
+ /// The ID of the user whose account is to be deleted.
+ /// A boolean value indicating whether the account deletion was successful.
public async Task DeleteUserAccountAsync(int userId)
{
var response = await DeleteAsync($"users/{userId}");
diff --git a/MauiStoreApp/ViewModels/BaseViewModel.cs b/MauiStoreApp/ViewModels/BaseViewModel.cs
index 6a7ae1b..84cb032 100644
--- a/MauiStoreApp/ViewModels/BaseViewModel.cs
+++ b/MauiStoreApp/ViewModels/BaseViewModel.cs
@@ -1,24 +1,47 @@
-using CommunityToolkit.Mvvm.ComponentModel;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// Provides a base implementation for view models.
+ ///
public partial class BaseViewModel : ObservableObject
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public BaseViewModel()
{
}
private bool _isBusy;
+
+ ///
+ /// Gets or sets a value indicating whether the view model is busy performing an operation.
+ ///
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
+ ///
+ /// Gets or sets the title of the page.
+ ///
[ObservableProperty]
string title;
+ ///
+ /// Navigates back to the previous page in the navigation stack.
+ ///
+ /// A task that represents the asynchronous operation.
[RelayCommand]
public async Task GoBack()
{
@@ -36,4 +59,4 @@ private async Task GoToRoute(string pageName)
await Shell.Current.GoToAsync($"//{pageName}");
}
}
-}
\ No newline at end of file
+}
diff --git a/MauiStoreApp/ViewModels/CartViewModel.cs b/MauiStoreApp/ViewModels/CartViewModel.cs
index bce9dbb..019e227 100644
--- a/MauiStoreApp/ViewModels/CartViewModel.cs
+++ b/MauiStoreApp/ViewModels/CartViewModel.cs
@@ -1,13 +1,21 @@
-
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Collections.ObjectModel;
+using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiStoreApp.Models;
using MauiStoreApp.Services;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// Represents the view model for the cart page.
+ ///
public partial class CartViewModel : BaseViewModel
{
private readonly CartService _cartService;
@@ -15,26 +23,46 @@ public partial class CartViewModel : BaseViewModel
bool isFirstRun;
- public CartViewModel(CartService cartService, ProductService productService, AuthService authService)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An instance of the class used for cart operations.
+ /// An instance of the class used for authentication operations.
+ public CartViewModel(CartService cartService, AuthService authService)
{
_cartService = cartService;
_authService = authService;
isFirstRun = true;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
public CartViewModel()
{
}
+ ///
+ /// Gets or sets a value indicating whether the user is logged in.
+ ///
[ObservableProperty]
public bool isUserLoggedIn;
-
+ ///
+ /// Gets or sets a value indicating whether the view model is busy with cart modification.
+ ///
[ObservableProperty]
private bool isBusyWithCartModification;
+ ///
+ /// Gets the cart items.
+ ///
public ObservableCollection CartItems { get; private set; } = new ObservableCollection();
+ ///
+ /// Initializes the cart view model.
+ ///
+ /// A representing the asynchronous operation.
[RelayCommand]
public async Task Init()
{
@@ -45,7 +73,7 @@ public async Task Init()
}
else
{
- this.SyncCartItems();
+ this.SyncCartItems();
}
IsUserLoggedIn = _authService.IsUserLoggedIn;
}
@@ -55,7 +83,9 @@ private async Task GetCartByUserIdAsync()
if (_authService.IsUserLoggedIn)
{
if (IsBusy)
+ {
return;
+ }
int userId;
var userIdStr = await SecureStorage.GetAsync("userId");
@@ -89,33 +119,41 @@ private async Task GetCartByUserIdAsync()
}
}
+ ///
+ /// Navigates to the login page.
+ ///
+ /// A task that represents the asynchronous operation.
[RelayCommand]
public async Task GoToLoginPage()
{
await Shell.Current.GoToAsync("LoginPage");
}
+ ///
+ /// Deletes the cart.
+ ///
+ /// A task that represents the asynchronous operation.
[RelayCommand]
public async Task DeleteCart()
{
if (IsBusy || IsBusyWithCartModification)
+ {
return;
+ }
try
{
- // Ask the user for confirmation
var userResponse = await Shell.Current.DisplayAlert("Potvrda", "Jeste li sigurni da želite obrisati košaricu?", "Da", "Ne");
if (!userResponse)
{
Debug.WriteLine("Cart deletion cancelled by the user.");
- return; // exit if the user cancels the deletion
+ return;
}
if (CartItems.Count > 0)
{
IsBusyWithCartModification = true;
- // Delete the cart
var response = await _cartService.DeleteCartAsync();
if (response != null && response.IsSuccessStatusCode)
@@ -147,14 +185,16 @@ public async Task DeleteCart()
}
}
+ ///
+ /// Increases the quantity of the specified product in the cart.
+ ///
+ /// The product whose quantity to increase.
[RelayCommand]
public void IncreaseProductQuantity(Product product)
{
try
{
_cartService.IncreaseProductQuantity(product.Id);
-
- // Refresh the cart item in the ViewModel
SyncCartItems();
}
catch (Exception ex)
@@ -164,14 +204,16 @@ public void IncreaseProductQuantity(Product product)
}
}
+ ///
+ /// Decreases the quantity of the specified product in the cart.
+ ///
+ /// The product whose quantity to decrease.
[RelayCommand]
public void DecreaseProductQuantity(Product product)
{
try
{
_cartService.DecreaseProductQuantity(product.Id);
-
- // Refresh the cart items in the ViewModel
SyncCartItems();
}
catch (Exception ex)
@@ -184,8 +226,6 @@ public void DecreaseProductQuantity(Product product)
private void SyncCartItems()
{
var updatedCartItems = _cartService.GetCartItems();
-
- // Remove items not in the updated list
foreach (var item in CartItems.ToList())
{
if (!updatedCartItems.Any(ci => ci.Product.Id == item.Product.Id))
@@ -194,7 +234,6 @@ private void SyncCartItems()
}
}
- // Add or update items
foreach (var updatedItem in updatedCartItems)
{
var existingItem = CartItems.FirstOrDefault(ci => ci.Product.Id == updatedItem.Product.Id);
@@ -204,7 +243,7 @@ private void SyncCartItems()
}
else
{
- existingItem.Quantity = updatedItem.Quantity; // Assuming Quantity property notifies changes
+ existingItem.Quantity = updatedItem.Quantity;
}
}
}
diff --git a/MauiStoreApp/ViewModels/CategoryPageViewModel.cs b/MauiStoreApp/ViewModels/CategoryPageViewModel.cs
index c29add4..dbd5389 100644
--- a/MauiStoreApp/ViewModels/CategoryPageViewModel.cs
+++ b/MauiStoreApp/ViewModels/CategoryPageViewModel.cs
@@ -1,48 +1,82 @@
-
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Collections.ObjectModel;
+using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiStoreApp.Models;
using MauiStoreApp.Services;
using MauiStoreApp.Views;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// Represents the view model for the category page.
+ ///
[QueryProperty(nameof(Category), "Category")]
public partial class CategoryPageViewModel : BaseViewModel
{
-
private readonly ProductService _productService;
private readonly RecentlyViewedProductsService _recentlyViewedProductsService;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The product service.
+ /// The recently viewed products service.
public CategoryPageViewModel(ProductService productService, RecentlyViewedProductsService recentlyViewedProductsService)
{
_productService = productService;
_recentlyViewedProductsService = recentlyViewedProductsService;
}
+ ///
+ /// Gets or sets the category.
+ ///
[ObservableProperty]
Category category;
+ ///
+ /// Gets or sets the sort order.
+ ///
[ObservableProperty]
string sortOrder = "asc";
+ ///
+ /// Gets or sets a value indicating whether the view model is busy with sorting.
+ ///
[ObservableProperty]
bool isBusyWithSorting = false;
+ ///
+ /// Gets the products.
+ ///
public ObservableCollection Products { get; private set; } = new ObservableCollection();
+ ///
+ /// Initializes the category page view model.
+ ///
+ /// A representing the asynchronous operation.
[RelayCommand]
public async Task Init()
{
await GetProductsByCategoryAsync();
}
+ ///
+ /// Gets the products by category.
+ ///
+ /// The sort order. Can be "asc" or "desc". Defaults to "asc".
private async Task GetProductsByCategoryAsync(string sortOrder = "asc")
{
if (IsBusy)
+ {
return;
+ }
try
{
@@ -66,18 +100,23 @@ private async Task GetProductsByCategoryAsync(string sortOrder = "asc")
}
}
-
+ ///
+ /// Handles the product tapped event.
+ ///
+ /// The tapped product.
[RelayCommand]
private async Task ProductTapped(Product product)
{
IsBusy = true;
if (product == null)
+ {
return;
+ }
var navigationParameter = new Dictionary
{
- { "Product", product }
+ { "Product", product },
};
_recentlyViewedProductsService.AddProduct(product);
@@ -87,11 +126,16 @@ private async Task ProductTapped(Product product)
IsBusy = false;
}
+ ///
+ /// Sorts the products.
+ ///
[RelayCommand]
private async Task SortProducts()
{
if (IsBusyWithSorting)
+ {
return;
+ }
IsBusyWithSorting = true;
diff --git a/MauiStoreApp/ViewModels/HomePageViewModel.cs b/MauiStoreApp/ViewModels/HomePageViewModel.cs
index e8bf112..374feb8 100644
--- a/MauiStoreApp/ViewModels/HomePageViewModel.cs
+++ b/MauiStoreApp/ViewModels/HomePageViewModel.cs
@@ -1,23 +1,45 @@
-using MauiStoreApp.Models;
-using MauiStoreApp.Services;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
using System.Collections.ObjectModel;
using System.Diagnostics;
using CommunityToolkit.Mvvm.Input;
+using MauiStoreApp.Models;
+using MauiStoreApp.Services;
using MauiStoreApp.Views;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// Represents the view model for the home page.
+ ///
public partial class HomePageViewModel : BaseViewModel
{
private readonly ProductService _productService;
private readonly CategoryService _categoryService;
private readonly RecentlyViewedProductsService _recentlyViewedProductsService;
+ ///
+ /// Gets the products.
+ ///
public ObservableCollection Products { get; } = new ObservableCollection();
+
+ ///
+ /// Gets the categories.
+ ///
public ObservableCollection Categories { get; } = new ObservableCollection();
- bool isFirstRun;
+ private bool isFirstRun;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The product service.
+ /// The category service.
+ /// The recently viewed products service.
public HomePageViewModel(ProductService productService, CategoryService categoryService, RecentlyViewedProductsService recentlyViewedProductsService)
{
_productService = productService;
@@ -26,10 +48,17 @@ public HomePageViewModel(ProductService productService, CategoryService category
isFirstRun = true;
}
+ ///
+ /// Initializes a new instance of the class. This empty constructor is used for design-time data.
+ ///
public HomePageViewModel()
{
}
+ ///
+ /// Initializes the home page view model.
+ ///
+ /// A representing the asynchronous operation.
[RelayCommand]
public async Task Init()
{
@@ -42,6 +71,9 @@ public async Task Init()
}
}
+ ///
+ /// Gets the categories.
+ ///
private async Task GetCategoriesAsync()
{
var categories = await _categoryService.GetCategoriesAsync();
@@ -51,10 +83,15 @@ private async Task GetCategoriesAsync()
}
}
+ ///
+ /// Gets the products.
+ ///
private async Task GetProductsAsync()
{
if (IsBusy)
+ {
return;
+ }
try
{
@@ -78,15 +115,21 @@ private async Task GetProductsAsync()
}
}
+ ///
+ /// Handles the product tapped event.
+ ///
+ /// The tapped product.
[RelayCommand]
private async Task ProductTapped(Product product)
{
if (product == null)
+ {
return;
+ }
var navigationParameter = new Dictionary
{
- { "Product", product }
+ { "Product", product },
};
_recentlyViewedProductsService.AddProduct(product);
@@ -94,15 +137,21 @@ private async Task ProductTapped(Product product)
await Shell.Current.GoToAsync($"{nameof(ProductDetailsPage)}", true, navigationParameter);
}
+ ///
+ /// Handles the category tapped event.
+ ///
+ /// The tapped category.
[RelayCommand]
private async Task CategoryTapped(Category category)
{
if (category == null)
+ {
return;
+ }
var navigationParameter = new Dictionary
{
- { "Category", category }
+ { "Category", category },
};
await Shell.Current.GoToAsync($"{nameof(CategoryPage)}", true, navigationParameter);
diff --git a/MauiStoreApp/ViewModels/LoginViewModel.cs b/MauiStoreApp/ViewModels/LoginViewModel.cs
index 26ce17f..ed39d66 100644
--- a/MauiStoreApp/ViewModels/LoginViewModel.cs
+++ b/MauiStoreApp/ViewModels/LoginViewModel.cs
@@ -1,33 +1,51 @@
-
+using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiStoreApp.Models;
using MauiStoreApp.Services;
-using System.Diagnostics;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// The view model for the login page.
+ ///
public partial class LoginViewModel : BaseViewModel
{
private readonly AuthService _authService;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The authentication service.
public LoginViewModel(AuthService authService)
{
_authService = authService;
}
+ ///
+ /// Initializes a new instance of the class. This empty constructor is used for design-time data.
+ ///
public LoginViewModel()
{
}
+ ///
+ /// Gets or sets the username.
+ ///
[ObservableProperty]
string username;
+ ///
+ /// Gets or sets the password.
+ ///
[ObservableProperty]
string password;
- LoginResponse loginResponse = new LoginResponse();
+ private LoginResponse loginResponse = new LoginResponse();
+ ///
+ /// Attempts to log in the user.
+ ///
[RelayCommand]
public async Task Login()
{
@@ -45,6 +63,7 @@ public async Task Login()
// save token to secure storage
await SecureStorage.Default.SetAsync("token", loginResponse.Token);
+
// save user id to secure storage
await SecureStorage.Default.SetAsync("userId", loginResponse.UserId.ToString());
diff --git a/MauiStoreApp/ViewModels/ProductDetailsViewModel.cs b/MauiStoreApp/ViewModels/ProductDetailsViewModel.cs
index cb7243b..d376be6 100644
--- a/MauiStoreApp/ViewModels/ProductDetailsViewModel.cs
+++ b/MauiStoreApp/ViewModels/ProductDetailsViewModel.cs
@@ -1,22 +1,35 @@
-
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Collections.ObjectModel;
+using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiStoreApp.Models;
using MauiStoreApp.Services;
using MauiStoreApp.Views;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// Represents the view model for the product details page.
+ ///
[QueryProperty(nameof(Product), "Product")]
public partial class ProductDetailsViewModel : BaseViewModel
{
-
private readonly ProductService _productService;
private readonly CartService _cartService;
private readonly RecentlyViewedProductsService _recentlyViewedProductsService;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The product service.
+ /// The cart service.
+ /// The recently viewed products service.
public ProductDetailsViewModel(ProductService productService, CartService cartService, RecentlyViewedProductsService recentlyViewedProductsService)
{
_productService = productService;
@@ -24,18 +37,31 @@ public ProductDetailsViewModel(ProductService productService, CartService cartSe
_recentlyViewedProductsService = recentlyViewedProductsService;
}
+ ///
+ /// Initializes a new instance of the class. This empty constructor is used for design-time data.
+ ///
public ProductDetailsViewModel()
{
- }
+ }
+ ///
+ /// Gets or sets the current product.
+ ///
[ObservableProperty]
Product product;
+ ///
+ /// Gets the cross-sell products.
+ ///
public ObservableCollection CrossSellProducts { get; private set; } = new ObservableCollection();
+ ///
+ /// Initializes the view model.
+ ///
+ /// A representing the asynchronous operation.
[RelayCommand]
public async Task Init()
- {
+ {
await GetProductByIdAsync();
await GetCrossSellProductsAsync();
}
@@ -55,7 +81,7 @@ private async Task GetProductByIdAsync()
catch (Exception ex)
{
Debug.WriteLine($"Unable to get product: {ex.Message}");
- await Shell.Current.DisplayAlert("Error!", ex.Message, "OK");
+ await Shell.Current.DisplayAlert("Došlo je do pogreške!", ex.Message, "U redu");
}
finally
{
@@ -66,7 +92,9 @@ private async Task GetProductByIdAsync()
private async Task GetCrossSellProductsAsync()
{
if (IsBusy || Product == null)
+ {
return;
+ }
try
{
@@ -84,7 +112,7 @@ private async Task GetCrossSellProductsAsync()
catch (Exception ex)
{
Debug.WriteLine($"Unable to get cross-sell products: {ex.Message}");
- await Shell.Current.DisplayAlert("Error!", ex.Message, "OK");
+ await Shell.Current.DisplayAlert("Došlo je do pogreške!", ex.Message, "U redu");
}
finally
{
@@ -92,17 +120,23 @@ private async Task GetCrossSellProductsAsync()
}
}
+ ///
+ /// Handles the product tapped event.
+ ///
+ /// The tapped product.
[RelayCommand]
private async Task ProductTapped(Product product)
{
IsBusy = true;
if (product == null)
+ {
return;
+ }
var navigationParameter = new Dictionary
{
- { "Product", product }
+ { "Product", product },
};
_recentlyViewedProductsService.AddProduct(product);
@@ -112,6 +146,10 @@ private async Task ProductTapped(Product product)
IsBusy = false;
}
+ ///
+ /// Shares the product.
+ ///
+ /// The product to share.
[RelayCommand]
private async Task ShareProduct(Product product)
{
@@ -122,20 +160,28 @@ private async Task ShareProduct(Product product)
{
Uri = product.Image,
Title = product.Title,
- Text = "Pogledaj ovaj proizod na AStore!"
+ Text = "Pogledaj ovaj proizvod na AStore!",
});
}
+ ///
+ /// Adds the product to the cart.
+ ///
+ /// The product to add to the cart.
[RelayCommand]
private async Task AddToCart(Product product)
{
if (IsBusy)
+ {
return;
+ }
try
{
if (product == null)
+ {
return;
+ }
_cartService.AddProductToCart(product);
diff --git a/MauiStoreApp/ViewModels/ProfilePageViewModel.cs b/MauiStoreApp/ViewModels/ProfilePageViewModel.cs
index bbb8700..cb03983 100644
--- a/MauiStoreApp/ViewModels/ProfilePageViewModel.cs
+++ b/MauiStoreApp/ViewModels/ProfilePageViewModel.cs
@@ -1,34 +1,60 @@
-
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiStoreApp.Models;
using MauiStoreApp.Services;
using MauiStoreApp.Views;
-using System.Diagnostics;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// Represents the view model for the profile page.
+ ///
public partial class ProfilePageViewModel : BaseViewModel
{
private readonly UserService _userService;
private readonly AuthService _authService;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The user service.
+ /// The authentication service.
public ProfilePageViewModel(UserService userService, AuthService authService)
{
_userService = userService;
_authService = authService;
}
+ ///
+ /// Initializes a new instance of the class. This empty constructor is used for design-time data.
+ ///
public ProfilePageViewModel()
{
}
+ ///
+ /// Gets or sets a value indicating whether the user is logged in.
+ ///
[ObservableProperty]
public bool isUserLoggedIn;
+ ///
+ /// Gets or sets the user.
+ ///
[ObservableProperty]
User user;
+ ///
+ /// Initializes the view model.
+ ///
+ /// A representing the asynchronous operation.
[RelayCommand]
public async Task Init()
{
@@ -39,18 +65,20 @@ public async Task Init()
private async Task GetUserByIdAsync()
{
if (IsBusy)
+ {
return;
+ }
try
{
IsBusy = true;
- // read id from secure storage
+ // Read id from secure storage
var userId = await SecureStorage.Default.GetAsync("userId");
if (userId == null)
{
- Debug.WriteLine("User id not found in secure storage.");
+ Debug.WriteLine("User id not found in secure storage.");
return;
}
else
@@ -74,33 +102,45 @@ private async Task GetUserByIdAsync()
}
}
+ ///
+ /// Logs the user out.
+ ///
[RelayCommand]
private async Task Logout()
{
- // fire alert
- var result = await Shell.Current.DisplayAlert("Odjava", "Jeste li sigurni da se želite odjaviti?", "Da", "Ne");
+ // fire alert
+ var result = await Shell.Current.DisplayAlert("Odjava", "Jeste li sigurni da se želite odjaviti?", "Da", "Ne");
if (result)
{
_authService.IsUserLoggedIn = false;
- // navigate to home page
+ // Navigate to home page
await Shell.Current.GoToAsync("//HomePage");
}
}
+ ///
+ /// Navigates to the login page.
+ ///
[RelayCommand]
private async Task Login()
{
await Shell.Current.GoToAsync($"{nameof(LoginPage)}");
}
+ ///
+ /// Opens the FakeStoreAPI website in a browser.
+ ///
[RelayCommand]
private static async Task OpenFakeStoreApi()
{
await Browser.OpenAsync("https://fakestoreapi.com/");
}
+ ///
+ /// Deletes the user account.
+ ///
[RelayCommand]
private async Task DeleteAccount()
{
@@ -109,7 +149,7 @@ private async Task DeleteAccount()
if (result)
{
- // read id from secure storage
+ // Read id from secure storage
var userId = await SecureStorage.Default.GetAsync("userId");
if (userId == null)
@@ -125,7 +165,7 @@ private async Task DeleteAccount()
{
await Shell.Current.DisplayAlert("Obavijest", "Račun je uspješno izbrisan.", "U redu");
- // navigate to home page
+ // Navigate to home page
await Shell.Current.GoToAsync("//HomePage");
}
else
diff --git a/MauiStoreApp/ViewModels/RecentlyViewedPageViewModel.cs b/MauiStoreApp/ViewModels/RecentlyViewedPageViewModel.cs
index 8df393f..055c978 100644
--- a/MauiStoreApp/ViewModels/RecentlyViewedPageViewModel.cs
+++ b/MauiStoreApp/ViewModels/RecentlyViewedPageViewModel.cs
@@ -1,25 +1,48 @@
-using CommunityToolkit.Mvvm.ComponentModel;
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Kvesic, Matkovic, FSRE. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiStoreApp.Models;
-using MauiStoreApp.Views;
using MauiStoreApp.Services;
+using MauiStoreApp.Views;
namespace MauiStoreApp.ViewModels
{
+ ///
+ /// Represents the view model for the recently viewed products page.
+ ///
public partial class RecentlyViewedPageViewModel : BaseViewModel
{
+ ///
+ /// Gets or sets the recently viewed products service.
+ ///
[ObservableProperty]
public RecentlyViewedProductsService recentlyViewedProductsService;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The recently viewed products service.
public RecentlyViewedPageViewModel(RecentlyViewedProductsService recentlyViewedProductsService)
{
RecentlyViewedProductsService = recentlyViewedProductsService;
}
+ ///
+ /// Initializes a new instance of the class. This empty constructor is used for design-time data.
+ ///
public RecentlyViewedPageViewModel()
{
}
+ ///
+ /// Initializes the view model.
+ ///
+ /// A representing the asynchronous operation.
[RelayCommand]
public async Task Init()
{
@@ -28,17 +51,23 @@ public async Task Init()
await Task.CompletedTask;
}
+ ///
+ /// Handles the product tapped event.
+ ///
+ /// The tapped product.
[RelayCommand]
private async Task ProductTapped(Product product)
{
IsBusy = true;
if (product == null)
+ {
return;
+ }
var navigationParameter = new Dictionary
{
- { "Product", product }
+ { "Product", product },
};
await Shell.Current.GoToAsync($"{nameof(ProductDetailsPage)}", true, navigationParameter);
@@ -46,12 +75,18 @@ private async Task ProductTapped(Product product)
IsBusy = false;
}
+ ///
+ /// Navigates to the home page.
+ ///
[RelayCommand]
private async Task GoToHome()
{
await Shell.Current.GoToAsync($"//{nameof(HomePage)}");
}
+ ///
+ /// Deletes all recently viewed products.
+ ///
[RelayCommand]
private async Task DeleteAll()
{
@@ -59,7 +94,9 @@ private async Task DeleteAll()
var result = await Shell.Current.DisplayAlert("Brisanje", "Sigurno želite izbrisati sve nedavno gledane proizvode?", "Da", "Ne");
if (!result)
- return; // exit if user cancels
+ {
+ return; // Exit if user cancels
+ }
RecentlyViewedProductsService.RecentlyViewedProducts.Clear();
RecentlyViewedProductsService.SaveProducts();
diff --git a/MauiStoreApp/stylecop.json b/MauiStoreApp/stylecop.json
new file mode 100644
index 0000000..495e3eb
--- /dev/null
+++ b/MauiStoreApp/stylecop.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "documentationRules": {
+ "companyName": "Kvesic, Matkovic, FSRE",
+ "copyrightText": "Copyright (c) {companyName}. All rights reserved.",
+ "headerDecoration": "-----------------------------------------------------------------------"
+ },
+ "orderingRules": {
+ "systemUsingDirectivesFirst": true,
+ "usingDirectivesPlacement": "outsideNamespace",
+ "elementOrder": [
+ "kind",
+ "constant",
+ "static",
+ "readonly"
+ ]
+ }
+ }
+}
\ No newline at end of file