Compare commits

..

No commits in common. 'master' and 'homepage-05-09' have entirely different histories.

@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LibraryDTO\LibraryDTO.csproj" />
</ItemGroup>
</Project>

@ -1,102 +0,0 @@
using LibraryDTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DtoAbstractLayer
{
/// <summary>
/// abstract layer for requests on Books Library
/// </summary>
public interface IDtoManager
{
/// <summary>
/// get a book by specifying its id
/// </summary>
/// <param name="id">id of the Book to get</param>
/// <returns>a Book with this id (or null if id is unknown)</returns>
Task<BookDTO> GetBookById(string id);
/// <summary>
/// get a book by specifying its isbn
/// </summary>
/// <param name="isbn">isbn of the Book to get</param>
/// <returns>a Book with this isbn (or null if isbn is unknown)</returns>
Task<BookDTO> GetBookByISBN(string isbn);
/// <summary>
/// get books containing a substring in their titles
/// </summary>
/// <param name="title">the substring to look for in book titles</param>
/// <param name="index">index of the page of resulting books</param>
/// <param name="count">number of resulting books per page</param>
/// <param name="sort">sort criterium (not mandatory):
/// <ul>
/// <li>```title```: sort books by titles in alphabetical order,</li>
/// <li>```title_reverse```: sort books by titles in reverse alphabetical order,</li>
/// <li>```new```: sort books by publishing dates, beginning with the most recents,</li>
/// <li>```old```: sort books by publishing dates, beginning with the oldest</li>
/// </ul>
/// </param>
/// <returns>max <i>count</i> books</returns>
Task<Tuple<long, IEnumerable<BookDTO>>> GetBooksByTitle(string title, int index, int count, string sort = "");
/// <summary>
/// get books of a particular author by giving the author id
/// </summary>
/// <param name="authorId">the id of the author</param>
/// <param name="index">index of the page of resulting books</param>
/// <param name="count">number of resulting books per page</param>
/// <param name="sort">sort criterium (not mandatory):
/// <ul>
/// <li>```title```: sort books by titles in alphabetical order,</li>
/// <li>```title_reverse```: sort books by titles in reverse alphabetical order,</li>
/// <li>```new```: sort books by publishing dates, beginning with the most recents,</li>
/// <li>```old```: sort books by publishing dates, beginning with the oldest</li>
/// </ul>
/// </param>
/// <returns>max <i>count</i> books</returns>
Task<Tuple<long, IEnumerable<BookDTO>>> GetBooksByAuthorId(string authorId, int index, int count, string sort = "");
/// <summary>
/// get books of authors whose name (or alternate names) contains a particular substring
/// </summary>
/// <param name="author">name to look for in author names or alternate names</param>
/// <param name="index">index of the page of resulting books</param>
/// <param name="count">number of resulting books per page</param>
/// <param name="sort">sort criterium (not mandatory):
/// <ul>
/// <li>```title```: sort books by titles in alphabetical order,</li>
/// <li>```title_reverse```: sort books by titles in reverse alphabetical order,</li>
/// <li>```new```: sort books by publishing dates, beginning with the most recents,</li>
/// <li>```old```: sort books by publishing dates, beginning with the oldest</li>
/// </ul>
/// </param>
/// <returns>max <i>count</i> books</returns>
Task<Tuple<long, IEnumerable<BookDTO>>> GetBooksByAuthor(string author, int index, int count, string sort = "");
/// <summary>
/// get an author by specifying its id
/// </summary>
/// <param name="id">id of the Author to get</param>
/// <returns>an author with this id (or null if id is unknown)</returns>
Task<AuthorDTO> GetAuthorById(string id);
/// <summary>
/// get authors containing a substring in their names (or alternate names)
/// </summary>
/// <param name="substring">the substring to look for in author names (or alternate names)</param>
/// <param name="index">index of the page of resulting authors</param>
/// <param name="count">number of resulting authors per page</param>
/// <param name="sort">sort criterium (not mandatory):
/// <ul>
/// <li>```name```: sort authors by names in alphabetical order,</li>
/// <li>```name_reverse```: sort authors by names in reverse alphabetical order,</li>
/// </ul>
/// </param>
/// <returns>max <i>count</i> authors</returns>
Task<Tuple<long, IEnumerable<AuthorDTO>>> GetAuthorsByName(string substring, int index, int count, string sort = "");
}
}

@ -1,78 +0,0 @@
using LibraryDTO;
using Newtonsoft.Json.Linq;
using System.Globalization;
namespace JsonReader
{
public static class AuthorJsonReader
{
public static AuthorDTO ReadAuthor(string json)
{
JObject o = JObject.Parse(json);
string bioTokenAsString = null;
if (o.TryGetValue("bio", out JToken? bioToken))
{
if (bioToken.Type == JTokenType.String)
{
bioTokenAsString = (string)bioToken;
}
else
{
var bioTokenValue = o["bio"]?["value"];
bioTokenAsString = (string)bioTokenValue;
}
}
AuthorDTO author = new AuthorDTO
{
Id = (string)o["key"],
Name = (string)o["name"],
Bio = bioTokenAsString,
BirthDate = o.TryGetValue("birth_date", out JToken? bd) ? ReadDate((string)o["birth_date"]) : null,
DeathDate = o.TryGetValue("death_date", out JToken? dd) ? ReadDate((string)o["death_date"]) : null,
Links = o.TryGetValue("links", out JToken? links) ? links.Select(l => new LinkDTO { Title = (string)l["title"], Url = (string)l["url"] }).ToList() : new List<LinkDTO>(),
AlternateNames = o.TryGetValue("alternate_names", out JToken? altNames) ? altNames.Select(alt => (string)alt).ToList() : new List<string?>()
};
return author;
}
public static DateTime? ReadDate(string dateInJson)
{
if (dateInJson == null) return null;
List<Tuple<string, CultureInfo>> pubDateFormat = new List<Tuple<string, CultureInfo>>()
{
Tuple.Create("d MMMM yyyy", CultureInfo.GetCultureInfo("fr-FR")),
Tuple.Create("d MMMM yyyy", CultureInfo.InvariantCulture),
Tuple.Create("MMM dd, yyyy", CultureInfo.InvariantCulture)
};
DateTime? publishDate = null;
foreach (var format in pubDateFormat)
{
if (DateTime.TryParseExact(dateInJson, format.Item1, format.Item2, DateTimeStyles.None, out DateTime readDate))
{
publishDate = readDate;
break;
}
}
if (!publishDate.HasValue && int.TryParse(dateInJson, out int year))
{
publishDate = new DateTime(year, 12, 31);
}
return publishDate;
}
public static Tuple<long, IEnumerable<AuthorDTO>> GetAuthorsByName(string json)
{
JObject o = JObject.Parse(json);
long numFound = (long)o["numFound"];
var authors = o["docs"].Select(doc => new AuthorDTO
{
Id = $"/authors/{(string)doc["key"]}",
Name = (string)doc["name"],
});
return Tuple.Create(numFound, authors);
}
}
}

@ -1,101 +0,0 @@
using LibraryDTO;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JsonReader
{
public static class BookJsonReader
{
static Dictionary<string, Languages> languages = new Dictionary<string, Languages>()
{
[@"/languages/fre"] = Languages.French,
[@"/languages/eng"] = Languages.English,
["fre"] = Languages.French,
["eng"] = Languages.English,
[""] = Languages.Unknown
};
public static BookDTO ReadBook(string json)
{
JObject o = JObject.Parse(json);
var l = o["languages"]?.FirstOrDefault("");
Languages lang = l != null ? languages[(string)l["key"]] : Languages.Unknown;
//List<Tuple<string, CultureInfo>> pubDateFormat =new List<Tuple<string, CultureInfo>>()
//{
// Tuple.Create("d MMMM yyyy", CultureInfo.GetCultureInfo("fr-FR")),
// Tuple.Create("MMM dd, yyyy", CultureInfo.InvariantCulture)
//};
//DateTime? publishDate = null;
//foreach(var format in pubDateFormat)
//{
// if(DateTime.TryParseExact((string)o["publish_date"], format.Item1, format.Item2, DateTimeStyles.None, out DateTime readDate))
// {
// publishDate = readDate;
// break;
// }
//}
//if(!publishDate.HasValue)
//{
// publishDate = new DateTime((int)o["publish_date"], 12, 31);
//}
DateTime? publishDate = AuthorJsonReader.ReadDate((string)o["publish_date"]);
BookDTO book = new BookDTO
{
Id = (string)o["key"],
Title = (string)o["title"],
Publishers = o["publishers"].Select(p => (string)p).ToList(),
PublishDate = publishDate.GetValueOrDefault(DateTime.Now),
ISBN13 = (string)o["isbn_13"][0],
NbPages = o["number_of_pages"] != null ? (int)o["number_of_pages"] : -1,
Language = lang,
Format = o.TryGetValue("physical_format", out JToken? f) ? (string)f : null,
Works = o["works"].Select(w => new WorkDTO { Id = (string)w["key"] }).ToList(),
Contributors = o.TryGetValue("contributors", out JToken? contr) ? contr.Select(c => new ContributorDTO { Name = (string)c["name"], Role = (string)c["role"] }).ToList() : new List<ContributorDTO>(),
Authors = o["authors"]?.Select(a => new AuthorDTO { Id = (string)a["key"] }).ToList()
};
if (book.Authors == null)
{
book.Authors = new List<AuthorDTO>();
}
return book;
}
public static Tuple<long, IEnumerable<BookDTO>> GetBooksByAuthor(string json)
{
JObject o = JObject.Parse(json);
long numFound = (long)o["numFound"];
var books = o["docs"].Select(doc => new BookDTO
{
Id = (string)(doc["seed"].First()),
Title = (string)doc["title"],
ISBN13 = (string)(doc["isbn"].First()),
Authors = doc["seed"].Where(s => ((string)s).StartsWith("/authors/"))
.Select(s => new AuthorDTO { Id = (string)s }).ToList(),
Language = languages.GetValueOrDefault((string)(doc["language"].First()))
});
return Tuple.Create(numFound, books);
}
public static Tuple<long, IEnumerable<BookDTO>> GetBooksByTitle(string json)
{
JObject o = JObject.Parse(json);
long numFound = (long)o["numFound"];
var books = o["docs"].Select(doc => new BookDTO
{
Id = (string)(doc["seed"].First()),
Title = (string)doc["title"],
ISBN13 = (string)(doc["isbn"].First()),
Authors = doc["seed"].Where(s => ((string)s).StartsWith("/authors/"))
.Select(s => new AuthorDTO { Id = (string)s }).ToList(),
Language = languages.GetValueOrDefault((string)(doc["language"].First()))
});
return Tuple.Create(numFound, books);
}
}
}

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LibraryDTO\LibraryDTO.csproj" />
</ItemGroup>
</Project>

@ -1,57 +0,0 @@
using LibraryDTO;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JsonReader
{
public static class WorkJsonReader
{
public static WorkDTO ReadWork(string json, string ratingsJson)
{
JObject o = JObject.Parse(json);
JObject r = JObject.Parse(ratingsJson);
var ratingsDto = new RatingsDTO();
if (r["summary"]["average"].Type != JTokenType.Float)
{
ratingsDto.Average = -1;
ratingsDto.Count = 0;
}
else
{
ratingsDto.Average = (float)r["summary"]["average"];
ratingsDto.Count = (int)r["summary"]["count"];
}
string description = null;
if (o.TryGetValue("description", out JToken? descr))
{
if (descr.Type == JTokenType.String)
{
description = (string)descr;
}
else
{
if (descr["value"].Type == JTokenType.String)
{
description = (string)descr["value"];
}
}
}
WorkDTO work = new WorkDTO
{
Id = (string)o["key"],
Title = (string)o["title"],
Authors = o.TryGetValue("authors", out JToken? authors) ? authors.Select(a => new AuthorDTO { Id = (string)a["author"]["key"] }).ToList() : new List<AuthorDTO>(),
Description = description,
Subjects = o.TryGetValue("subjects", out JToken? subjects) ? subjects.Select(s => (string)s).ToList() : new List<string>(),
Ratings = ratingsDto
};
return work;
}
}
}

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryDTO
{
public class AuthorDTO
{
public string Id { get; set; }
public string Name { get; set; }
public string ImageSmall => $"https://covers.openlibrary.org/a/olid/{Id.Substring(Id.LastIndexOf("/"))}-S.jpg";
public string ImageMedium => $"https://covers.openlibrary.org/a/olid/{Id.Substring(Id.LastIndexOf("/"))}-M.jpg";
public string ImageLarge => $"https://covers.openlibrary.org/a/olid/{Id.Substring(Id.LastIndexOf("/"))}-L.jpg";
public string Bio { get; set; }
public List<string> AlternateNames { get; set; } = new List<string>();
public List<LinkDTO> Links { get; set; }
public DateTime? BirthDate { get; set; }
public DateTime? DeathDate { get; set; }
}
}

@ -1,21 +0,0 @@
namespace LibraryDTO
{
public class BookDTO
{
public string Id { get; set; }
public string Title { get; set; }
public List<string> Publishers { get; set; } = new List<string>();
public DateTime PublishDate { get; set; }
public string ISBN13 { get; set; }
public List<string> Series { get; set; } = new List<string>();
public int NbPages { get; set; }
public string Format { get; set; }
public Languages Language { get; set; }
public List<ContributorDTO> Contributors { get; set; }
public string ImageSmall => $"https://covers.openlibrary.org/b/isbn/{ISBN13}-S.jpg";
public string ImageMedium => $"https://covers.openlibrary.org/b/isbn/{ISBN13}-M.jpg";
public string ImageLarge => $"https://covers.openlibrary.org/b/isbn/{ISBN13}-L.jpg";
public List<WorkDTO> Works { get; set; } = new List<WorkDTO>();
public List<AuthorDTO> Authors { get; set; } = new List<AuthorDTO>();
}
}

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryDTO
{
public class ContributorDTO
{
public string Name { get; set; }
public string Role { get; set; }
}
}

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryDTO
{
public enum Languages
{
Unknown,
French,
English
}
}

@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryDTO
{
public class LinkDTO
{
public string Title { get; set; }
public string Url { get; set; }
}
}

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryDTO
{
public class RatingsDTO
{
public float Average { get; set; }
public int Count { get; set; }
}
}

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibraryDTO
{
public class WorkDTO
{
public string Id { get; set; }
public string Description { get; set; }
public string Title { get; set; }
public List<string> Subjects { get; set; } = new List<string>();
public List<AuthorDTO> Authors { get; set; } = new List<AuthorDTO>();
public RatingsDTO Ratings { get; set; }
}
}

@ -4,29 +4,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 17.0.31611.283
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LivreLand", "LivreLand\LivreLand.csproj", "{0E95A11F-0D16-4CC3-82CD-E3BE44C28B2B}"
ProjectSection(ProjectDependencies) = postProject
{7DB41B43-9DAA-48C8-8D41-EF2F06FDD33E} = {7DB41B43-9DAA-48C8-8D41-EF2F06FDD33E}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model", "Model\Model.csproj", "{7DB41B43-9DAA-48C8-8D41-EF2F06FDD33E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModels", "ViewModels\ViewModels.csproj", "{72B707A3-3797-4F15-80BC-9D5ECA7B67EE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stub", "Stub\Stub.csproj", "{65A55AED-D8C3-4416-85FE-5E0688C70B88}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StubbedDTO", "StubbedDTO\StubbedDTO.csproj", "{73CAF8BC-E443-48F3-AB04-77F1AF6A24A3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibraryDTO", "LibraryDTO\LibraryDTO.csproj", "{C42003CE-3CE8-4CAA-BF08-82FB9EA5E825}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DtoAbstractLayer", "DtoAbstractLayer\DtoAbstractLayer.csproj", "{0AAA2F93-2C4F-4245-A37D-DC8C7261ADEC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonReader", "JsonReader\JsonReader.csproj", "{62D56765-482A-4B7A-B77A-517B0AABF443}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils", "Utils\Utils.csproj", "{D74E6DD7-ED6A-400C-89EE-FA3BB50D924F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PersonalMVVMToolkit", "PersonalMVVMToolkit\PersonalMVVMToolkit.csproj", "{DBB77CBE-CB7A-4277-B625-60DBD5749C12}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{F2F8D537-7A2F-4B67-A7C6-F8B7FE37483D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -40,46 +17,6 @@ Global
{0E95A11F-0D16-4CC3-82CD-E3BE44C28B2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E95A11F-0D16-4CC3-82CD-E3BE44C28B2B}.Release|Any CPU.Build.0 = Release|Any CPU
{0E95A11F-0D16-4CC3-82CD-E3BE44C28B2B}.Release|Any CPU.Deploy.0 = Release|Any CPU
{7DB41B43-9DAA-48C8-8D41-EF2F06FDD33E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7DB41B43-9DAA-48C8-8D41-EF2F06FDD33E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7DB41B43-9DAA-48C8-8D41-EF2F06FDD33E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7DB41B43-9DAA-48C8-8D41-EF2F06FDD33E}.Release|Any CPU.Build.0 = Release|Any CPU
{72B707A3-3797-4F15-80BC-9D5ECA7B67EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{72B707A3-3797-4F15-80BC-9D5ECA7B67EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72B707A3-3797-4F15-80BC-9D5ECA7B67EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{72B707A3-3797-4F15-80BC-9D5ECA7B67EE}.Release|Any CPU.Build.0 = Release|Any CPU
{65A55AED-D8C3-4416-85FE-5E0688C70B88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65A55AED-D8C3-4416-85FE-5E0688C70B88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65A55AED-D8C3-4416-85FE-5E0688C70B88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65A55AED-D8C3-4416-85FE-5E0688C70B88}.Release|Any CPU.Build.0 = Release|Any CPU
{73CAF8BC-E443-48F3-AB04-77F1AF6A24A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73CAF8BC-E443-48F3-AB04-77F1AF6A24A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73CAF8BC-E443-48F3-AB04-77F1AF6A24A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73CAF8BC-E443-48F3-AB04-77F1AF6A24A3}.Release|Any CPU.Build.0 = Release|Any CPU
{C42003CE-3CE8-4CAA-BF08-82FB9EA5E825}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C42003CE-3CE8-4CAA-BF08-82FB9EA5E825}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C42003CE-3CE8-4CAA-BF08-82FB9EA5E825}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C42003CE-3CE8-4CAA-BF08-82FB9EA5E825}.Release|Any CPU.Build.0 = Release|Any CPU
{0AAA2F93-2C4F-4245-A37D-DC8C7261ADEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0AAA2F93-2C4F-4245-A37D-DC8C7261ADEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0AAA2F93-2C4F-4245-A37D-DC8C7261ADEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0AAA2F93-2C4F-4245-A37D-DC8C7261ADEC}.Release|Any CPU.Build.0 = Release|Any CPU
{62D56765-482A-4B7A-B77A-517B0AABF443}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62D56765-482A-4B7A-B77A-517B0AABF443}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62D56765-482A-4B7A-B77A-517B0AABF443}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62D56765-482A-4B7A-B77A-517B0AABF443}.Release|Any CPU.Build.0 = Release|Any CPU
{D74E6DD7-ED6A-400C-89EE-FA3BB50D924F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D74E6DD7-ED6A-400C-89EE-FA3BB50D924F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D74E6DD7-ED6A-400C-89EE-FA3BB50D924F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D74E6DD7-ED6A-400C-89EE-FA3BB50D924F}.Release|Any CPU.Build.0 = Release|Any CPU
{DBB77CBE-CB7A-4277-B625-60DBD5749C12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBB77CBE-CB7A-4277-B625-60DBD5749C12}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBB77CBE-CB7A-4277-B625-60DBD5749C12}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBB77CBE-CB7A-4277-B625-60DBD5749C12}.Release|Any CPU.Build.0 = Release|Any CPU
{F2F8D537-7A2F-4B67-A7C6-F8B7FE37483D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2F8D537-7A2F-4B67-A7C6-F8B7FE37483D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2F8D537-7A2F-4B67-A7C6-F8B7FE37483D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2F8D537-7A2F-4B67-A7C6-F8B7FE37483D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -12,15 +12,15 @@
<TabBar>
<ShellContent Title="My Library"
ContentTemplate="{DataTemplate view:BibliothequeView}"
Route="library"
Icon="books_vertical_fill.png"/>
<ShellContent Title="My Lists"
ContentTemplate="{DataTemplate view:TousView}"
Route="tous"
Icon="list_bullet.svg"/>
<ShellContent Title="My Readings"
ContentTemplate="{DataTemplate view:EmpruntsPretsView}"
Icon="bookmark_fill"/>
<ShellContent Title="Search"
ContentTemplate="{DataTemplate view:FiltrageDateView}"
Icon="magnifying_glass.png"/>
</TabBar>

@ -1,22 +1,9 @@
using LivreLand.View;
namespace LivreLand;
namespace LivreLand;
public partial class AppShell : Shell
{
public AppShell()
{
Routing.RegisterRoute("library/tous/", typeof(TousView));
Routing.RegisterRoute("library/pret/", typeof(EmpruntsPretsView));
Routing.RegisterRoute("library/later/", typeof(ALirePlusTardView));
Routing.RegisterRoute("library/statut/", typeof(StatutLectureView));
Routing.RegisterRoute("library/favoris/", typeof(FavorisView));
Routing.RegisterRoute("library/auteur/", typeof(FiltrageAuteurView));
Routing.RegisterRoute("library/date/", typeof(FiltrageDateView));
Routing.RegisterRoute("library/note/", typeof(FiltrageNoteView));
Routing.RegisterRoute("library/contacts/", typeof(ContactsView));
Routing.RegisterRoute("library/scan/", typeof(ScanView));
Routing.RegisterRoute("library/tous/details/", typeof(DetailsLivreView));
InitializeComponent();
}
}

@ -32,7 +32,7 @@
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" />
<MauiIcon Include="Resources\AppIcon\appicon.png" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
@ -49,20 +49,12 @@
</ItemGroup>
<ItemGroup>
<Compile Remove="ViewModel\PublishDateVM.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Camera.MAUI" Version="1.4.4" />
<PackageReference Include="CommunityToolkit.Maui" Version="5.3.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Model\Model.csproj" />
<ProjectReference Include="..\PersonalMVVMToolkit\PersonalMVVMToolkit.csproj" />
<ProjectReference Include="..\Stub\Stub.csproj" />
<ProjectReference Include="..\ViewModels\ViewModels.csproj" />
<Folder Include="ViewModel\" />
</ItemGroup>
<ItemGroup>
@ -72,9 +64,6 @@
<MauiXaml Update="View\BibliothequeView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="View\ContactsView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="View\ContentViews\AlphabetVerticalMenuView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
@ -93,9 +82,6 @@
<MauiXaml Update="View\ContentViews\PopupHomePlusButtonView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="View\ContentViews\PopupISBNView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="View\ContentViews\PopupLetterView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
@ -138,9 +124,6 @@
<MauiXaml Update="View\HeaderPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="View\ScanView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="View\StatutLectureView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>

@ -1,12 +1,5 @@
using Camera.MAUI;
using CommunityToolkit.Maui;
using LivreLand.View;
using LivreLand.View.ContentViews;
using LivreLand.ViewModel;
using CommunityToolkit.Maui;
using Microsoft.Extensions.Logging;
using Model;
using Stub;
using ViewModels;
namespace LivreLand;
@ -18,48 +11,12 @@ public static class MauiProgram
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.UseMauiCameraView()
.ConfigureFonts(fonts =>
{
fonts.AddFont("SF-Compact-Display-Black.otf", "SFCompactDisplayBlack");
fonts.AddFont("SF-Compact-Display-Bold.otf", "SFCompactDisplayBold");
});
builder.Services
.AddSingleton<BibliothequeView>()
.AddSingleton<TousView>()
.AddSingleton<FiltrageAuteurView>()
.AddSingleton<FiltrageDateView>()
.AddSingleton<FiltrageNoteView>()
.AddSingleton<ALirePlusTardView>()
.AddSingleton<StatutLectureView>()
.AddSingleton<EmpruntsPretsView>()
.AddSingleton<FavorisView>()
.AddSingleton<ContactsView>()
.AddSingleton<PopupISBNView>()
.AddSingleton<ScanView>()
.AddSingleton<NavigatorVM>()
.AddSingleton<ILibraryManager, LibraryStub>()
.AddSingleton<IUserLibraryManager, UserLibraryStub>()
.AddSingleton<Manager>()
.AddSingleton<ManagerVM>()
.AddSingleton<BibliothequeVM>()
.AddSingleton<TousVM>()
.AddSingleton<FiltrageAuteurVM>()
.AddSingleton<FiltrageDateVM>()
.AddSingleton<FiltrageNoteVM>()
.AddSingleton<ALirePlusTardVM>()
.AddSingleton<StatutLectureVM>()
.AddSingleton<EmpruntsPretsVM>()
.AddSingleton<FavorisVM>()
.AddSingleton<ContactsVM>()
.AddSingleton<PopupISBNVM>()
.AddSingleton<ScanVM>();
#if DEBUG
builder.Logging.AddDebug();
#endif

@ -3,5 +3,4 @@
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
</manifest>

@ -28,7 +28,5 @@
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
<key>NSCameraUsageDescription</key>
<string>This app uses camera for scanning barcodes</string>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

@ -1,45 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="500.000000pt" height="500.000000pt" viewBox="0 0 500.000000 500.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2715 2400 c-22 -11 -31 -18 -20 -15 98 21 140 14 219 -35 54 -35 68
-32 46 8 -34 61 -162 83 -245 42z"/>
<path d="M2095 2385 c-38 -20 -65 -51 -65 -76 0 -17 9 -13 61 23 59 42 63 43
140 43 72 0 76 1 46 12 -47 17 -147 16 -182 -2z"/>
<path d="M2761 2308 c-149 -23 -259 -165 -248 -320 5 -77 31 -134 85 -191 40
-42 108 -82 116 -69 3 5 -10 14 -29 20 -42 16 -111 90 -137 150 -14 32 -21 67
-20 113 0 120 56 207 167 260 232 111 487 -121 396 -361 -10 -27 -33 -68 -51
-90 -17 -22 -27 -40 -22 -40 5 0 22 16 36 35 99 129 90 299 -20 409 -71 71
-167 100 -273 84z"/>
<path d="M2119 2299 c-100 -15 -183 -79 -231 -179 -32 -64 -31 -176 0 -245 24
-52 58 -95 76 -95 5 0 -2 12 -17 28 -40 42 -68 115 -69 180 -3 215 197 356
398 281 229 -86 247 -420 29 -528 -31 -16 -35 -20 -18 -21 30 0 102 57 139
112 18 26 36 71 43 105 41 210 -137 395 -350 362z"/>
<path d="M2158 2129 c-11 -6 -18 -22 -18 -39 0 -39 35 -42 52 -5 15 33 -7 60
-34 44z"/>
<path d="M2797 2133 c-13 -12 -7 -50 9 -63 12 -11 18 -10 31 3 14 13 14 21 5
42 -11 24 -31 32 -45 18z"/>
<path d="M2229 2083 c-39 -34 -59 -79 -59 -137 0 -56 14 -93 47 -128 80 -84
193 -9 193 127 0 69 -23 121 -64 146 -43 26 -79 24 -117 -8z"/>
<path d="M2643 2094 c-93 -46 -108 -201 -28 -281 105 -105 244 64 175 214 -18
42 -69 83 -100 83 -8 0 -30 -8 -47 -16z"/>
<path d="M2570 1730 c-43 -23 -79 -25 -125 -6 -19 8 -35 11 -35 6 0 -4 20 -16
45 -25 51 -20 101 -15 137 14 32 27 20 33 -22 11z"/>
<path d="M1684 1728 c-4 -7 -10 -215 -12 -464 -3 -339 -2 -453 7 -459 7 -4 54
-15 106 -26 202 -41 595 -201 610 -249 6 -18 15 -20 100 -20 89 0 94 1 97 23
6 46 271 154 567 232 74 19 138 38 143 43 5 5 7 207 6 450 -3 499 -1 482 -73
457 -22 -8 -182 -60 -357 -116 -271 -88 -318 -106 -327 -126 -9 -20 -18 -23
-66 -23 -48 0 -57 3 -66 24 -9 19 -65 42 -352 145 -188 66 -350 121 -359 121
-9 0 -20 -5 -24 -12z m1576 -153 c0 -50 -4 -85 -10 -85 -6 0 -10 31 -10 74 l0
75 -72 -25 c-78 -26 -98 -30 -82 -14 10 10 140 58 162 59 9 1 12 -22 12 -84z
m4 -296 c6 -154 4 -192 -8 -178 -7 8 -14 349 -6 349 4 0 10 -77 14 -171z m6
-209 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z
m0 -40 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10
-10z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.ALirePlusTardView"
Title="ALirePlusTardView">
@ -18,8 +17,6 @@
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="True"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding ALirePlusTardVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding ALirePlusTardVM.Navigator.PopupBackButtonNavigationCommand}"
Grid.Row="0"/>
<ScrollView Grid.Row="2">
<Grid>
@ -41,14 +38,12 @@
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1"/>
</Grid>
<CollectionView ItemsSource="{Binding ALirePlusTardVM.Manager.ToBeReadBooks}"
SelectedItem="{Binding ALirePlusTardVM.Manager.SelectedBook}"
<CollectionView ItemsSource="{Binding ALirePlusTardBooks}"
SelectionMode="Single"
SelectionChangedCommand="{Binding ALirePlusTardVM.OnSelectionChangedCommand}"
SelectionChangedCommandParameter="{Binding ALirePlusTardVM.Manager.SelectedBook}"
SelectionChanged="OnSelectionChanged"
Grid.Row="2">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:BookVM">
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
@ -87,7 +82,7 @@
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="{Binding ImageSmall}"
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
@ -103,11 +98,11 @@
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<Label Text="Authors"
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding Status}"
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>

@ -1,28 +1,22 @@
using LivreLand.Model;
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class ALirePlusTardView : ContentPage
{
#region Properties
public ALirePlusTardVM ALirePlusTardVM { get; set; }
#endregion
#region Constructor
public List<BookModel> ALirePlusTardBooks { get; set; } = new List<BookModel>()
{
new BookModel("La horde du contrevent","Alain Damasio","Non lu", 0),
};
public ALirePlusTardView(ALirePlusTardVM aLirePlusTardVM)
public ALirePlusTardView()
{
ALirePlusTardVM = aLirePlusTardVM;
InitializeComponent();
BindingContext = this;
InitializeComponent();
}
#endregion
#region Methods
#endregion
void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView());
}
}

@ -5,6 +5,7 @@
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="LivreLand.View.BibliothequeView"
x:Name="this"
Title="BibliothequeView">
<ContentPage.Behaviors>
@ -15,15 +16,14 @@
</toolkit:StatusBarBehavior>
</ContentPage.Behaviors>
<Grid>
<Grid BindingContext="{x:Reference this}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<view:HeaderHome Grid.Row="0"
ButtonTappedCommand="{Binding BibliothequeVM.Navigator.PopupHomePlusNavigationCommand}"/>
<view:HeaderHome Grid.Row="0"/>
<ScrollView Grid.Row="2">
<Grid>
<Grid.RowDefinitions>
@ -52,10 +52,10 @@
<!--Tous-->
<contentView:HomeButtonView ButtonTitle="Tous"
ButtonIcon="tray_2_fill.png"
ButtonNumber="{Binding BibliothequeVM.Manager.NbBooks}"
ButtonNumber="45"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllBooksNavigateCommand}"/>
ButtonTappedCommand="{Binding TousNavigationCommand}"/>
<contentView:SeparatorCutStartView/>
@ -65,7 +65,7 @@
ButtonNumber="1"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllLoansBorrowingsNavigateCommand}"/>
ButtonTappedCommand="{Binding EmpruntsPretsNavigationCommand}"/>
<contentView:SeparatorCutStartView/>
@ -74,7 +74,7 @@
ButtonIcon="arrow_forward.png"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllToReadBooksNavigateCommand}"/>
ButtonTappedCommand="{Binding ALirePlusTardNavigationCommand}"/>
<contentView:SeparatorCutStartView/>
@ -83,7 +83,7 @@
ButtonIcon="eyeglasses.png"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllStatusBooksNavigateCommand}"/>
ButtonTappedCommand="{Binding StatutLectureNavigationCommand}"/>
<contentView:SeparatorCutStartView/>
@ -92,7 +92,7 @@
ButtonIcon="heart_fill.png"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllFavorisBooksNavigateCommand}"/>
ButtonTappedCommand="{Binding FavorisNavigationCommand}"/>
<contentView:SeparatorEntireView/>
</VerticalStackLayout>
@ -114,7 +114,7 @@
ButtonIcon="person_fill.png"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllAuthorsNavigateCommand}"/>
ButtonTappedCommand="{Binding AuteurNavigationCommand}"/>
<contentView:SeparatorCutStartView/>
@ -123,7 +123,7 @@
ButtonIcon="calendar.png"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllDatesNavigateCommand}"/>
ButtonTappedCommand="{Binding DatePublicationNavigationCommand}"/>
<contentView:SeparatorCutStartView/>
@ -132,7 +132,7 @@
ButtonIcon="sparkles.png"
ButtonRedIconVisible="False"
ButtonBlackIconVisible="True"
ButtonTappedCommand="{Binding BibliothequeVM.AllRatingsNavigateCommand}"/>
ButtonTappedCommand="{Binding NoteNavigationCommand}"/>
<contentView:SeparatorEntireView/>
</VerticalStackLayout>

@ -1,36 +1,69 @@
using LivreLand.ViewModel;
using System.Windows.Input;
namespace LivreLand.View;
public partial class BibliothequeView : ContentPage
{
#region Properties
public ICommand TousNavigationCommand { get; }
public ICommand EmpruntsPretsNavigationCommand { get; }
public ICommand ALirePlusTardNavigationCommand { get; }
public ICommand StatutLectureNavigationCommand { get; }
public ICommand FavorisNavigationCommand { get; }
public ICommand AuteurNavigationCommand { get; }
public ICommand DatePublicationNavigationCommand { get; }
public ICommand NoteNavigationCommand { get; }
public BibliothequeVM BibliothequeVM { get; set; }
#endregion
public BibliothequeView()
{
TousNavigationCommand = new Command(TousNavigation);
EmpruntsPretsNavigationCommand = new Command(EmpruntsPretsNavigation);
ALirePlusTardNavigationCommand = new Command(ALirePlusTardNavigation);
StatutLectureNavigationCommand = new Command(StatutLectureNavigation);
FavorisNavigationCommand = new Command(FavorisNavigation);
AuteurNavigationCommand = new Command(AuteurNavigation);
DatePublicationNavigationCommand = new Command(DatePublicationNavigation);
NoteNavigationCommand = new Command(NoteNavigation);
InitializeComponent();
}
#region Constructor
//Gestion de la navigation temporaire
private async void TousNavigation()
{
await App.Current.MainPage.Navigation.PushAsync(new TousView());
}
public BibliothequeView(BibliothequeVM bibliothequeVM)
private async void EmpruntsPretsNavigation()
{
BibliothequeVM = bibliothequeVM;
InitializeComponent();
BindingContext = this;
await App.Current.MainPage.Navigation.PushAsync(new EmpruntsPretsView());
}
#endregion
private async void ALirePlusTardNavigation()
{
await App.Current.MainPage.Navigation.PushAsync(new ALirePlusTardView());
}
#region Methods
private async void StatutLectureNavigation()
{
await App.Current.MainPage.Navigation.PushAsync(new StatutLectureView());
}
protected override void OnAppearing()
private async void AuteurNavigation()
{
base.OnAppearing();
await App.Current.MainPage.Navigation.PushAsync(new FiltrageAuteurView());
}
BibliothequeVM.Manager.GetBooksFromCollectionCommand.Execute(null);
private async void FavorisNavigation()
{
await App.Current.MainPage.Navigation.PushAsync(new FavorisView());
}
#endregion
private async void DatePublicationNavigation()
{
await App.Current.MainPage.Navigation.PushAsync(new FiltrageDateView());
}
private async void NoteNavigation()
{
await App.Current.MainPage.Navigation.PushAsync(new FiltrageNoteView());
}
}

@ -1,115 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.ContactsView"
Title="ContactsView">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<view:HeaderPage HeaderTitle="Contacts"
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="True"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding ContactsVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding ContactsVM.Navigator.PopupBackButtonNavigationCommand}"
Grid.Row="0"/>
<ScrollView Grid.Row="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource HeaderGray}, Dark={StaticResource Gray900}}"
Grid.Row="0"
Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Contacts"
VerticalOptions="Center"
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1"/>
</Grid>
<Grid HorizontalOptions="Center"
Grid.Row="1"
Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="5"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Text="+ Add new contact"
Grid.Row="0"/>
<VerticalStackLayout IsVisible="{Binding ContactsVM.DataFormIsVisible}"
Grid.Row="2">
<Label Text="Prénom :" />
<Entry Placeholder="Saisissez le prénom"
Text="{Binding ContactsVM.Manager.GivenFirstName}"/>
<Label Text="Nom :"/>
<Entry Placeholder="Saisissez le nom"
Text="{Binding ContactsVM.Manager.GivenLastName}"/>
<Button Text="Enregistrer"
BackgroundColor="Transparent"
Command="{Binding ContactsVM.Manager.AddContactCommand}">
<Button.BorderColor>
<AppThemeBinding Light="{StaticResource Black}" Dark="{StaticResource White}" />
</Button.BorderColor>
<Button.TextColor>
<AppThemeBinding Light="{StaticResource Black}" Dark="{StaticResource White}" />
</Button.TextColor>
</Button>
</VerticalStackLayout>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ContactsVM.AddContactDataFormCommand}"/>
</Grid.GestureRecognizers>
</Grid>
<CollectionView ItemsSource="{Binding ContactsVM.Manager.AllContacts}"
SelectedItem="{Binding ContactsVM.Manager.SelectedContact}"
SelectionChangedCommand="{Binding ContactsVM.BookLendedCommand}"
SelectionChangedCommandParameter="{Binding ContactsVM.Manager.SelectedContact}"
SelectionMode="Single"
Grid.Row="1"
Grid.Column="1">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:ContactVM">
<VerticalStackLayout>
<Grid HorizontalOptions="Center">
<Label>
<Label.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="FirstName" />
<Binding Path="LastName" />
</MultiBinding>
</Label.Text>
</Label>
</Grid>
<contentView:SeparatorEntireView/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ScrollView>
<Grid HorizontalOptions="End"
VerticalOptions="Center"
Grid.RowSpan="3">
<contentView:AlphabetVerticalMenuView/>
</Grid>
</Grid>
</ContentPage>

@ -1,27 +0,0 @@
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class ContactsView : ContentPage
{
#region Properties
public ContactsVM ContactsVM { get; set; }
#endregion
#region Constructor
public ContactsView(ContactsVM contactsVM)
{
ContactsVM = contactsVM;
InitializeComponent();
BindingContext = this;
}
#endregion
#region Methods
#endregion
}

@ -26,9 +26,6 @@
TextColor="Red"
VerticalOptions="Center"
Grid.Column="2"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ButtonCommand}" CommandParameter="{Binding ButtonCommandParameter}"/>
</Grid.GestureRecognizers>
</Grid>
</ContentView>

@ -1,6 +1,3 @@
using System.Windows.Input;
using ViewModels;
namespace LivreLand.View.ContentViews;
public partial class DetailsLivreButtonView : ContentView
@ -19,20 +16,6 @@ public partial class DetailsLivreButtonView : ContentView
set => SetValue(DetailsLivreButtonView.ButtonIconProperty, value);
}
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(nameof(ButtonCommand), typeof(ICommand), typeof(DetailsLivreButtonView));
public ICommand ButtonCommand
{
get => (ICommand)GetValue(DetailsLivreButtonView.ButtonCommandProperty);
set => SetValue(DetailsLivreButtonView.ButtonCommandProperty, value);
}
public static readonly BindableProperty ButtonCommandParameterProperty = BindableProperty.Create(nameof(ButtonCommandParameter), typeof(object), typeof(DetailsLivreButtonView));
public object ButtonCommandParameter
{
get => (object)GetValue(DetailsLivreButtonView.ButtonCommandParameterProperty);
set => SetValue(DetailsLivreButtonView.ButtonCommandParameterProperty, value);
}
public DetailsLivreButtonView()
{
InitializeComponent();

@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LivreLand.View.ContentViews.EmpruntsPretsButtonView"
x:Name="this">
x:Class="LivreLand.View.ContentViews.EmpruntsPretsButtonView">
<Grid BindingContext="{x:Reference this}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="4*"/>
@ -18,18 +17,18 @@
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button Text="Prêts"
<Button x:Name="pretsClicked"
Text="Prêts"
TextColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"
BackgroundColor="{Binding PretButtonBackgroundColor}"
IsEnabled="{Binding PretButtonIsEnabled}"
Command="{Binding PretsButtonCommand}"
BackgroundColor="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}"
Clicked="OnPretsClicked"
Margin="2"
Grid.Column="0"/>
<Button Text="Emprunts"
<Button x:Name="empruntsButton"
Text="Emprunts"
TextColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"
BackgroundColor="{Binding EmpruntButtonBackgroundColor}"
IsEnabled="{Binding EmpruntButtonIsEnabled}"
Command="{Binding EmpruntsButtonCommand}"
BackgroundColor="Transparent"
Clicked="OnEmpruntsClicked"
Margin="2"
Grid.Column="1"/>
</Grid>

@ -1,61 +1,46 @@
using LivreLand.ViewModel;
using System.Windows.Input;
namespace LivreLand.View.ContentViews;
public partial class EmpruntsPretsButtonView : ContentView
{
#region Properties
public static readonly BindableProperty PretButtonBackgroundColorProperty = BindableProperty.Create(nameof(PretButtonBackgroundColor), typeof(Color), typeof(EmpruntsPretsButtonView));
public Color PretButtonBackgroundColor
public EmpruntsPretsButtonView()
{
get => (Color)GetValue(EmpruntsPretsButtonView.PretButtonBackgroundColorProperty);
set => SetValue(EmpruntsPretsButtonView.PretButtonBackgroundColorProperty, value);
InitializeComponent();
}
public static readonly BindableProperty PretButtonIsEnabledProperty = BindableProperty.Create(nameof(PretButtonIsEnabled), typeof(bool), typeof(EmpruntsPretsButtonView));
public bool PretButtonIsEnabled
public void OnPretsClicked(object sender, EventArgs e)
{
get => (bool)GetValue(EmpruntsPretsButtonView.PretButtonIsEnabledProperty);
set => SetValue(EmpruntsPretsButtonView.PretButtonIsEnabledProperty, value);
}
public static readonly BindableProperty PretsButtonCommandProperty = BindableProperty.Create(nameof(PretsButtonCommand), typeof(ICommand), typeof(EmpruntsPretsButtonView));
public ICommand PretsButtonCommand
if (App.Current.PlatformAppTheme == AppTheme.Light)
{
get { return (ICommand)GetValue(PretsButtonCommandProperty); }
set { SetValue(PretsButtonCommandProperty, value); }
pretsClicked.BackgroundColor = Colors.Transparent;
pretsClicked.IsEnabled = false;
empruntsButton.BackgroundColor = Colors.White;
empruntsButton.IsEnabled = true;
}
public static readonly BindableProperty EmpruntButtonBackgroundColorProperty = BindableProperty.Create(nameof(EmpruntButtonBackgroundColor), typeof(Color), typeof(EmpruntsPretsButtonView));
public Color EmpruntButtonBackgroundColor
else
{
get => (Color)GetValue(EmpruntsPretsButtonView.EmpruntButtonBackgroundColorProperty);
set => SetValue(EmpruntsPretsButtonView.EmpruntButtonBackgroundColorProperty, value);
pretsClicked.BackgroundColor = Colors.Transparent;
pretsClicked.IsEnabled = false;
empruntsButton.BackgroundColor = Colors.Black;
empruntsButton.IsEnabled = true;
}
public static readonly BindableProperty EmpruntButtonIsEnabledProperty = BindableProperty.Create(nameof(EmpruntButtonIsEnabled), typeof(bool), typeof(EmpruntsPretsButtonView));
public bool EmpruntButtonIsEnabled
{
get => (bool)GetValue(EmpruntsPretsButtonView.EmpruntButtonIsEnabledProperty);
set => SetValue(EmpruntsPretsButtonView.EmpruntButtonIsEnabledProperty, value);
}
public static readonly BindableProperty EmpruntsButtonCommandProperty = BindableProperty.Create(nameof(EmpruntsButtonCommand), typeof(ICommand), typeof(EmpruntsPretsButtonView));
public ICommand EmpruntsButtonCommand
public void OnEmpruntsClicked(object sender, EventArgs e)
{
if (App.Current.PlatformAppTheme == AppTheme.Light)
{
get { return (ICommand)GetValue(EmpruntsButtonCommandProperty); }
set { SetValue(EmpruntsButtonCommandProperty, value); }
pretsClicked.BackgroundColor = Colors.White;
pretsClicked.IsEnabled = true;
empruntsButton.BackgroundColor = Colors.Transparent;
empruntsButton.IsEnabled = false;
}
#endregion
#region Constructor
public EmpruntsPretsButtonView()
else
{
InitializeComponent();
pretsClicked.BackgroundColor = Colors.Black;
pretsClicked.IsEnabled = true;
empruntsButton.BackgroundColor = Colors.Transparent;
empruntsButton.IsEnabled = false;
}
#endregion
}
}

@ -52,7 +52,7 @@
</Image.Behaviors>
</Image>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ButtonTappedCommand}" CommandParameter="{Binding CommandParameter}"/>
<TapGestureRecognizer Command="{Binding ButtonTappedCommand}"/>
</Grid.GestureRecognizers>
</Grid>

@ -47,13 +47,6 @@ public partial class HomeButtonView : ContentView
set { SetValue(ButtonTappedCommandProperty, value); }
}
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(string), typeof(HomeButtonView));
public string CommandParameter
{
get { return (string)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public HomeButtonView()
{
InitializeComponent();

@ -48,10 +48,6 @@
<toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"/>
</Image.Behaviors>
</Image>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Navigator.NavigationCommand}"
CommandParameter="/scan"/>
</Grid.GestureRecognizers>
</Grid>
<contentView:SeparatorEntireView Grid.Row="3"/>
@ -121,9 +117,6 @@
<toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"/>
</Image.Behaviors>
</Image>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Navigator.PopupISBNNavigationCommand}"/>
</Grid.GestureRecognizers>
</Grid>
</Grid>
<Border.StrokeShape>

@ -1,27 +1,12 @@
using CommunityToolkit.Maui.Views;
using LivreLand.ViewModel;
namespace LivreLand.View.ContentViews;
public partial class PopupHomePlusButtonView : Popup
{
#region Properties
public NavigatorVM Navigator { get; private set; }
#endregion
#region Constructor
public PopupHomePlusButtonView(NavigatorVM navigatorVM)
public PopupHomePlusButtonView()
{
Navigator = navigatorVM;
InitializeComponent();
Size = new Size(0.8 * (DeviceDisplay.Current.MainDisplayInfo.Width / DeviceDisplay.Current.MainDisplayInfo.Density), 0.5 * (DeviceDisplay.Current.MainDisplayInfo.Width / DeviceDisplay.Current.MainDisplayInfo.Density));
BindingContext = this;
}
#endregion
}

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<toolkit:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="LivreLand.View.ContentViews.PopupISBNView"
HorizontalOptions="Center"
VerticalOptions="Center"
Color="Transparent">
<Border>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource PopupBackground}, Dark={StaticResource Black}}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Margin="5">
<Label Text="Saisir l'ISBN"
Style="{StaticResource MasterStateBookText}"/>
</Grid>
<Grid Grid.Row="1"
Margin="5">
<Entry Text="{Binding Manager.EntryText}"
ReturnCommand="{Binding AddBookCommand}"
ReturnCommandParameter="{Binding Manager.EntryText}"/>
</Grid>
</Grid>
<Border.StrokeShape>
<RoundRectangle CornerRadius="10" />
</Border.StrokeShape>
</Border>
</toolkit:Popup>

@ -1,14 +0,0 @@
using CommunityToolkit.Maui.Views;
using LivreLand.ViewModel;
namespace LivreLand.View.ContentViews;
public partial class PopupISBNView : Popup
{
public PopupISBNView(PopupISBNVM popupISBNVM)
{
InitializeComponent();
BindingContext = popupISBNVM;
Size = new Size(0.8 * (DeviceDisplay.Current.MainDisplayInfo.Width / DeviceDisplay.Current.MainDisplayInfo.Density), 0.5 * (DeviceDisplay.Current.MainDisplayInfo.Width / DeviceDisplay.Current.MainDisplayInfo.Density));
}
}

@ -1,11 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
xmlns:model="clr-namespace:Model;assembly=Model"
x:Class="LivreLand.View.DetailsLivreView"
Title="DetailsLivreView">
<Grid>
@ -20,9 +17,7 @@
HeaderBackButtonText="Tous"
HeaderPlusButtonVisible="False"
HeaderSwitchButtonVisible="False"
HeaderColor="{StaticResource HeaderGray}"
ButtonPlusTappedCommand="{Binding DetailsLivreVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding DetailsLivreVM.BackButtonCommand}"/>
HeaderColor="{StaticResource HeaderGray}"/>
<contentView:SeparatorEntireView/>
</VerticalStackLayout>
@ -62,7 +57,7 @@
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="{Binding DetailsLivreVM.Book.ImageSmall}"
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
@ -74,7 +69,7 @@
Margin="0,97,20,0"
VerticalOptions="End"/>
</Grid>
<Label Text="{Binding DetailsLivreVM.Book.Title}"
<Label Text="La horde du contrevent"
Grid.Column="2"
Grid.Row="0"/>
<contentView:StarNotationView Grid.Column="2"
@ -97,14 +92,7 @@
<Image Source="chevron_right.png"
MaximumHeightRequest="20"
MaximumWidthRequest="20"
Grid.Column="2">
<Image.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"/>
</Image.Behaviors>
</Image>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding DetailsLivreVM.OpenInfoCommand}"/>
</Grid.GestureRecognizers>
Grid.Column="2"/>
</Grid>
<contentView:SeparatorCutStartView/>
@ -119,20 +107,9 @@
<Label Text="Auteur"
Style="{StaticResource DetailsLivreTitle}"
Grid.Row="0"/>
<CollectionView ItemsSource="{Binding DetailsLivreVM.Book.Authors}"
Grid.Row="1">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:AuthorVM">
<Label Text="{Binding Name}"
<Label Text="Alain Damasio"
Style="{StaticResource DetailsLivreBody}"
Margin="0,0,1,0"
Grid.Row="1"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<contentView:SeparatorCutStartView/>
@ -147,26 +124,9 @@
<Label Text="Maison d'édition"
Style="{StaticResource DetailsLivreTitle}"
Grid.Row="0"/>
<Grid Grid.Row="1">
<HorizontalStackLayout>
<CollectionView ItemsSource="{Binding DetailsLivreVM.Book.Publishers}"
Grid.Column="0">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding .}"
<Label Text="Gallimard (2015)"
Style="{StaticResource DetailsLivreBody}"
Margin="0,0,1,0"
Grid.Row="1"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Label Text="{Binding DetailsLivreVM.Book.PublishDate,StringFormat=' ({0:yyyy})'}"
Grid.Column="1"/>
</HorizontalStackLayout>
</Grid>
</Grid>
<contentView:SeparatorCutStartView/>
@ -181,7 +141,7 @@
<Label Text="Résumé"
Style="{StaticResource DetailsLivreTitle}"
Grid.Row="0"/>
<Label Text="{Binding DetailsLivreVM.Book.WorkDescription}"
<Label Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Et malesuada fames ac turpis egestas integer eget aliquet. Nunc sed id semper risus. Nisl purus in mollis nunc sed id semper risus. Egestas congue quisque egestas diam in arcu cursus euismod. Elementum integer enim neque volutpat ac tincidunt vitae. Amet luctus venenatis lectus magna fringilla urna porttitor rhoncus dolor. Sollicitudin tempor id eu nisl nunc. Eget mauris pharetra et ultrices neque. In vitae turpis massa sed elementum tempus. Posuere ac ut consequat semper viverra nam. Quisque non tellus orci ac auctor augue mauris augue. Cursus in hac habitasse platea dictumst. Pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus faucibus. Vel fringilla est ullamcorper eget nulla facilisi etiam."
Style="{StaticResource DetailsLivreBody}"
Grid.Row="1"/>
</Grid>
@ -210,7 +170,7 @@
<Label Text="Nombre de pages"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="0"/>
<Label Text="{Binding DetailsLivreVM.Book.NbPages}"
<Label Text="700"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="2"/>
</Grid>
@ -224,7 +184,7 @@
<Label Text="Langue"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="0"/>
<Label Text="{Binding DetailsLivreVM.Book.Language}"
<Label Text="français"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="2"/>
</Grid>
@ -238,7 +198,7 @@
<Label Text="ISBN"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="0"/>
<Label Text="{Binding DetailsLivreVM.Book.ISBN13}"
<Label Text="9782070464234"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="2"/>
</Grid>
@ -266,7 +226,7 @@
<Label Text="Statut"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="0"/>
<Label Text="{Binding DetailsLivreVM.Book.Status}"
<Label Text="Non lu"
Style="{StaticResource DetailsLivreBody}"
Grid.Column="2"/>
</Grid>
@ -304,63 +264,29 @@
</VerticalStackLayout>
<Picker ItemsSource="{Binding DetailsLivreVM.Manager.AllStatus}"
SelectedItem="{Binding DetailsLivreVM.Manager.SelectedStatus}"
IsVisible="{Binding DetailsLivreVM.IsPickerVisible}"
HorizontalOptions="Center"
VerticalOptions="Center"
Grid.Row="1">
<Picker.Behaviors>
<toolkit:EventToCommandBehavior EventName="SelectedIndexChanged"
Command="{Binding DetailsLivreVM.Manager.UpdateStatusBookCommand}"
CommandParameter="{Binding DetailsLivreVM.Book}"/>
</Picker.Behaviors>
</Picker>
<!--Buttons-->
<VerticalStackLayout Grid.Row="2">
<contentView:SeparatorCutStartView/>
<contentView:DetailsLivreButtonView ButtonIcon="heart.png"
ButtonTitle="{Binding DetailsLivreVM.AddFavorisButtonText}"
ButtonCommand="{Binding DetailsLivreVM.AddRemoveBookToFavoritesCommand}"
ButtonCommandParameter="{Binding DetailsLivreVM.Book}"/>
<contentView:SeparatorCutStartView/>
<contentView:DetailsLivreButtonView ButtonIcon="folder.png"
ButtonTitle="Déplacer le livre"/>
<contentView:SeparatorCutStartView/>
<contentView:DetailsLivreButtonView ButtonIcon="rounded_plus.png"
ButtonTitle="Ajouter à la liste À lire plus tard"
ButtonCommand="{Binding DetailsLivreVM.AddBookToReadListCommand}"
ButtonCommandParameter="{Binding DetailsLivreVM.Book}"/>
<contentView:DetailsLivreButtonView ButtonIcon="rounded_plus"
ButtonTitle="Ajouter à la liste À lire plus tard"/>
<contentView:SeparatorCutStartView/>
<contentView:DetailsLivreButtonView ButtonIcon="eyeglasses.png"
ButtonTitle="Changer le statut de lecture"
ButtonCommand="{Binding DetailsLivreVM.ShowPickerCommand}"/>
ButtonTitle="Changer le statut de lecture"/>
<contentView:SeparatorCutStartView/>
<contentView:DetailsLivreButtonView ButtonIcon="person.png"
ButtonTitle="Prêter le livre"
ButtonCommand="{Binding DetailsLivreVM.LoanBookCommand}"
ButtonCommandParameter="{Binding DetailsLivreVM.Book}"/>
<contentView:SeparatorCutStartView/>
<contentView:DetailsLivreButtonView ButtonTitle="Supprimer le livre"
ButtonCommand="{Binding DetailsLivreVM.RemoveBookCommand}"
ButtonCommandParameter="{Binding DetailsLivreVM.Book}"/>
ButtonTitle="Prêter le livre"/>
</VerticalStackLayout>
<!--Buttons-->
</Grid>
</ScrollView>
</Grid>

@ -1,23 +1,9 @@
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class DetailsLivreView : ContentPage
{
#region Properties
public DetailsLivreVM DetailsLivreVM { get; set; }
#endregion
#region Constructor
public DetailsLivreView(DetailsLivreVM detailsLivreVM)
public DetailsLivreView()
{
DetailsLivreVM = detailsLivreVM;
InitializeComponent();
BindingContext = this;
}
#endregion
}

@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.EmpruntsPretsView"
Title="EmpruntsPretsView">
@ -20,27 +19,19 @@
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="True"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding EmpruntsPretsVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding EmpruntsPretsVM.Navigator.PopupBackButtonNavigationCommand}"
Grid.Row="0"/>
<contentView:EmpruntsPretsButtonView Grid.Row="2"
PretButtonBackgroundColor="{Binding EmpruntsPretsVM.PretButtonBackgroundColor}"
PretButtonIsEnabled="{Binding EmpruntsPretsVM.PretButtonIsEnabled}"
PretsButtonCommand="{Binding EmpruntsPretsVM.PretsButtonCommand}"
EmpruntButtonBackgroundColor="{Binding EmpruntsPretsVM.EmpruntButtonBackgroundColor}"
EmpruntButtonIsEnabled="{Binding EmpruntsPretsVM.EmpruntButtonIsEnabled}"
EmpruntsButtonCommand="{Binding EmpruntsPretsVM.EmpruntsButtonCommand}"/>
<contentView:EmpruntsPretsButtonView Grid.Row="2"/>
<ScrollView Grid.Row="4">
<Grid>
<CollectionView ItemsSource="{Binding EmpruntsPretsVM.Manager.AllCurrentGroupedLoans}"
SelectedItem="{Binding EmpruntsPretsVM.Manager.SelectedLoan}"
SelectionMode="Single"
SelectionChangedCommand="{Binding EmpruntsPretsVM.OnSelectionLoanChangedCommand}"
SelectionChangedCommandParameter="{Binding EmpruntsPretsVM.Manager.SelectedLoan}"
IsVisible="{Binding EmpruntsPretsVM.PretCollectionIsVisible}"
IsGrouped="True">
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="10"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="40"/>
<RowDefinition Height="10"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource HeaderGray}, Dark={StaticResource Gray900}}"
Grid.Row="0">
<Grid.ColumnDefinitions>
@ -48,21 +39,18 @@
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label VerticalOptions="Center"
<Label Text="Antoine"
VerticalOptions="Center"
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1">
<Label.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="Key.FirstName" />
<Binding Path="Key.LastName" />
</MultiBinding>
</Label.Text>
</Label>
Grid.Column="1"/>
</Grid>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
<CollectionView ItemsSource="{Binding AntoineBooks}"
SelectionMode="Single"
SelectionChanged="OnSelectionChanged"
Grid.Row="2">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:LoanVM">
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
@ -101,7 +89,7 @@
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="{Binding Book.ImageSmall}"
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
@ -113,15 +101,15 @@
Margin="0,97,20,0"
VerticalOptions="End"/>
</Grid>
<Label Text="{Binding Book.Title}"
<Label Text="{Binding Title}"
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<Label Text="Author"
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding Book.Status}"
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>
@ -133,37 +121,25 @@
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView ItemsSource="{Binding EmpruntsPretsVM.Manager.AllCurrentGroupedBorrowings}"
SelectedItem="{Binding EmpruntsPretsVM.Manager.SelectedBorrowing}"
SelectionMode="Single"
SelectionChangedCommand="{Binding EmpruntsPretsVM.OnSelectionBorrowingChangedCommand}"
SelectionChangedCommandParameter="{Binding EmpruntsPretsVM.Manager.SelectedBorrowing}"
IsVisible="{Binding EmpruntsPretsVM.EmpruntCollectionIsVisible}"
IsGrouped="True">
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource HeaderGray}, Dark={StaticResource Gray900}}"
Grid.Row="0">
Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label VerticalOptions="Center"
<Label Text="Audrey Pouclet"
VerticalOptions="Center"
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1">
<Label.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="Key.FirstName" />
<Binding Path="Key.LastName" />
</MultiBinding>
</Label.Text>
</Label>
Grid.Column="1"/>
</Grid>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
<CollectionView ItemsSource="{Binding AudreyPoucletBooks}"
SelectionMode="Single"
SelectionChanged="OnSelectionChanged"
Grid.Row="6">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:BorrowingVM">
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
@ -202,7 +178,7 @@
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="{Binding Book.ImageSmall}"
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
@ -214,15 +190,15 @@
Margin="0,97,20,0"
VerticalOptions="End"/>
</Grid>
<Label Text="{Binding Book.Title}"
<Label Text="{Binding Title}"
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<Label Text="Author"
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding Book.Status}"
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>

@ -1,28 +1,27 @@
using LivreLand.Model;
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class EmpruntsPretsView : ContentPage
{
#region Properties
public EmpruntsPretsVM EmpruntsPretsVM { get; set; }
#endregion
public List<BookModel> AntoineBooks { get; set; } = new List<BookModel>()
{
new BookModel("The Wake","Scott Snyder","Terminé", 0),
};
#region Constructor
public List<BookModel> AudreyPoucletBooks { get; set; } = new List<BookModel>()
{
new BookModel("Les feux de Cibola","James S. A. Corey","Terminé", 0),
};
public EmpruntsPretsView(EmpruntsPretsVM empruntsPretsVM)
public EmpruntsPretsView()
{
EmpruntsPretsVM = empruntsPretsVM;
InitializeComponent();
BindingContext = this;
InitializeComponent();
}
#endregion
#region Methods
#endregion
void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView());
}
}

@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.FavorisView"
Title="FavorisView">
@ -18,8 +17,6 @@
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="True"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding FavorisVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding FavorisVM.Navigator.PopupBackButtonNavigationCommand}"
Grid.Row="0"/>
<ScrollView Grid.Row="2">
<Grid>
@ -41,14 +38,12 @@
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1"/>
</Grid>
<CollectionView ItemsSource="{Binding FavorisVM.Manager.AllFavoriteBooks}"
SelectedItem="{Binding FavorisVM.Manager.SelectedBook}"
<CollectionView ItemsSource="{Binding FavorisBooks}"
SelectionMode="Single"
SelectionChangedCommand="{Binding FavorisVM.OnSelectionChangedCommand}"
SelectionChangedCommandParameter="{Binding FavorisVM.Manager.SelectedBook}"
SelectionChanged="OnSelectionChanged"
Grid.Row="2">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:BookVM">
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
@ -87,7 +82,7 @@
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="{Binding ImageSmall}"
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
@ -103,11 +98,11 @@
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<Label Text="Author"
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding Status}"
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>

@ -1,28 +1,23 @@
using LivreLand.Model;
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class FavorisView : ContentPage
{
#region Properties
public FavorisVM FavorisVM { get; set; }
#endregion
#region Constructor
public List<BookModel> FavorisBooks { get; set; } = new List<BookModel>()
{
new BookModel("La zone du dehors","Alain Damasio","Terminé", 0),
new BookModel("Le problème à trois corps","Cixin Liu","Terminé", 0)
};
public FavorisView(FavorisVM favorisVM)
public FavorisView()
{
FavorisVM = favorisVM;
InitializeComponent();
BindingContext = this;
InitializeComponent();
}
#endregion
#region Methods
#endregion
void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView());
}
}

@ -4,7 +4,6 @@
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.FiltrageAuteurView"
Title="FiltrageAuteurView">
@ -21,9 +20,7 @@
HeaderTitle="Auteur"
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="False"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding FiltrageAuteurVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding FiltrageAuteurVM.Navigator.PopupBackButtonNavigationCommand}"/>
HeaderSwitchButtonVisible="True"/>
<VerticalStackLayout BackgroundColor="{DynamicResource Light}"
Spacing="10"
@ -37,23 +34,104 @@
<VerticalStackLayout Grid.Row="2">
<contentView:SeparatorEntireView/>
<CollectionView ItemsSource="{Binding FiltrageAuteurVM.Manager.AllAuthors}"
SelectionMode="Single"
SelectedItem="{Binding FiltrageAuteurVM.Manager.SelectedAuthor}"
SelectionChangedCommand="{Binding FiltrageAuteurVM.NavigateAuthorPageCommand}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:AuthorVM">
<VerticalStackLayout>
<contentView:HomeButtonView ButtonTitle="{Binding Name}"
<!--Alain Damasio-->
<contentView:HomeButtonView ButtonTitle="Alain Damasio"
ButtonIcon="book.png"
ButtonNumber="{Binding NbBooksWritten}"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--Cixin Liu-->
<contentView:HomeButtonView ButtonTitle="Cixin Liu"
ButtonIcon="book.png"
ButtonNumber="3"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--Daniel Pennac-->
<contentView:HomeButtonView ButtonTitle="Daniel Pennac"
ButtonIcon="book.png"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--Evgenij Ivanovič Zamâtin-->
<contentView:HomeButtonView ButtonTitle="Evgenij Ivanovič Zamâtin"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--Frank Herbert-->
<contentView:HomeButtonView ButtonTitle="Frank Herbert"
ButtonIcon="book.png"
ButtonNumber="6"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--Herbert George Wells-->
<contentView:HomeButtonView ButtonTitle="Herbert George Wells"
ButtonIcon="book.png"
ButtonNumber="3"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--James S. A. Corey-->
<contentView:HomeButtonView ButtonTitle="James S. A. Corey"
ButtonIcon="book.png"
ButtonNumber="6"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--James Tynion-->
<contentView:HomeButtonView ButtonTitle="James Tynion"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--James Tynion (IV)-->
<contentView:HomeButtonView ButtonTitle="James Tynion (IV)"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--Ken Kesey-->
<contentView:HomeButtonView ButtonTitle="Ken Kesey"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--Ken Liu-->
<contentView:HomeButtonView ButtonTitle="Ken Liu"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>

@ -1,27 +1,9 @@
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class FiltrageAuteurView : ContentPage
{
#region Properties
public FiltrageAuteurVM FiltrageAuteurVM { get; set; }
#endregion
#region Constructor
public FiltrageAuteurView(FiltrageAuteurVM filtrageAuteurVM)
public FiltrageAuteurView()
{
FiltrageAuteurVM = filtrageAuteurVM;
InitializeComponent();
BindingContext = this;
}
#endregion
#region Methods
#endregion
}

@ -4,7 +4,6 @@
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.FiltrageDateView"
Title="FiltrageDateView">
@ -18,11 +17,8 @@
</Grid.RowDefinitions>
<view:HeaderPage HeaderTitle="Date de publication"
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="False"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding FiltrageDateVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding FiltrageDateVM.Navigator.PopupBackButtonNavigationCommand}"
Grid.Row="0"/>
<VerticalStackLayout BackgroundColor="{DynamicResource Light}"
@ -37,23 +33,104 @@
<VerticalStackLayout Grid.Row="2">
<contentView:SeparatorEntireView/>
<CollectionView ItemsSource="{Binding FiltrageDateVM.Manager.AllPublishDates}"
SelectionMode="Single"
SelectedItem="{Binding FiltrageDateVM.Manager.SelectedDate}"
SelectionChangedCommand="{Binding FiltrageDateVM.NavigateDatePageCommand}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:PublishDateVM">
<VerticalStackLayout>
<contentView:HomeButtonView ButtonTitle="{Binding PublishDate, StringFormat='{}{0:yyyy}'}"
<!--2022-->
<contentView:HomeButtonView ButtonTitle="2022"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2021-->
<contentView:HomeButtonView ButtonTitle="2021"
ButtonIcon="book.png"
ButtonNumber="6"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2020-->
<contentView:HomeButtonView ButtonTitle="2020"
ButtonIcon="book.png"
ButtonNumber="6"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2019-->
<contentView:HomeButtonView ButtonTitle="2019"
ButtonIcon="book.png"
ButtonNumber="3"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2018-->
<contentView:HomeButtonView ButtonTitle="2018"
ButtonIcon="book.png"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2016-->
<contentView:HomeButtonView ButtonTitle="2016"
ButtonIcon="book.png"
ButtonNumber="4"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2015-->
<contentView:HomeButtonView ButtonTitle="2015"
ButtonIcon="book.png"
ButtonNumber="4"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2012-->
<contentView:HomeButtonView ButtonTitle="2012"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2010-->
<contentView:HomeButtonView ButtonTitle="2010"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2004-->
<contentView:HomeButtonView ButtonTitle="2004"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--1997-->
<contentView:HomeButtonView ButtonTitle="1997"
ButtonIcon="book.png"
ButtonNumber="1"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>
</Grid>

@ -1,27 +1,9 @@
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class FiltrageDateView : ContentPage
{
#region Properties
public FiltrageDateVM FiltrageDateVM { get; set; }
#endregion
#region Constructor
public FiltrageDateView(FiltrageDateVM filtrageDateVM)
public FiltrageDateView()
{
FiltrageDateVM = filtrageDateVM;
InitializeComponent();
BindingContext = this;
}
#endregion
#region Methods
#endregion
}

@ -4,7 +4,6 @@
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.FiltrageNoteView"
Title="FiltrageNoteView">
@ -21,9 +20,7 @@
HeaderTitle="Note"
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="False"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding FiltrageNoteVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding FiltrageNoteVM.Navigator.PopupBackButtonNavigationCommand}"/>
HeaderSwitchButtonVisible="True"/>
<VerticalStackLayout BackgroundColor="{DynamicResource Light}"
Spacing="10"
@ -37,25 +34,50 @@
<VerticalStackLayout Grid.Row="2">
<contentView:SeparatorEntireView/>
<CollectionView ItemsSource="{Binding FiltrageNoteVM.Manager.AllRatings}"
SelectionMode="Single"
SelectedItem="{Binding FiltrageNoteVM.Manager.SelectedRating}"
SelectionChangedCommand="{Binding FiltrageNoteVM.NavigateRatingPageCommand}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:RatingsVM">
<VerticalStackLayout>
<contentView:HomeButtonView ButtonTitle="{Binding Average}"
<!--1 étoile-->
<contentView:HomeButtonView ButtonTitle="1 étoile"
ButtonIcon="book.png"
ButtonNumber="{Binding NbBooksWritten}"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--2 étoiles-->
<contentView:HomeButtonView ButtonTitle="2 étoiles"
ButtonIcon="book.png"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--3 étoiles-->
<contentView:HomeButtonView ButtonTitle="3 étoiles"
ButtonIcon="book.png"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--4 étoiles-->
<contentView:HomeButtonView ButtonTitle="4 étoiles"
ButtonIcon="book.png"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
<!--5 étoiles-->
<contentView:HomeButtonView ButtonTitle="5 étoiles"
ButtonIcon="book.png"
ButtonNumber="2"
ButtonRedIconVisible="True"
ButtonBlackIconVisible="False"/>
<contentView:SeparatorBigCutStartView/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ScrollView>
</Grid>

@ -1,27 +1,9 @@
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class FiltrageNoteView : ContentPage
{
#region Properties
public FiltrageNoteVM FiltrageNoteVM { get; set; }
#endregion
#region Constructor
public FiltrageNoteView(FiltrageNoteVM filtrageNoteVM)
public FiltrageNoteView()
{
FiltrageNoteVM = filtrageNoteVM;
InitializeComponent();
BindingContext = this;
}
#endregion
#region Methods
#endregion
}

@ -2,11 +2,9 @@
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="LivreLand.View.HeaderHome"
x:Name="this">
x:Class="LivreLand.View.HeaderHome">
<Grid BindingContext="{x:Reference this}"
ColumnDefinitions="auto, *, auto"
<Grid ColumnDefinitions="auto, *, auto"
Margin="5">
<Grid>
<Label Text="Modifier"
@ -20,8 +18,8 @@
BackgroundColor="Transparent"
MaximumHeightRequest="20"
MaximumWidthRequest="20"
Grid.Column="2"
Command="{Binding ButtonTappedCommand}">
Clicked="OnPlusClicked"
Grid.Column="2">
<ImageButton.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{StaticResource PinkOrange}"/>
</ImageButton.Behaviors>

@ -1,30 +1,18 @@
using LivreLand.ViewModel;
using System.Windows.Input;
using CommunityToolkit.Maui.Views;
using LivreLand.View.ContentViews;
namespace LivreLand.View;
public partial class HeaderHome : ContentView
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public static readonly BindableProperty ButtonTappedCommandProperty = BindableProperty.Create(nameof(ButtonTappedCommand), typeof(ICommand), typeof(HeaderPage));
public ICommand ButtonTappedCommand
{
get { return (ICommand)GetValue(ButtonTappedCommandProperty); }
set { SetValue(ButtonTappedCommandProperty, value); }
}
#endregion
#region Constructor
public HeaderHome()
{
InitializeComponent();
}
#endregion
public void OnPlusClicked(object sender, EventArgs e)
{
var plusPopup = new PopupHomePlusButtonView();
App.Current.MainPage.ShowPopup(plusPopup);
}
}

@ -4,10 +4,10 @@
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="LivreLand.View.HeaderPage"
x:Name="this"
BindingContext="{x:Reference this}"
BackgroundColor="{AppThemeBinding Light={Binding HeaderColor}, Dark={StaticResource Black}}">
<Grid BindingContext="{x:Reference this}"
Margin="5">
<Grid Margin="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
@ -31,7 +31,7 @@
MaximumWidthRequest="20"
Grid.Column="0">
<ImageButton.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{StaticResource PinkOrange}"/>
<toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource PinkOrange}, Dark={StaticResource White}}"/>
</ImageButton.Behaviors>
</ImageButton>
<Label Text="{Binding HeaderBackButtonText}"
@ -40,7 +40,7 @@
Style="{StaticResource HeaderTitle}"
Grid.Column="2"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ButtonBackTappedCommand}"/>
<TapGestureRecognizer Tapped="OnBackButtonTapped"/>
</Grid.GestureRecognizers>
</Grid>
<ImageButton VerticalOptions="Center"
@ -49,7 +49,7 @@
MaximumHeightRequest="20"
MaximumWidthRequest="20"
IsVisible="{Binding HeaderPlusButtonVisible}"
Command="{Binding ButtonPlusTappedCommand}"
Clicked="OnPlusClicked"
Grid.Column="2">
<ImageButton.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{StaticResource PinkOrange}"/>

@ -2,18 +2,11 @@ using LivreLand.View.ContentViews;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Graphics;
using CommunityToolkit.Maui.Views;
using System.Windows.Input;
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class HeaderPage : ContentView
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public static readonly BindableProperty HeaderTitleProperty = BindableProperty.Create(nameof(HeaderTitle), typeof(string), typeof(HeaderPage), string.Empty);
public string HeaderTitle
{
@ -49,29 +42,19 @@ public partial class HeaderPage : ContentView
set => SetValue(HeaderPage.HeaderColorProperty, value);
}
public static readonly BindableProperty ButtonPlusTappedCommandProperty = BindableProperty.Create(nameof(ButtonPlusTappedCommand), typeof(ICommand), typeof(HeaderPage));
public ICommand ButtonPlusTappedCommand
public HeaderPage()
{
get { return (ICommand)GetValue(ButtonPlusTappedCommandProperty); }
set { SetValue(ButtonPlusTappedCommandProperty, value); }
InitializeComponent();
}
public static readonly BindableProperty ButtonBackTappedCommandProperty = BindableProperty.Create(nameof(ButtonBackTappedCommand), typeof(ICommand), typeof(HeaderPage));
public ICommand ButtonBackTappedCommand
public void OnBackButtonTapped(object sender, EventArgs e)
{
get { return (ICommand)GetValue(ButtonBackTappedCommandProperty); }
set { SetValue(ButtonBackTappedCommandProperty, value); }
App.Current.MainPage.Navigation.PopAsync();
}
#endregion
#region Constructor
public HeaderPage()
public void OnPlusClicked(object sender, EventArgs e)
{
InitializeComponent();
var plusPopup = new PopupHomePlusButtonView();
App.Current.MainPage.ShowPopup(plusPopup);
}
#endregion
}

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:cv="clr-namespace:Camera.MAUI;assembly=Camera.MAUI"
x:Class="LivreLand.View.ScanView"
Title="ScanView">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<cv:CameraView x:Name="cameraView"
BarCodeDetectionEnabled="True"
Camera="{Binding ScanVM.Camera}"
Cameras="{Binding ScanVM.Cameras}"
NumCamerasDetected="{Binding ScanVM.CamerasCount}"
BarCodeResults="{Binding ScanVM.BarCodeResult}"
WidthRequest="300"
HeightRequest="200">
<cv:CameraView.Behaviors>
<toolkit:EventToCommandBehavior EventName="BarcodeDetected"
Command="{Binding ScanVM.BarcodeDetectCommand}"/>
<toolkit:EventToCommandBehavior EventName="CamerasLoaded"
Command="{Binding ScanVM.CamerasLoadCommand}"/>
</cv:CameraView.Behaviors>
</cv:CameraView>
</Grid>
<Grid Margin="2"
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Label Text="Annuler"
TextColor="{StaticResource Blue100Accent}"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ScanVM.Navigator.PopupBackButtonNavigationCommand}"/>
</Grid.GestureRecognizers>
</Grid>
<Grid IsVisible="{Binding ScanVM.AddIsVisible}"
Grid.Column="2">
<Label Text="Ajouter le livre !"
TextColor="{StaticResource Blue100Accent}"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ScanVM.AddBookISBNDetectedCommand}"
CommandParameter="{Binding ScanVM.BarcodeText}"/>
</Grid.GestureRecognizers>
</Grid>
<Label Text="{Binding ScanVM.BarcodeText}"
TextColor="{StaticResource Blue100Accent}"
Grid.Column="4"/>
</Grid>
</Grid>
</ContentPage>

@ -1,24 +0,0 @@
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class ScanView : ContentPage
{
#region Properties
public ScanVM ScanVM { get; set; }
#endregion
#region Constructor
public ScanView(ScanVM scanVM)
{
ScanVM = scanVM;
InitializeComponent();
ScanVM.CameraView = cameraView; //ToRemove
BindingContext = this;
}
#endregion
}

@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
x:Class="LivreLand.View.StatutLectureView"
Title="StatutLectureView">
@ -20,37 +19,127 @@
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="True"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding StatutLectureVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding StatutLectureVM.Navigator.PopupBackButtonNavigationCommand}"
Grid.Row="0"/>
<contentView:SearchBarView Grid.Row="2"/>
<ScrollView Grid.Row="4">
<Grid>
<CollectionView ItemsSource="{Binding StatutLectureVM.Manager.GroupedStatusBooks}"
SelectedItem="{Binding StatutLectureVM.Manager.SelectedBook}"
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="10"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="40"/>
<RowDefinition Height="10"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource HeaderGray}, Dark={StaticResource Gray900}}"
Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Non lus"
VerticalOptions="Center"
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1"/>
</Grid>
<CollectionView ItemsSource="{Binding NonLuBooks}"
SelectionMode="Single"
SelectionChangedCommand="{Binding StatutLectureVM.OnSelectionChangedCommand}"
SelectionChangedCommandParameter="{Binding StatutLectureVM.Manager.SelectedBook}"
IsGrouped="True"
SelectionChanged="OnSelectionChanged"
Grid.Row="2">
<CollectionView.GroupHeaderTemplate>
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
<VisualStateGroup>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Transparent" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Column="0"
Grid.RowSpan="5">
<Border Padding="-5,-5,-5,1"
Margin="10,0,0,0"
HeightRequest="100"
WidthRequest="62"
HorizontalOptions="Center"
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Border HorizontalOptions="Center"
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
</Border>
</Border>
<Image Source="bookmark_red.png"
HeightRequest="10"
WidthRequest="10"
Margin="0,97,20,0"
VerticalOptions="End"/>
</Grid>
<Label Text="{Binding Title}"
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>
<contentView:StarNotationView Grid.Column="2"
Grid.Row="4"/>
</Grid>
<contentView:SeparatorCutStartView/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource HeaderGray}, Dark={StaticResource Gray900}}"
Grid.Row="0">
Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Key}"
<Label Text="Terminés"
VerticalOptions="Center"
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1"/>
</Grid>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
<CollectionView ItemsSource="{Binding TermineBooks}"
SelectionMode="Single"
SelectionChanged="OnSelectionChanged"
Grid.Row="6">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:BookVM">
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
@ -89,7 +178,7 @@
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="{Binding ImageSmall}"
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
@ -105,11 +194,11 @@
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<Label Text="Author"
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding Status}"
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>

@ -1,28 +1,30 @@
using LivreLand.Model;
using LivreLand.ViewModel;
namespace LivreLand.View;
public partial class StatutLectureView : ContentPage
{
#region Properties
public StatutLectureVM StatutLectureVM { get; set; }
#endregion
public List<BookModel> NonLuBooks { get; set; } = new List<BookModel>()
{
new BookModel("La horde du contrevent","Alain Damasio","Non lu", 0),
};
#region Constructor
public List<BookModel> TermineBooks { get; set; } = new List<BookModel>()
{
new BookModel("La zone du dehors","Alain Damasio","Terminé", 0),
new BookModel("L'équateur d'Einstein","Cixin Liu","Terminé", 0),
new BookModel("La forêt sombre","Cixin Liu","Terminé", 0),
new BookModel("Le problème à trois corps","Cixin Liu","Terminé", 0)
};
public StatutLectureView(StatutLectureVM statutLectureVM)
public StatutLectureView()
{
StatutLectureVM = statutLectureVM;
InitializeComponent();
BindingContext = this;
InitializeComponent();
}
#endregion
#region Methods
#endregion
void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView());
}
}

@ -3,18 +3,13 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:view="clr-namespace:LivreLand.View"
xmlns:contentView="clr-namespace:LivreLand.View.ContentViews"
xmlns:viewModel="clr-namespace:ViewModels;assembly=ViewModels"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="LivreLand.View.TousView"
Title="TousView">
<ContentPage.Behaviors>
<toolkit:EventToCommandBehavior Command="{Binding TousVM.Manager.GetBooksFromCollectionCommand}"/>
</ContentPage.Behaviors>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
@ -22,10 +17,8 @@
HeaderBackButtonText="Mes livres"
HeaderPlusButtonVisible="True"
HeaderSwitchButtonVisible="True"
ButtonPlusTappedCommand="{Binding TousVM.Navigator.PopupHomePlusNavigationCommand}"
ButtonBackTappedCommand="{Binding TousVM.Navigator.PopupBackButtonNavigationCommand}"
Grid.Row="0"/>
<ScrollView Grid.Row="1">
<ScrollView Grid.Row="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
@ -36,15 +29,6 @@
<RowDefinition Height="10"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<CollectionView ItemsSource="{Binding TousVM.Manager.GroupedBooks}"
SelectedItem="{Binding TousVM.Manager.SelectedBook}"
SelectionMode="Single"
SelectionChangedCommand="{Binding TousVM.OnSelectionChangedCommand}"
SelectionChangedCommandParameter="{Binding TousVM.Manager.SelectedBook}"
IsGrouped="True"
Grid.Row="2">
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource HeaderGray}, Dark={StaticResource Gray900}}"
Grid.Row="0">
<Grid.ColumnDefinitions>
@ -52,15 +36,18 @@
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Key}"
<Label Text="Alain Damasio"
VerticalOptions="Center"
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1"/>
</Grid>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
<CollectionView ItemsSource="{Binding DamasioBooks}"
SelectionMode="Single"
SelectionChanged="OnSelectionChanged"
Grid.Row="2">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:BookVM">
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
@ -99,7 +86,7 @@
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="{Binding ImageSmall}"
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
@ -115,21 +102,11 @@
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<CollectionView ItemsSource="{Binding Authors}"
Grid.Column="2"
Grid.Row="1">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewModel:AuthorVM">
<Label Text="{Binding Name}"
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Margin="0,0,5,0"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Label Text="{Binding Status}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>
@ -141,44 +118,95 @@
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Grid Grid.Row="6">
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource HeaderGray}, Dark={StaticResource Gray900}}"
Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ImageButton Source="chevron_right.png"
Rotation="180"
Command="{Binding TousVM.Manager.PreviousCommand}"
Grid.Column="1">
<ImageButton.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"/>
</ImageButton.Behaviors>
</ImageButton>
<Label Style="{StaticResource MasterTitleBookText}"
VerticalOptions="FillAndExpand"
Grid.Column="3">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding TousVM.Manager.Index}"/>
<Span Text="/"/>
<Span Text="{Binding TousVM.Manager.NbPages}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<ImageButton Source="chevron_right.png"
Command="{Binding TousVM.Manager.NextCommand}"
Grid.Column="5">
<ImageButton.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}"/>
</ImageButton.Behaviors>
</ImageButton>
<Label Text="Cixin Liu"
VerticalOptions="Center"
Style="{StaticResource HeaderCollectionViewText}"
Grid.Column="1"/>
</Grid>
<CollectionView ItemsSource="{Binding LiuBooks}"
SelectionMode="Single"
SelectionChanged="OnSelectionChanged"
Grid.Row="6">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout Margin="10"
Spacing="20">
<VisualStateManager.VisualStateGroups x:Name="SelectionStates">
<VisualStateGroup>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Transparent" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Column="0"
Grid.RowSpan="5">
<Border Padding="-5,-5,-5,1"
Margin="10,0,0,0"
HeightRequest="100"
WidthRequest="62"
HorizontalOptions="Center"
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Border HorizontalOptions="Center"
Stroke="{StaticResource Gray}"
StrokeShape="RoundRectangle 3"
StrokeThickness="3">
<Image Source="couverture_la_horde_du_contrevent.png"
Aspect="AspectFill"
Grid.Column="0"
Grid.RowSpan="5"/>
</Border>
</Border>
<Image Source="bookmark_red.png"
HeightRequest="10"
WidthRequest="10"
Margin="0,97,20,0"
VerticalOptions="End"/>
</Grid>
<Label Text="{Binding Title}"
Style="{StaticResource MasterTitleBookText}"
Grid.Column="2"
Grid.Row="0"/>
<Label Text="{Binding Author}"
Style="{StaticResource MasterAuthorBookText}"
Grid.Column="2"
Grid.Row="1"/>
<Label Text="{Binding State}"
Style="{StaticResource MasterStateBookText}"
Grid.Column="2"
Grid.Row="2"/>
<contentView:StarNotationView Grid.Column="2"
Grid.Row="4"/>
</Grid>
<contentView:SeparatorCutStartView/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ScrollView>
<Grid HorizontalOptions="End"

@ -1,30 +1,30 @@
using LivreLand.Model;
using LivreLand.ViewModel;
using ViewModels;
namespace LivreLand.View;
public partial class TousView : ContentPage
{
public List<BookModel> DamasioBooks { get; set; } = new List<BookModel>()
{
new BookModel("La horde du contrevent","Alain Damasio","Non lu", 0),
new BookModel("La zone du dehors","Alain Damasio","Terminé", 0),
};
#region Properties
public TousVM TousVM { get; set; }
#endregion
#region Constructor
public List<BookModel> LiuBooks { get; set; } = new List<BookModel>()
{
new BookModel("L'équateur d'Einstein","Cixin Liu","Terminé", 0),
new BookModel("La forêt sombre","Cixin Liu","Terminé", 0),
new BookModel("Le problème à trois corps","Cixin Liu","Terminé", 0)
};
public TousView(TousVM tousVM)
public TousView()
{
TousVM = tousVM;
InitializeComponent();
BindingContext = this;
InitializeComponent();
}
#endregion
#region Methods
#endregion
void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView());
}
}

@ -1,49 +0,0 @@
using LivreLand.View;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class ALirePlusTardVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand OnSelectionChangedCommand { get; private set; }
#endregion
#region Constructor
public ALirePlusTardVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
OnSelectionChangedCommand = new RelayCommand<BookVM>((bookVM) => OnSelectionChanged(bookVM));
}
#endregion
#region Methods
private void OnSelectionChanged(BookVM bookVM)
{
if (bookVM != null)
{
var result = new DetailsLivreVM(Manager, Navigator, bookVM);
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView(result));
}
}
#endregion
}
}

@ -1,109 +0,0 @@
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class BibliothequeVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand AllBooksNavigateCommand { get; private set; }
public ICommand AllLoansBorrowingsNavigateCommand { get; private set; }
public ICommand AllFavorisBooksNavigateCommand { get; private set; }
public ICommand AllStatusBooksNavigateCommand { get; private set; }
public ICommand AllToReadBooksNavigateCommand { get; private set; }
public ICommand AllAuthorsNavigateCommand { get; private set; }
public ICommand AllDatesNavigateCommand { get; private set; }
public ICommand AllRatingsNavigateCommand { get; private set; }
#endregion
#region Constructor
public BibliothequeVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
AllBooksNavigateCommand = new RelayCommand(() => AllBooksNavigate());
AllLoansBorrowingsNavigateCommand = new RelayCommand(() => AllLoansBorrowingsNavigate());
AllFavorisBooksNavigateCommand = new RelayCommand(() => AllFavorisBooksNavigate());
AllStatusBooksNavigateCommand = new RelayCommand(() => AllStatusBooksNavigate());
AllToReadBooksNavigateCommand = new RelayCommand(() => AllToReadBooksNavigate());
AllAuthorsNavigateCommand = new RelayCommand(() => AllAuthorsNavigate());
AllDatesNavigateCommand = new RelayCommand(() => AllDatesNavigate());
AllRatingsNavigateCommand = new RelayCommand(() => AllRatingsNavigate());
}
#endregion
#region Methods
private void AllBooksNavigate()
{
Manager.GetBooksFromCollectionCommand.Execute(null);
Navigator.NavigationCommand.Execute("/tous");
}
private void AllLoansBorrowingsNavigate()
{
Manager.GetCurrentLoansCommand.Execute(null);
Manager.GetCurrentBorrowingsCommand.Execute(null);
Navigator.NavigationCommand.Execute("/pret");
}
private void AllFavorisBooksNavigate()
{
Manager.GetFavoriteBooksCommand.Execute(null);
Navigator.NavigationCommand.Execute("/favoris");
}
private void AllStatusBooksNavigate()
{
Manager.GetBooksFromCollectionCommand.Execute(null);
Navigator.NavigationCommand.Execute("/statut");
}
private void AllToReadBooksNavigate()
{
Manager.GetToBeReadBooksCommand.Execute(null);
Navigator.NavigationCommand.Execute("/later");
}
private void AllAuthorsNavigate()
{
Manager.GetAllAuthorsCommand.Execute(null);
Navigator.NavigationCommand.Execute("/auteur");
}
private void AllDatesNavigate()
{
Manager.GetAllPublishDatesCommand.Execute(null);
Navigator.NavigationCommand.Execute("/date");
}
private void AllRatingsNavigate()
{
Manager.GetAllRatingsCommand.Execute(null);
Navigator.NavigationCommand.Execute("/note");
}
#endregion
}
}

@ -1,79 +0,0 @@
using CommunityToolkit.Maui.Alerts;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class ContactsVM : BaseViewModel
{
#region Fields
private bool dataFormIsVisible = false;
#endregion
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public bool DataFormIsVisible
{
get { return dataFormIsVisible; }
set
{
if (dataFormIsVisible != value)
{
dataFormIsVisible = value;
OnPropertyChanged(nameof(DataFormIsVisible));
}
}
}
public ICommand AddContactDataFormCommand { get; private set; }
public ICommand BookLendedCommand { get; private set; }
#endregion
#region Constructor
public ContactsVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
AddContactDataFormCommand = new RelayCommand(() => AddContactDataForm());
BookLendedCommand = new RelayCommand<ContactVM>((contactVM) => BookLended(contactVM));
}
#endregion
#region Methods
private void AddContactDataForm()
{
DataFormIsVisible = true;
}
private async Task BookLended(ContactVM contactVM)
{
Manager.LendBookCommand.Execute(contactVM);
var toast = Toast.Make("Livre prêté !", CommunityToolkit.Maui.Core.ToastDuration.Short);
await toast.Show();
Manager.GetCurrentLoansCommand.Execute(null);
Manager.GetCurrentBorrowingsCommand.Execute(null);
Navigator.NavigationCommand.Execute("/pret");
}
#endregion
}
}

@ -1,182 +0,0 @@
using CommunityToolkit.Maui.Alerts;
using Model;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class DetailsLivreVM : BaseViewModel
{
#region Fields
private bool isPickerVisible = false;
private string addFavorisButtonText;
#endregion
#region Properties
public ManagerVM Manager { get; private set; }
public NavigatorVM Navigator { get; private set; }
public BookVM Book { get; private set; }
public bool IsPickerVisible
{
get => isPickerVisible;
set
{
if (isPickerVisible != value)
{
isPickerVisible = value;
OnPropertyChanged(nameof(IsPickerVisible));
}
}
}
public string AddFavorisButtonText
{
get
{
Manager.GetFavoriteBooksCommand.Execute(null);
if (Manager.AllFavoriteBooks.Any(favoriteBook => favoriteBook.Id == Book.Id))
{
return addFavorisButtonText = "Supprimer des favoris";
}
else
{
return addFavorisButtonText = "Ajouter aux favoris";
}
}
set
{
if (addFavorisButtonText != value)
{
addFavorisButtonText = value;
OnPropertyChanged(nameof(AddFavorisButtonText));
}
}
}
public ICommand BackButtonCommand { get; private set; }
public ICommand ShowPickerCommand { get; private set; }
public ICommand AddRemoveBookToFavoritesCommand { get; private set; }
public ICommand AddBookToReadListCommand { get; private set; }
public ICommand LoanBookCommand { get; private set; }
public ICommand RemoveBookCommand { get; private set; }
public ICommand OpenInfoCommand { get; private set; }
#endregion
#region Constructor
public DetailsLivreVM(ManagerVM managerVM, NavigatorVM navigatorVM, BookVM bookVM)
{
Manager = managerVM;
Navigator = navigatorVM;
Book = bookVM;
BackButtonCommand = new RelayCommand(() => BackButton());
ShowPickerCommand = new RelayCommand(() => ShowPicker());
AddRemoveBookToFavoritesCommand = new RelayCommand<BookVM>((bookVM) => AddRemoveBookToFavorites(bookVM));
AddBookToReadListCommand = new RelayCommand<BookVM>((bookVM) => AddBookToReadList(bookVM));
LoanBookCommand = new RelayCommand<BookVM>((bookVM) => LoanBook(bookVM));
RemoveBookCommand = new RelayCommand<BookVM>((bookVM) => RemoveBook(bookVM));
OpenInfoCommand = new RelayCommand(() => OpenInfo());
}
#endregion
#region Methods
private void BackButton()
{
Navigator.PopupBackButtonNavigationCommand.Execute(null);
}
private void ShowPicker()
{
Manager.GetAllStatusCommand.Execute(null);
Manager.SelectedStatus = Book.Status;
IsPickerVisible = true;
}
private async Task AddRemoveBookToFavorites(BookVM bookVM)
{
Manager.CheckBookIsFavoriteCommand.Execute(bookVM);
if (Manager.IsFavorite == false)
{
Manager.AddToFavoritesCommand.Execute(bookVM);
AddFavorisButtonText = "Supprimer des favoris";
OnPropertyChanged(nameof(AddFavorisButtonText));
var toast = Toast.Make("Livre ajouté aux favoris !", CommunityToolkit.Maui.Core.ToastDuration.Short);
await toast.Show();
Manager.GetFavoriteBooksCommand.Execute(null);
Navigator.NavigationCommand.Execute("/favoris");
}
else
{
Manager.RemoveFromFavoritesCommand.Execute(bookVM);
AddFavorisButtonText = "Ajouter aux favoris";
OnPropertyChanged(nameof(AddFavorisButtonText));
var toast = Toast.Make("Livre supprimé des favoris !", CommunityToolkit.Maui.Core.ToastDuration.Short);
await toast.Show();
Manager.GetFavoriteBooksCommand.Execute(null);
Navigator.NavigationCommand.Execute("/favoris");
}
}
private async Task AddBookToReadList(BookVM bookVM)
{
Manager.UpdateToBeReadBookCommand.Execute(bookVM);
var toast = Toast.Make("Livre ajouté à la liste À lire plus tard !", CommunityToolkit.Maui.Core.ToastDuration.Short);
await toast.Show();
Manager.GetToBeReadBooksCommand.Execute(null);
Navigator.NavigationCommand.Execute("/later");
}
private void LoanBook(BookVM bookVM)
{
Manager.SelectedBook = bookVM;
Manager.GetContactsCommand.Execute(null);
Navigator.NavigationCommand.Execute("contacts");
}
private async Task RemoveBook(BookVM bookVM)
{
Manager.RemoveBookCommand.Execute(bookVM);
var toast = Toast.Make("Livre supprimé !", CommunityToolkit.Maui.Core.ToastDuration.Short);
await toast.Show();
Navigator.PopupBackButtonNavigationCommand.Execute(null);
}
private async Task OpenInfo()
{
var isbn = Manager.SelectedBook.ISBN13;
string url = "https://openlibrary.org/isbn/" + isbn;
await Launcher.OpenAsync(url);
}
#endregion
}
}

@ -1,211 +0,0 @@
using LivreLand.View;
using Model;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class EmpruntsPretsVM : BaseViewModel
{
#region Fields
private Color pretButtonBackgroundColor = Colors.White;
private bool pretButtonIsEnabled = true;
private Color empruntButtonBackgroundColor = Colors.Transparent;
private bool empruntButtonIsEnabled = false;
private bool pretCollectionIsVisible = true;
private bool empruntCollectionIsVisible = false;
#endregion
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public Color PretButtonBackgroundColor
{
get { return pretButtonBackgroundColor; }
set
{
if (pretButtonBackgroundColor != value)
{
pretButtonBackgroundColor = value;
OnPropertyChanged(nameof(PretButtonBackgroundColor));
}
}
}
public bool PretButtonIsEnabled
{
get { return pretButtonIsEnabled; }
set
{
if (pretButtonIsEnabled != value)
{
pretButtonIsEnabled = value;
OnPropertyChanged(nameof(PretButtonIsEnabled));
}
}
}
public Color EmpruntButtonBackgroundColor
{
get { return empruntButtonBackgroundColor; }
set
{
if (empruntButtonBackgroundColor != value)
{
empruntButtonBackgroundColor = value;
OnPropertyChanged(nameof(EmpruntButtonBackgroundColor));
}
}
}
public bool EmpruntButtonIsEnabled
{
get { return empruntButtonIsEnabled; }
set
{
if (empruntButtonIsEnabled != value)
{
empruntButtonIsEnabled = value;
OnPropertyChanged(nameof(EmpruntButtonIsEnabled));
}
}
}
public bool EmpruntCollectionIsVisible
{
get { return empruntCollectionIsVisible; }
set
{
if (empruntCollectionIsVisible != value)
{
empruntCollectionIsVisible = value;
OnPropertyChanged(nameof(EmpruntCollectionIsVisible));
}
}
}
public bool PretCollectionIsVisible
{
get { return pretCollectionIsVisible; }
set
{
if (pretCollectionIsVisible != value)
{
pretCollectionIsVisible = value;
OnPropertyChanged(nameof(PretCollectionIsVisible));
}
}
}
public ICommand OnSelectionLoanChangedCommand { get; private set; }
public ICommand OnSelectionBorrowingChangedCommand { get; private set; }
public ICommand PretsButtonCommand { get; private set; }
public ICommand EmpruntsButtonCommand { get; private set; }
#endregion
#region Constructor
public EmpruntsPretsVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
OnSelectionLoanChangedCommand = new RelayCommand<LoanVM>((loanVM) => OnSelectionLoanChanged(loanVM));
OnSelectionBorrowingChangedCommand = new RelayCommand<BorrowingVM>((borrowingVM) => OnSelectionBorrowingChanged(borrowingVM));
PretsButtonCommand = new RelayCommand(() => PretsButtonClicked());
EmpruntsButtonCommand = new RelayCommand(() => EmpruntsButtonClicked());
}
#endregion
#region Methods
private void OnSelectionLoanChanged(LoanVM loanVM)
{
if (loanVM != null)
{
foreach (var b in Manager.AllCurrentLoans)
{
if (b.Book.Id == loanVM.Book.Id)
{
var bookCorresponding = b.Book;
var result = new DetailsLivreVM(Manager, Navigator, bookCorresponding);
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView(result));
}
}
}
}
private void OnSelectionBorrowingChanged(BorrowingVM borrowingVM)
{
if (borrowingVM != null)
{
foreach (var b in Manager.AllCurrentBorrowings)
{
if (b.Book.Id == borrowingVM.Book.Id)
{
var bookCorresponding = b.Book;
var result = new DetailsLivreVM(Manager, Navigator, bookCorresponding);
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView(result));
}
}
}
}
public void PretsButtonClicked()
{
if (App.Current.PlatformAppTheme == AppTheme.Light)
{
PretButtonBackgroundColor = Colors.Transparent;
PretButtonIsEnabled = false;
EmpruntButtonBackgroundColor = Colors.White;
EmpruntButtonIsEnabled = true;
}
else
{
PretButtonBackgroundColor = Colors.Transparent;
PretButtonIsEnabled = false;
EmpruntButtonBackgroundColor = Colors.Black;
EmpruntButtonIsEnabled = true;
}
PretCollectionIsVisible = false;
EmpruntCollectionIsVisible = true;
}
public void EmpruntsButtonClicked()
{
if (App.Current.PlatformAppTheme == AppTheme.Light)
{
PretButtonBackgroundColor = Colors.White;
PretButtonIsEnabled = true;
EmpruntButtonBackgroundColor = Colors.Transparent;
EmpruntButtonIsEnabled = false;
}
else
{
PretButtonBackgroundColor = Colors.Black;
PretButtonIsEnabled = true;
EmpruntButtonBackgroundColor = Colors.Transparent;
EmpruntButtonIsEnabled = false;
}
PretCollectionIsVisible = true;
EmpruntCollectionIsVisible = false;
}
#endregion
}
}

@ -1,49 +0,0 @@
using LivreLand.View;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class FavorisVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand OnSelectionChangedCommand { get; private set; }
#endregion
#region Constructor
public FavorisVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
OnSelectionChangedCommand = new RelayCommand<BookVM>((bookVM) => OnSelectionChanged(bookVM));
}
#endregion
#region Methods
private void OnSelectionChanged(BookVM bookVM)
{
if (bookVM != null)
{
var result = new DetailsLivreVM(Manager, Navigator, bookVM);
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView(result));
}
}
#endregion
}
}

@ -1,45 +0,0 @@
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class FiltrageAuteurVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand NavigateAuthorPageCommand { get; private set; }
#endregion
#region Constructor
public FiltrageAuteurVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
NavigateAuthorPageCommand = new RelayCommand(() => NavigateAuthorPage());
}
#endregion
#region Methods
private void NavigateAuthorPage()
{
Manager.GetBooksByAuthorCommand.Execute(null);
Navigator.NavigationCommand.Execute("/tous");
}
#endregion
}
}

@ -1,45 +0,0 @@
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class FiltrageDateVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand NavigateDatePageCommand { get; private set; }
#endregion
#region Constructor
public FiltrageDateVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
NavigateDatePageCommand = new RelayCommand(() => NavigateDatePage());
}
#endregion
#region Methods
private void NavigateDatePage()
{
Manager.GetBooksByDateCommand.Execute(null);
Navigator.NavigationCommand.Execute("/tous");
}
#endregion
}
}

@ -1,45 +0,0 @@
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class FiltrageNoteVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand NavigateRatingPageCommand { get; private set; }
#endregion
#region Constructor
public FiltrageNoteVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
NavigateRatingPageCommand = new RelayCommand(() => NavigateRatingPage());
}
#endregion
#region Methods
private void NavigateRatingPage()
{
Manager.GetBooksByRatingCommand.Execute(null);
Navigator.NavigationCommand.Execute("/tous");
}
#endregion
}
}

@ -1,41 +0,0 @@
using CommunityToolkit.Maui.Views;
using LivreLand.View;
using LivreLand.View.ContentViews;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace LivreLand.ViewModel
{
public class NavigatorVM
{
#region Properties
public ICommand NavigationCommand { get; }
public ICommand PopupHomePlusNavigationCommand { get; }
public ICommand PopupISBNNavigationCommand { get; }
public ICommand PopupBackButtonNavigationCommand { get; }
#endregion
#region Constructor
public NavigatorVM()
{
NavigationCommand = new Command(async (target) => await Shell.Current.GoToAsync($"//library/{target}"));
PopupHomePlusNavigationCommand = new Command(() => App.Current.MainPage.ShowPopup(new PopupHomePlusButtonView(this)));
PopupISBNNavigationCommand = new Command(() => App.Current.MainPage.ShowPopup(new PopupISBNView(Application.Current.Handler.MauiContext.Services.GetService<PopupISBNVM>())));
PopupBackButtonNavigationCommand = new Command(() => App.Current.MainPage.Navigation.PopAsync());
}
#endregion
#region Methods
#endregion
}
}

@ -1,52 +0,0 @@
using CommunityToolkit.Maui.Alerts;
using Model;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class PopupISBNVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand AddBookCommand { get; private set; }
#endregion
#region Constructor
public PopupISBNVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
AddBookCommand = new RelayCommand<string>((text) => AddBook(text));
}
#endregion
#region Methods
private async Task AddBook(string entryText)
{
Manager.AddBookCommand.Execute(entryText);
var toast = Toast.Make("Livre ajouté !", CommunityToolkit.Maui.Core.ToastDuration.Short);
await toast.Show();
Manager.GetBooksFromCollectionCommand.Execute(null);
Navigator.NavigationCommand.Execute("/tous");
}
#endregion
}
}

@ -1,29 +0,0 @@
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LivreLand.ViewModel
{
public class PublishDateVM : BaseViewModel
{
#region Properties
public DateTime PublishDate { get; set; }
public int NbBooksWritten { get; set; }
#endregion
#region Constructor
public PublishDateVM()
{
}
#endregion
}
}

@ -1,183 +0,0 @@
using Camera.MAUI;
using CommunityToolkit.Maui.Alerts;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
using ZXing;
namespace LivreLand.ViewModel
{
public class ScanVM : BaseViewModel
{
#region Fields
private CameraView cameraView;
private CameraInfo camera = null;
private ObservableCollection<CameraInfo> cameras = new();
private Result[] result;
private string barcodeText = "ISBN";
private bool addIsVisible = false;
#endregion
#region Properties
public CameraView CameraView
{
get => cameraView;
set
{
if (cameraView != value)
{
cameraView = value;
OnPropertyChanged(nameof(CameraView));
}
}
}
public CameraInfo Camera
{
get => camera;
set
{
if (camera != value)
{
camera = value;
OnPropertyChanged(nameof(Camera));
}
}
}
public ObservableCollection<CameraInfo> Cameras
{
get => cameras;
set
{
if (cameras != value)
{
cameras = value;
OnPropertyChanged(nameof(Cameras));
}
}
}
public int CamerasCount
{
get => Cameras.Count();
set
{
if (value > 0)
{
Camera = Cameras.First();
}
}
}
public Result[] BarCodeResult
{
get => result;
set
{
if (result != value)
{
result = value;
OnPropertyChanged(nameof(BarCodeResult));
}
}
}
public string BarcodeText
{
get => barcodeText;
set
{
if (barcodeText != value)
{
barcodeText = value;
OnPropertyChanged(nameof(BarcodeText));
}
}
}
public bool AddIsVisible
{
get => addIsVisible;
set
{
if (addIsVisible != value)
{
addIsVisible = value;
OnPropertyChanged(nameof(AddIsVisible));
}
}
}
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand CamerasLoadCommand { get; private set; }
public ICommand BarcodeDetectCommand { get; private set; }
public ICommand AddBookISBNDetectedCommand { get; private set; }
#endregion
#region Constructor
public ScanVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
CamerasLoadCommand = new RelayCommand(() => CamerasLoad());
BarcodeDetectCommand = new RelayCommand(() => BarcodeDetect());
AddBookISBNDetectedCommand = new RelayCommand<string>((isbn) => AddBookISBNDetected(isbn));
}
#endregion
#region Methods
private async Task CamerasLoad()
{
if (Cameras.Count > 0)
{
Camera = Cameras.First();
MainThread.BeginInvokeOnMainThread(async () =>
{
await CameraView.StopCameraAsync();
await CameraView.StartCameraAsync();
});
}
}
private async Task BarcodeDetect()
{
MainThread.BeginInvokeOnMainThread(() =>
{
BarcodeText = BarCodeResult[0].Text;
AddIsVisible = true;
});
}
private async Task AddBookISBNDetected(string isbn)
{
Manager.AddBookCommand.Execute(isbn);
var toast = Toast.Make("Livre ajouté !", CommunityToolkit.Maui.Core.ToastDuration.Short);
await toast.Show();
Manager.GetBooksFromCollectionCommand.Execute(null);
Navigator.NavigationCommand.Execute("/tous");
}
#endregion
}
}

@ -1,49 +0,0 @@
using LivreLand.View;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class StatutLectureVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand OnSelectionChangedCommand { get; private set; }
#endregion
#region Constructor
public StatutLectureVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
OnSelectionChangedCommand = new RelayCommand<BookVM>((bookVM) => OnSelectionChanged(bookVM));
}
#endregion
#region Methods
private void OnSelectionChanged(BookVM bookVM)
{
if (bookVM != null)
{
var result = new DetailsLivreVM(Manager, Navigator, bookVM);
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView(result));
}
}
#endregion
}
}

@ -1,49 +0,0 @@
using LivreLand.View;
using PersonalMVVMToolkit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using ViewModels;
namespace LivreLand.ViewModel
{
public class TousVM : BaseViewModel
{
#region Properties
public NavigatorVM Navigator { get; private set; }
public ManagerVM Manager { get; private set; }
public ICommand OnSelectionChangedCommand { get; private set; }
#endregion
#region Constructor
public TousVM(NavigatorVM navigatorVM, ManagerVM managerVM)
{
Navigator = navigatorVM;
Manager = managerVM;
OnSelectionChangedCommand = new RelayCommand<BookVM>((bookVM) => OnSelectionChanged(bookVM));
}
#endregion
#region Methods
private void OnSelectionChanged(BookVM bookVM)
{
if (bookVM != null)
{
var result = new DetailsLivreVM(Manager, Navigator, bookVM);
App.Current.MainPage.Navigation.PushAsync(new DetailsLivreView(result));
}
}
#endregion
}
}

@ -1,30 +0,0 @@
namespace Model
{
public class Author : IEquatable<Author>
{
public string Id { get; set; }
public string Name { get; set; }
public string ImageSmall => $"https://covers.openlibrary.org/a/olid/{Id.Substring(Id.LastIndexOf("/"))}-S.jpg";
public string ImageMedium => $"https://covers.openlibrary.org/a/olid/{Id.Substring(Id.LastIndexOf("/"))}-M.jpg";
public string ImageLarge => $"https://covers.openlibrary.org/a/olid/{Id.Substring(Id.LastIndexOf("/"))}-L.jpg";
public string Bio { get; set; }
public List<string> AlternateNames { get; set; } = new List<string>();
public List<Link> Links { get; set; }
public DateTime? BirthDate { get; set; }
public DateTime? DeathDate { get; set; }
public bool Equals(Author? other)
=> Id == other.Id;
public override bool Equals(object? obj)
{
if (ReferenceEquals(obj, null)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
return Equals(obj as Author);
}
public override int GetHashCode()
=> Id.GetHashCode();
}
}

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Book : IEquatable<Book>
{
public string Id { get; set; }
public string Title { get; set; }
public List<string> Publishers { get; set; } = new List<string>();
public DateTime PublishDate { get; set; }
public string ISBN13 { get; set; }
public List<string> Series { get; set; } = new List<string>();
public int NbPages { get; set; }
public string Format { get; set; }
public Languages Language { get; set; }
public List<Contributor> Contributors { get; set; }
public string ImageSmall => $"https://covers.openlibrary.org/b/isbn/{ISBN13}-S.jpg";
public string ImageMedium => $"https://covers.openlibrary.org/b/isbn/{ISBN13}-M.jpg";
public string ImageLarge => $"https://covers.openlibrary.org/b/isbn/{ISBN13}-L.jpg";
public List<Work> Works { get; set; } = new List<Work>();
public List<Author> Authors { get; set; } = new List<Author>();
public Status Status { get; set; }
public List<string> UserTags { get; set; } = new List<string>();
public float? UserRating { get; set; }
public string UserNote { get; set; }
public bool Equals(Book? other)
=> Id == other.Id;
public override bool Equals(object? obj)
{
if (ReferenceEquals(obj, null)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
return Equals(obj as Book);
}
public override int GetHashCode()
=> Id.GetHashCode();
}
}

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Borrowing : IEquatable<Borrowing>
{
public string Id { get; set; }
public Book Book { get; set; }
public Contact Owner { get; set; }
public DateTime BorrowedAt { get; set; }
public DateTime? ReturnedAt { get; set; }
public bool Equals(Borrowing? other)
=> Id == other.Id;
public override bool Equals(object? obj)
{
if (ReferenceEquals(obj, null)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
return Equals(obj as Borrowing);
}
public override int GetHashCode()
=> Id.GetHashCode();
}
}

@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Contact : IEquatable<Contact>
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Equals(Contact? other)
=> Id == other.Id;
public override bool Equals(object? obj)
{
if (ReferenceEquals(obj, null)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
return Equals(obj as Contact);
}
public override int GetHashCode()
=> Id.GetHashCode();
}
}

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Contributor
{
public string Name { get; set; }
public string Role { get; set; }
}
}

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public interface ILibraryManager
{
Task<Book> GetBookById(string id);
Task<Book> GetBookByISBN(string isbn);
Task<Tuple<long, IEnumerable<Book>>> GetBooksByTitle(string title, int index, int count, string sort = "");
Task<Tuple<long, IEnumerable<Book>>> GetBooksByAuthorId(string authorId, int index, int count, string sort = "");
Task<Tuple<long, IEnumerable<Book>>> GetBooksByAuthor(string author, int index, int count, string sort = "");
Task<Author> GetAuthorById(string id);
Task<Tuple<long, IEnumerable<Author>>> GetAuthorsByName(string substring, int index, int count, string sort = "");
}
}

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public interface IUserLibraryManager : ILibraryManager
{
Task<Tuple<long, IEnumerable<Book>>> GetBooksFromCollection(int index, int count, string sort = "");
Task<Book> AddBook(Book book);
Task<Book> AddBook(string id);
Task<Book> AddBookByIsbn(string isbn);
Task<bool> RemoveBook(Book book);
Task<bool> RemoveBook(string id);
Task<bool> RemoveBookByIsbn(string isbn);
Task<bool> AddToFavorites(Book book);
Task<bool> AddToFavorites(string bookId);
Task<bool> RemoveFromFavorites(Book book);
Task<bool> RemoveFromFavorites(string bookId);
Task<Tuple<long, IEnumerable<Book>>> GetFavoritesBooks(int index, int count);
Task<Book> UpdateBook(Book updatedBook);
Task<Contact> AddContact(Contact contact);
Task<bool> RemoveContact(Contact contact);
Task<bool> LendBook(Book book, Contact contact, DateTime? loanDate);
Task<bool> GetBackBook(Book book, DateTime? returnedDate);
Task<bool> BorrowBook(Book book, Contact owner, DateTime? borrowedDate);
Task<bool> GiveBackBook(Book book, DateTime? returnedDate);
Task<Tuple<long, IEnumerable<Loan>>> GetCurrentLoans(int index, int count);
Task<Tuple<long, IEnumerable<Loan>>> GetPastLoans(int index, int count);
Task<Tuple<long, IEnumerable<Borrowing>>> GetCurrentBorrowings(int index, int count);
Task<Tuple<long, IEnumerable<Borrowing>>> GetPastBorrowings(int index, int count);
Task<Tuple<long, IEnumerable<Contact>>> GetContacts(int index, int count);
}
}

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public enum Languages
{
Unknown,
French,
English
}
}

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Link
{
public string Title { get; set; }
public string Url { get; set; }
}
}

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Loan : IEquatable<Loan>
{
public string Id { get; set; }
public Book Book { get; set; }
public Contact Loaner { get; set; }
public DateTime LoanedAt { get; set; }
public DateTime? ReturnedAt { get; set; }
public bool Equals(Loan? other)
=> Id == other.Id;
public override bool Equals(object? obj)
{
if (ReferenceEquals(obj, null)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
return Equals(obj as Loan);
}
public override int GetHashCode()
=> Id.GetHashCode();
}
}

@ -1,135 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Manager
{
private ILibraryManager LibraryManager { get; set; }
private IUserLibraryManager UserLibraryManager { get; set; }
public Manager(ILibraryManager libMgr, IUserLibraryManager userLibMgr)
{
LibraryManager = libMgr;
UserLibraryManager = userLibMgr;
}
public async Task<Book> GetBookById(string id)
=> await LibraryManager.GetBookById(id);
public async Task<Book> GetBookByISBN(string isbn)
=> await LibraryManager.GetBookByISBN(isbn);
public async Task<(long count, IEnumerable<Book> books)> GetBooksByTitle(string title, int index, int count, string sort = "")
{
var result = await LibraryManager.GetBooksByTitle(title, index, count, sort);
return (result.Item1, result.Item2);
}
public async Task<(long count, IEnumerable<Book> books)> GetBooksByAuthorId(string authorId, int index, int count, string sort = "")
{
var result = await LibraryManager.GetBooksByAuthorId(authorId, index, count, sort);
return (result.Item1, result.Item2);
}
public async Task<(long count, IEnumerable<Book> books)> GetBooksByAuthor(string author, int index, int count, string sort = "")
{
var result = await LibraryManager.GetBooksByAuthor(author, index, count, sort);
return (result.Item1, result.Item2);
}
public async Task<Author> GetAuthorById(string id)
=> await LibraryManager.GetAuthorById(id);
public async Task<(long count, IEnumerable<Author> authors)> GetAuthorsByName(string substring, int index, int count, string sort = "")
{
var result = await LibraryManager.GetAuthorsByName(substring, index, count, sort);
return (result.Item1, result.Item2);
}
public Task<Book> AddBookToCollection(string id)
{
return UserLibraryManager.AddBook(id);
}
public async Task<Book> GetBookByIdFromCollection(string id)
=> await UserLibraryManager.GetBookById(id);
public Task<Book> UpdateBook(Book book)
{
return UserLibraryManager.UpdateBook(book);
}
public Task<bool> RemoveBook(Book book)
{
return UserLibraryManager.RemoveBook(book);
}
public Task<(long count, IEnumerable<Book> books)> GetBooksFromCollection(int index, int count, string sort = "")
{
var result = UserLibraryManager.GetBooksFromCollection(index, count, sort).Result;
return Task.FromResult((result.Item1, result.Item2));
}
public Task<(long count, IEnumerable<Book> books)> GetFavoritesBooks(int index, int count)
{
var result = UserLibraryManager.GetFavoritesBooks(index, count).Result;
return Task.FromResult((result.Item1, result.Item2));
}
public Task<bool> AddToFavorites(string id)
{
return UserLibraryManager.AddToFavorites(id);
}
public Task<bool> RemoveFromFavorites(string id)
{
return UserLibraryManager.RemoveFromFavorites(id);
}
public Task<(long count, IEnumerable<Contact> contacts)> GetContacts(int index, int count)
{
var result = UserLibraryManager.GetContacts(index, count).Result;
return Task.FromResult((result.Item1, result.Item2));
}
public Task<Contact> AddContact(Contact contact)
{
var result = UserLibraryManager.AddContact(contact).Result;
return Task.FromResult(result);
}
public Task<(long count, IEnumerable<Loan> loans)> GetCurrentLoans(int index, int count)
{
var result = UserLibraryManager.GetCurrentLoans(index, count).Result;
return Task.FromResult((result.Item1, result.Item2));
}
public Task<(long count, IEnumerable<Loan> loans)> GetPastLoans(int index, int count)
{
var result = UserLibraryManager.GetPastLoans(index, count).Result;
return Task.FromResult((result.Item1, result.Item2));
}
public Task<(long count, IEnumerable<Borrowing> borrowings)> GetCurrentBorrowings(int index, int count)
{
var result = UserLibraryManager.GetCurrentBorrowings(index, count).Result;
return Task.FromResult((result.Item1, result.Item2));
}
public Task<(long count, IEnumerable<Borrowing> borrowings)> GetPastBorrowings(int index, int count)
{
var result = UserLibraryManager.GetPastBorrowings(index, count).Result;
return Task.FromResult((result.Item1, result.Item2));
}
public Task<bool> LendBook(Book book, Contact contact, DateTime? loanDate)
{
return UserLibraryManager.LendBook(book, contact, loanDate);
}
}
}

@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Ratings
{
public float Average { get; set; }
public int Count { get; set; }
}
}

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public enum Status
{
Unknown,
Finished,
Reading,
NotRead,
ToBeRead
}
}

@ -1,32 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class Work : IEquatable<Work>
{
public string Id { get; set; }
public string Description { get; set; }
public string Title { get; set; }
public List<string> Subjects { get; set; } = new List<string>();
public List<Author> Authors { get; set; } = new List<Author>();
public Ratings Ratings { get; set; }
public bool Equals(Work? other)
=> Id == other.Id;
public override bool Equals(object? obj)
{
if (ReferenceEquals(obj, null)) return false;
if (ReferenceEquals(this, obj)) return true;
if (GetType() != obj.GetType()) return false;
return Equals(obj as Work);
}
public override int GetHashCode()
=> Id.GetHashCode();
}
}

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PersonalMVVMToolkit
{
public class BaseViewModel<TModel> : ObservableObject
{
#region Fields
private TModel model;
#endregion
#region Properties
public TModel Model
{
get => model;
private set
{
SetProperty(ref model, value);
}
}
#endregion
#region Constructor
public BaseViewModel(TModel model)
{
Model = model;
}
public BaseViewModel() : this(default)
{ }
#endregion
}
public class BaseViewModel : ObservableObject { }
}

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace PersonalMVVMToolkit
{
public class ObservableObject : INotifyPropertyChanged
{
#region Properties
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string PropertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
protected virtual void SetProperty<T>(T member, T value, Action<T> action, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(member, value)) return;
action(value);
OnPropertyChanged(propertyName);
}
protected virtual void SetProperty<T>(ref T member, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(member, value)) return;
member = value;
OnPropertyChanged(propertyName);
}
#endregion
}
}

@ -1,9 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -1,65 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace PersonalMVVMToolkit
{
public class RelayCommand<T> : ICommand
{
#region Fields
private readonly Action<T> execute;
private readonly Func<T, bool> canExecute;
#endregion
#region Properties
public event EventHandler? CanExecuteChanged;
public bool CanExecute(object? parameter)
{
T param = (T)parameter;
return canExecute(param);
}
public void Execute(object? parameter)
{
T param = (T)parameter;
execute(param);
}
public void RefreshCommand()
=> CanExecuteChanged?.Invoke(this, EventArgs.Empty);
#endregion
#region Constructor
public RelayCommand(Action<T> execute, Func<T,bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute ?? (t => true);
}
#endregion
}
public class RelayCommand : RelayCommand<object>
{
#region Constructor
public RelayCommand(Action execute, Func<bool> canExecute = null) : base(new Action<object> (o => execute()), canExecute != null ? new Func<object, bool>(o => canExecute()) : null)
{
}
#endregion
}
}

@ -1,426 +0,0 @@
# **LIVRE LAND**
## Bonjour et bienvenue sur le dépôt du projet LIVRE LAND ! 👋
*******
### Sommaire
1. [Accessibilité](#acces)
2. [Progression](#progression)
3. [Présentation du projet](#presentation)
4. [Architecture](#architecture)
5. [Contenu](#contenu)
6. [Auteurs](#auteurs)
*******
<div id='acces'/>
Pour accéder au code de l'application, vous pouvez cloner la branche `master` du dépôt Code#0 et ouvrir celle-ci dans `Microsoft Visual Studio` par exemple.
Disponible sur :
![](https://img.shields.io/badge/Android-3DDC84?style=for-the-badge&logo=android&logoColor=white)
![](https://img.shields.io/badge/iOS-000000?style=for-the-badge&logo=ios&logoColor=white)
> **Warning**: L'application est fonctionnelle sous Windows et Android mais n'a pas été testée sous IOS.
- Dans la branche **Master**, vous retrouverez l'intégralité de l'application avec les fonctionnalités du `TP2` ainsi que le scan de code-barres.
- Dans la branche **TP3**, vous retrouverez l'implémentation du `MVVM Community Toolkit` dans notre application.
*******
<div id='progression'/>
## 🚧 __EN PROGRESSION__
### Étape 1 : Développement des vues en XAML
- Intégralité des pages proposées sur la page d'accueil développées
- Mode clair & Mode sombre disponibles (pas très esthétique)
- Utilisable en mode portrait ou mode paysage
- Exploitation des Styles et des Content View réutilisables
- Mise à disposition de quelques données dans un Stub pour la présentation des vues
- View Model non utilisés et fonctionnalités pas toutes mises en place (seulement les vues)
- Navigation généralement utilisable mais pas parfaitement codée
---
### Étape 2 : Personnal MVVM Toolkit
La création de ce `Toolkit Personnel` a pour but de faciliter le développement de l'application en fournissant un ensemble de fonctionnalités et de composants réutilisables. De plus, à l'aide d'une classe comme `RelayCommand`, notre objectif est de ne pas inclure dans nos ViewModels une dépendance avec les Commands de .NET MAUI.
Nous pouvons représenter la structure de notre toolkit avec le diagramme suivant :
```mermaid
classDiagram
direction LR
class INotifyPropertyChanged {
<<interface>>
}
class ObservableObject{
+PropertyChanged: event PropertyChangedEventHandler?;
#OnPropertyChanged (string PropertyName = null) : void
#SetProperty<T> (T member, T value, Action<T> action, string propertyName = null) : void
#SetProperty<T> (ref T member, T value, string propertyName = null) : void
}
class BaseViewModel{
+Model: TModel;
-model: TModel;
+BaseViewModel(TModel model)
+BaseViewModel() : this(default)
}
class ICommand{
<<interface>>
}
class RelayCommand{
+CanExecuteChanged: event EventHandler?;
+CanExecute (object? parameter) : bool
+Execute (object? parameter) : void
+RefreshCommand() : void
}
ObservableObject ..|> INotifyPropertyChanged
BaseViewModel --|> ObservableObject
RelayCommand ..|> ICommand
```
Cette structure est une version remplaçant pour le moment le `Community Toolkit` mis en place par Microsoft qui permet aussi de supprimer beaucoup de code inutile en remplaçant celui-ci par des annotations et des classes partielles.
---
### Étape 3 : MVVM
Nous utilisons au sein de notre projet le **patron d'architecture MVVM** avec les ViewModels Wrapping et Applicatives.
Nous retrouvons donc les 3 grandes parties du patron :
- **Model** :
Le `Model` représente la `logique métier`. Il est écrit en `C#` et est adpaté pour diifférentes applications.
- **View** :
Les `Vues` sont écrites en `XAML` et représentent l'interface utilisateur avec les vues de l'application. Le `Data Binding` est utilisé entre les propriétés du XAML et celles des ViewModels. Enfin, des évènements sont déclenchés à partir de certains composants des vues.
- **ViewModel** :
Les `ViewModels` sont écrits en `C#` et sont divisables en deux grandes catégories :
* Les **Wrapping ViewModel** encapsulent les données du modèle et exposent des propriétés et des commandes nécessaires à la vue pour interagir avec le modèle.
* Les **Applicative ViewModel** peuvent inclure une logique métier spécifique et des propriétés calculées, elles peuvent également exposer des commandes pour effectuer des actions spécifiques liées à la vue.
Le schéma suivant montre bien les relations entre les grandes parties du `patron MVVM` :
![Schema_MVVM](documentation/schema_mvvm.png)
Le **diagramme de classes** pouvant être extrèmement grand à cause des multiples classes au sein de notre projet, j'ai décidé de représenter une partie de celui-ci qui pourrait se répéter pour toutes les autres parties. L'objectif principal étant de comprendre comment fonctionne le **modèle MVVM** et comment les classes intéragissent entre elles, j'ai choisi de faire mon exemple avec la partie des livres qui est la plus générale du sujet.
```mermaid
classDiagram
class Book {
Id: string
Title: string
Publishers: List<string>
PublishDate: DateTime
ISBN13: string
Series: List<string>
NbPages: int
Format: string
Language: Languages
Contributors: List<Contributor>
ImageSmall: string
ImageMedium: string
ImageLarge: string
Works: List<Work>
Authors: List<Author>
Status: Status
UserTags: List<string>
UserRating: float?
UserNote: string
Equals(other: Book): bool
GetHashCode(): int
}
class DetailsLivreView {
DetailsLivreVM: DetailsLivreVM
}
class DetailsLivreVM {
isPickerVisible: bool
addFavorisButtonText: string
Manager: ManagerVM
Navigator: NavigatorVM
Book: BookVM
IsPickerVisible: bool
AddFavorisButtonText: string
BackButtonCommand: ICommand
ShowPickerCommand: ICommand
AddRemoveBookToFavoritesCommand: ICommand
AddBookToReadListCommand: ICommand
LoanBookCommand: ICommand
RemoveBookCommand: ICommand
OpenInfoCommand: ICommand
BackButton()
ShowPicker()
AddRemoveBookToFavorites(bookVM: BookVM)
AddBookToReadList(bookVM: BookVM)
LoanBook(bookVM: BookVM)
RemoveBook(bookVM: BookVM)
OpenInfo()
}
class BookVM {
Id: string
ISBN13: string
Title: string
Publishers: List<string>
PublishDate: DateTime
Works: List<WorkVM>
WorkDescription: string
Authors: List<AuthorVM>
Author: string
Status: Status
NbPages: int
Language: Languages
ImageSmall: string
UserRating: float?
}
DetailsLivreView --> DetailsLivreVM
DetailsLivreVM --> BookVM
DetailsLivreVM --> ManagerVM
DetailsLivreVM --> NavigatorVM
BookVM --> Book
BookVM --> WorkVM
BookVM --> AuthorVM
```
*******
<div id='presentation'/>
## **Présentation**
LivreLand : votre bibliothèque connectée !
Retrouver tous vos livres préférés en un clic.
*******
<div id='contenu'/>
## Fonctionnalités
**TP2 - Base** :
- [x] Page d'accueil
- [x] Affichage des livres de l'utilisateur : afficher tous les livres de l'utilisateur dans la vue BooksPage et permettre la sélection d'un livre et la navigation vers la page BookPage
* seule la note n'est pas encore affichée sous la forme d'étoiles (commencée dans `star-notation-22-10`)
- [x] Filtrage par auteur et par date de publication : afficher dans la vue de filtrage (FilterPage)
**TP2 - Ajouts** :
- [x] Changer le statut de lecture d'un livre
- [x] Ajouter un livre aux favoris
- [x] Filtrer les livres par Auteur, Date de publication, Note
* le filtrage fonctionne, au deuxième clique sur une date par exemple une fois une première date visitée, je remarque des soucis avec de temps à autre une exception
- [x] Ajouter un livre à sa collection en saisissant l'ISBN
- [x] Supprimer un livre
- [x] Prêter un livre (et ajouter un contact si besoin)
* la page avec les contacts n'est pas esthétiquement très réussie
- [x] Consulter la liste des livres prêtés
* j'ai fait le choix de n'afficher que les livres _actuellement_ prêtés ou empruntés
_Erreurs rencontrées_ :
* L'ajout en favoris fonctionne, cependant il m'ait arrivé lorque je choisissais à partir de la page BooksPage d'ajouter un livre qui ne se trouve pas sur la première page, que celui-ci supprime souvent tous les livres déjà en favoris.
* J'ai également eu à certains moments des problèmes avec l'accession à la page de détails et une double page qui s'ouvrait; dans ce cas je relance généralement l'application.
**TP3** :
- [X] Modifier l'intégralité du code pour que l'application utilise désormais le MVVM Community Toolkit à la place du toolkit personnel
* lecture de la documentation et implémentation dans la branche `TP3` (à affiner pour respecter parfaitement le Toolkit)
**TP 4** :
Ajouter les vues et les VM nécessaires pour permettre :
- [x] Le scan de code-barres afin d'ajouter de nouveaux livres
* le scan de code-barres fonctionne mais le livre n'est pas encore directement ajouté dans la liste (affichage de l'isbn dans en bas de page & du bouton d'ajout du livre)
- [X] La recherche en ligne (via le web service)
* il est possible d'accéder à la page d'un livre en ligne en cliquant dans la partie "Infos en ligne" de la page Détails
*******
<div id='architecture'/>
## Architectures du modèle et des services fournises
Dans cette partie, vous retrouverez dans un premier temps deux diagrammes mis à disposition dans le sujet représentant d'abord le `Modèle` puis les `Services et Interfaces` :
### Modèle
```mermaid
classDiagram
direction LR
class Book {
+Id : string
+Title : string
+Publishers : List~string~
+PublishDate : DateTime
+ISBN13 : string
+Series : List~string~
+NbPages : int
+Format : string
+ImageSmall : string
+ImageMedium : string
+ImageLarge : string
}
class Languages {
<<enum>>
Unknown,
French,
}
class Work {
+Id : string
+Description : string
+Title : string
+Subjects : List~string~
}
class Contributor {
+Name : string
+Role : string
}
class Author {
+Id : string
+Name : string
+ImageSmall : string
+ImageMedium : string
+ImageLarge : string
+Bio : string
+AlternateNames : List~string~
+BirthDate : DateTime?
+DeathDate : DateTime?
}
class Link {
+Title : string
+Url : string
}
class Ratings {
+Average : float
+Count : int
}
Book --> "1" Languages : Language
Book --> "*" Contributor : Contributors
Author --> "*" Link : Links
Work --> "*" Author : Authors
Work --> "1" Ratings : Ratings
Book --> "*" Author : Authors
Book --> "*" Work : Works
class Status {
<<enum>>
Unknown,
Finished,
Reading,
NotRead,
ToBeRead
}
class Contact{
+string Id;
+string FirstName;
+string LastName;
}
```
---
### Services et Interfaces
```mermaid
classDiagram
direction LR
Book --> "1" Languages : Language
Book --> "*" Contributor : Contributors
Author --> "*" Link : Links
Work --> "1" Ratings : Ratings
Work --> "*" Author : Authors
Book --> "*" Work : Works
Book --> "*" Author : Authors
class IUserLibraryManager {
<<interface>>
+AddBook(Book book) : Task<Book>
+AddBook(string id) : Task<Book>
+AddBookByIsbn(string isbn) : Task<Book>
+RemoveBook(Book book) : Task<bool>
+RemoveBook(string id) : Task<bool>
+RemoveBook(string id) : Task<bool>
+AddToFavorites(Book book) : Task<bool>
+AddToFavorites(string bookId) : Task<bool>
+RemoveFromFavorites(Book book) : Task<bool>
+RemoveFromFavorites(string bookId) : Task<bool>
+UpdateBook(Book updatedBook) : Task<Book>
+AddContact(Contact contact) : Task<Contact>
+RemoveContact(Contact contact) : Task<bool>
+LendBook(Book book, Contact contact, DateTime? loanDate) : Task<bool>
+GetBackBook(Book book, DateTime? returnedDate) : Task<bool>
+BorrowBook(Book book, Contact owner, DateTime? borrowedDate) : Task<bool>
+GiveBackBook(Book book, DateTime? returnedDate) : Task<bool>
+GetCurrentLoans(int index, int count)
+GetPastLoans(int index, int count)
+GetCurrentBorrowings(int index, int count)
+GetPastBorrowings(int index, int count)
+GetContacts(int index, int count)
}
class ILibraryManager {
<<interface>>
+GetBookById(string id)
+GetBookByIsbn(string isbn)
+GetBooksByTitle(string title, int index, int count, string sort)
+GetBooksByAuthorId(string authorId, int index, int count, string sort)
+GetBooksByAuthor(string author, int index, int count, string sort)
+GetAuthorById(string id)
+GetAuthorsByName(string substring, int index, int count, string sort)
}
class Status {
<<enum>>
}
IUserLibraryManager ..|> ILibraryManager
IUserLibraryManager ..> Status
IUserLibraryManager ..> Contact
IUserLibraryManager ..> Book
ILibraryManager ..> Book
ILibraryManager ..> Author
```
*******
## Ressources
- Temps
- 4 Septembre au 22 Octobre 2023
- Matériel
- Ordinateurs portables sous Windows
- Émulateur sous Visual Studio 2022
- Téléphone portable
- Langages utilisés
- ![](https://img.shields.io/badge/.NETMAUI-5C2D91?style=for-the-badge&logo=.net&logoColor=white)
- ![](https://img.shields.io/badge/C%23-239120?style=for-the-badge&logo=c-sharp&logoColor=white)
- ![](https://img.shields.io/static/v1?style=for-the-badge&message=XAML&color=0C54C2&logo=XAML&logoColor=FFFFFF&label=)
- Personnes
- 1 étudiant en BUT Informatique
*******
<div id='auteurs'/>
## Auteur
Étudiant 3ème Annnée - BUT Informatique - IUT Clermont Auvergne - 2023-2024
`BRODA Lou`

@ -1,51 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utils;
namespace Stub
{
static class EnumsMapper
{
public static EnumsMapper<Model.Languages, LibraryDTO.Languages> BiddingsMapper { get; }
= new EnumsMapper<Model.Languages, LibraryDTO.Languages>(
Tuple.Create(Model.Languages.Unknown, LibraryDTO.Languages.Unknown),
Tuple.Create(Model.Languages.French, LibraryDTO.Languages.French),
Tuple.Create(Model.Languages.English, LibraryDTO.Languages.English)
);
public static TModel ToModel<TModel, TDTO>(this TDTO dto) where TModel : Enum
where TDTO : Enum
{
foreach (var prop in typeof(EnumsMapper).GetProperties())
{
if (prop.PropertyType.Equals(typeof(EnumsMapper<TModel, TDTO>)))
{
return (prop.GetValue(null) as EnumsMapper<TModel, TDTO>).GetModel(dto);
}
}
return default(TModel);
}
public static Model.Languages ToModel(this LibraryDTO.Languages dto)
=> ToModel<Model.Languages, LibraryDTO.Languages>(dto);
public static TDTO ToDTO<TModel, TDTO>(this TModel model) where TModel : Enum
where TDTO : Enum
{
foreach (var prop in typeof(EnumsMapper).GetProperties())
{
if (prop.PropertyType.Equals(typeof(EnumsMapper<TModel, TDTO>)))
{
return (prop.GetValue(null) as EnumsMapper<TModel, TDTO>).GetEntity(model);
}
}
return default(TDTO);
}
public static LibraryDTO.Languages ToDTO(this Model.Languages model)
=> ToDTO<Model.Languages, LibraryDTO.Languages>(model);
}
}

@ -1,96 +0,0 @@
using LibraryDTO;
using Model;
using static Stub.Mapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Stub
{
public static class Extensions
{
public static Ratings ToPoco(this RatingsDTO dto)
=> new Ratings() { Average = dto.Average, Count = dto.Count };
public static IEnumerable<Ratings> ToPocos(this IEnumerable<RatingsDTO> dtos)
=> dtos.Select(dto => dto.ToPoco());
public static Contributor ToPoco(this ContributorDTO dto)
=> new Contributor { Name = dto.Name, Role = dto.Role };
public static IEnumerable<Contributor> ToPocos(this IEnumerable<ContributorDTO> dtos)
=> dtos.Select(dto => dto.ToPoco());
public static Link ToPoco(this LinkDTO dto)
=> new Link { Title = dto.Title, Url = dto.Url };
public static IEnumerable<Link> ToPocos(this IEnumerable<LinkDTO> dtos)
=> dtos.Select(dto => dto.ToPoco());
public static Author ToPoco(this AuthorDTO dto)
{
var result = AuthorsMapper.GetT(dto);
if (result == null)
{
result = new Author
{
AlternateNames = dto.AlternateNames,
Bio = dto.Bio,
BirthDate = dto.BirthDate,
DeathDate = dto.DeathDate,
Id = dto.Id,
Links = dto.Links.ToPocos().ToList(),
Name = dto.Name
};
}
return result;
}
public static IEnumerable<Author> ToPocos(this IEnumerable<AuthorDTO> dtos)
=> dtos.Select(dto => dto.ToPoco());
public static Work ToPoco(this WorkDTO dto)
{
var result = WorksMapper.GetT(dto);
if (result == null)
{
result = new Work
{
Authors = dto.Authors.ToPocos().ToList(),
Description = dto.Description,
Id = dto.Id,
Ratings = dto.Ratings.ToPoco(),
Subjects = dto.Subjects,
Title = dto.Title
};
}
return result;
}
public static IEnumerable<Work> ToPocos(this IEnumerable<WorkDTO> dtos)
=> dtos.Select(dto => dto.ToPoco());
public static Book ToPoco(this BookDTO dto)
{
var result = BooksMapper.GetT(dto);
if (result == null)
{
result = new Book
{
Authors = dto.Authors.ToPocos().ToList(),
Contributors = dto.Contributors.ToPocos().ToList(),
Format = dto.Format,
Id = dto.Id,
ISBN13 = dto.ISBN13,
Language = dto.Language.ToModel(),
NbPages = dto.NbPages,
PublishDate = dto.PublishDate,
Publishers = dto.Publishers,
Series = dto.Series,
Title = dto.Title,
Works = dto.Works.ToPocos().ToList()
};
}
return result;
}
public static IEnumerable<Book> ToPocos(this IEnumerable<BookDTO> dtos)
=> dtos.Select(dto => dto.ToPoco());
}
}

@ -1,25 +0,0 @@
using LibraryDTO;
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Utils;
namespace Stub
{
static class Mapper
{
internal static Mapper<Author, AuthorDTO> AuthorsMapper { get; } = new Mapper<Author, AuthorDTO>();
internal static Mapper<Work, WorkDTO> WorksMapper { get; } = new Mapper<Work, WorkDTO>();
internal static Mapper<Book, BookDTO> BooksMapper { get; } = new Mapper<Book, BookDTO>();
internal static void Reset()
{
AuthorsMapper.Reset();
WorksMapper.Reset();
BooksMapper.Reset();
}
}
}

@ -1,48 +0,0 @@
using Model;
namespace Stub
{
public class LibraryStub : ILibraryManager
{
private StubbedDTO.Stub StubDTO { get; set; } = new StubbedDTO.Stub();
public async Task<Author> GetAuthorById(string id)
{
return (await StubDTO.GetAuthorById(id)).ToPoco();
}
public async Task<Tuple<long, IEnumerable<Author>>> GetAuthorsByName(string substring, int index, int count, string sort = "")
{
var result = await StubDTO.GetAuthorsByName(substring, index, count, sort);
return Tuple.Create(result.Item1, result.Item2.ToPocos());
}
public async Task<Book> GetBookById(string id)
{
return (await StubDTO.GetBookById(id)).ToPoco();
}
public async Task<Book> GetBookByISBN(string isbn)
{
return (await StubDTO.GetBookByISBN(isbn)).ToPoco();
}
public async Task<Tuple<long, IEnumerable<Book>>> GetBooksByAuthor(string author, int index, int count, string sort = "")
{
var result = await StubDTO.GetBooksByAuthor(author, index, count, sort);
return Tuple.Create(result.Item1, result.Item2.ToPocos());
}
public async Task<Tuple<long, IEnumerable<Book>>> GetBooksByAuthorId(string authorId, int index, int count, string sort = "")
{
var result = await StubDTO.GetBooksByAuthor(authorId, index, count, sort);
return Tuple.Create(result.Item1, result.Item2.ToPocos());
}
public async Task<Tuple<long, IEnumerable<Book>>> GetBooksByTitle(string title, int index, int count, string sort = "")
{
var result = await StubDTO.GetBooksByTitle(title, index, count, sort);
return Tuple.Create(result.Item1, result.Item2.ToPocos());
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save