diff --git a/README.md b/README.md index b063b8e..f035280 100644 --- a/README.md +++ b/README.md @@ -63,12 +63,12 @@ After making changes to any entity you need to add a migration and update the da - Update the Roadmap - Git pull master - Open up *subtrack.maui.csproj* - - Set the value of application Id to `com.companyname.subtrack` + - Set the value of application Id to `com.code2gether.subtrack` - Set the value of application Title `subtrack` - Inside Visual Studio set build mode to **Release** - Build the project - Run the project -- The APK file should have been created at this location: *subtrack.MAUI\bin\Release\net6.0-android\com.companyname.subtrack-Signed.apk* +- The APK file should have been created at this location: *subtrack.MAUI\bin\Release\net6.0-android\com.code2gether.subtrack-Signed.apk* - Remove the changes that were made to the *.csproj* file - Upload the APK release to Github - The version should be prefixed with a **"v"** and suffix of (app stage which is currently alpha 2/9-2023) **"-alpha"** diff --git a/docs/MVP mockups.png b/docs/MVP mockups.png deleted file mode 100644 index fc4f193..0000000 Binary files a/docs/MVP mockups.png and /dev/null differ diff --git a/docs/mockups.drawio b/docs/mockups.drawio index fb0da00..4ce3fcb 100644 --- a/docs/mockups.drawio +++ b/docs/mockups.drawio @@ -1,6 +1,456 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -232,7 +682,7 @@ - + @@ -317,7 +767,7 @@ - + @@ -611,7 +1061,7 @@ - + diff --git a/docs/mockups.png b/docs/mockups.png index 4d6806e..62fe794 100644 Binary files a/docs/mockups.png and b/docs/mockups.png differ diff --git a/docs/roadmap.drawio b/docs/roadmap.drawio index e0dc4e7..20eb0a8 100644 --- a/docs/roadmap.drawio +++ b/docs/roadmap.drawio @@ -1,6 +1,6 @@ - + @@ -74,12 +74,12 @@ - + - - + + @@ -122,12 +122,12 @@ - + - - + + @@ -142,9 +142,21 @@ - + + + + + + + + + + + + + diff --git a/docs/roadmap.png b/docs/roadmap.png index 63ffc99..d3e742b 100644 Binary files a/docs/roadmap.png and b/docs/roadmap.png differ diff --git a/subtrack.DAL/Entities/Subscription.cs b/subtrack.DAL/Entities/Subscription.cs index c709733..d455214 100644 --- a/subtrack.DAL/Entities/Subscription.cs +++ b/subtrack.DAL/Entities/Subscription.cs @@ -26,6 +26,8 @@ public class Subscription : ICloneable [Range(1, int.MaxValue, ErrorMessage = "Interval has to be greater than 0")] public int BillingInterval { get; set; } + public string PrimaryColor { get; set; } + public object Clone() { return (Subscription)MemberwiseClone(); diff --git a/subtrack.DAL/Migrations/20230916005301_BackgroundColor.Designer.cs b/subtrack.DAL/Migrations/20230916005301_BackgroundColor.Designer.cs new file mode 100644 index 0000000..1572478 --- /dev/null +++ b/subtrack.DAL/Migrations/20230916005301_BackgroundColor.Designer.cs @@ -0,0 +1,101 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using subtrack.DAL; + +#nullable disable + +namespace subtrack.DAL.Migrations +{ + [DbContext(typeof(SubtrackDbContext))] + [Migration("20230916005301_BackgroundColor")] + partial class BackgroundColor + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.10"); + + modelBuilder.Entity("subtrack.DAL.Entities.SettingsBase", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("settings_type") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + + b.HasDiscriminator("settings_type").HasValue("SettingsBase"); + }); + + modelBuilder.Entity("subtrack.DAL.Entities.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BackgroundColor") + .IsRequired() + .HasColumnType("TEXT") + .HasDefaultValue("#282828"); + + b.Property("BillingInterval") + .HasColumnType("INTEGER") + .HasDefaultValue(1); + + b.Property("BillingOccurrence") + .HasColumnType("INTEGER") + .HasDefaultValue(1); + + b.Property("Cost") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("FirstPaymentDay") + .HasColumnType("INTEGER"); + + b.Property("IsAutoPaid") + .HasColumnType("INTEGER"); + + b.Property("LastPayment") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("subtrack.DAL.Entities.DateTimeSetting", b => + { + b.HasBaseType("subtrack.DAL.Entities.SettingsBase"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasDiscriminator().HasValue("DateTimeSetting"); + + b.HasData( + new + { + Id = "LastAutoPaymentTimeStamp" + }); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/subtrack.DAL/Migrations/20230916005301_BackgroundColor.cs b/subtrack.DAL/Migrations/20230916005301_BackgroundColor.cs new file mode 100644 index 0000000..64c57b1 --- /dev/null +++ b/subtrack.DAL/Migrations/20230916005301_BackgroundColor.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace subtrack.DAL.Migrations +{ + /// + public partial class BackgroundColor : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "BackgroundColor", + table: "Subscriptions", + type: "TEXT", + nullable: false, + defaultValue: "#282828"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "BackgroundColor", + table: "Subscriptions"); + } + } +} diff --git a/subtrack.DAL/Migrations/20230917120115_PrimaryColor.Designer.cs b/subtrack.DAL/Migrations/20230917120115_PrimaryColor.Designer.cs new file mode 100644 index 0000000..bc8a0b8 --- /dev/null +++ b/subtrack.DAL/Migrations/20230917120115_PrimaryColor.Designer.cs @@ -0,0 +1,101 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using subtrack.DAL; + +#nullable disable + +namespace subtrack.DAL.Migrations +{ + [DbContext(typeof(SubtrackDbContext))] + [Migration("20230917120115_PrimaryColor")] + partial class PrimaryColor + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.10"); + + modelBuilder.Entity("subtrack.DAL.Entities.SettingsBase", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("settings_type") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + + b.HasDiscriminator("settings_type").HasValue("SettingsBase"); + }); + + modelBuilder.Entity("subtrack.DAL.Entities.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BillingInterval") + .HasColumnType("INTEGER") + .HasDefaultValue(1); + + b.Property("BillingOccurrence") + .HasColumnType("INTEGER") + .HasDefaultValue(1); + + b.Property("Cost") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("FirstPaymentDay") + .HasColumnType("INTEGER"); + + b.Property("IsAutoPaid") + .HasColumnType("INTEGER"); + + b.Property("LastPayment") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PrimaryColor") + .IsRequired() + .HasColumnType("TEXT") + .HasDefaultValue("#282828"); + + b.HasKey("Id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("subtrack.DAL.Entities.DateTimeSetting", b => + { + b.HasBaseType("subtrack.DAL.Entities.SettingsBase"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasDiscriminator().HasValue("DateTimeSetting"); + + b.HasData( + new + { + Id = "LastAutoPaymentTimeStamp" + }); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/subtrack.DAL/Migrations/20230917120115_PrimaryColor.cs b/subtrack.DAL/Migrations/20230917120115_PrimaryColor.cs new file mode 100644 index 0000000..1558067 --- /dev/null +++ b/subtrack.DAL/Migrations/20230917120115_PrimaryColor.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace subtrack.DAL.Migrations +{ + /// + public partial class PrimaryColor : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "BackgroundColor", + table: "Subscriptions", + newName: "PrimaryColor"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "PrimaryColor", + table: "Subscriptions", + newName: "BackgroundColor"); + } + } +} diff --git a/subtrack.DAL/Migrations/SubtrackDbContextModelSnapshot.cs b/subtrack.DAL/Migrations/SubtrackDbContextModelSnapshot.cs index debab0c..db21001 100644 --- a/subtrack.DAL/Migrations/SubtrackDbContextModelSnapshot.cs +++ b/subtrack.DAL/Migrations/SubtrackDbContextModelSnapshot.cs @@ -40,12 +40,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER"); b.Property("BillingInterval") - .ValueGeneratedOnAdd() .HasColumnType("INTEGER") .HasDefaultValue(1); b.Property("BillingOccurrence") - .ValueGeneratedOnAdd() .HasColumnType("INTEGER") .HasDefaultValue(1); @@ -66,9 +64,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Name") .IsRequired() - .HasMaxLength(12) + .HasMaxLength(50) .HasColumnType("TEXT"); + b.Property("PrimaryColor") + .IsRequired() + .HasColumnType("TEXT") + .HasDefaultValue("#282828"); + b.HasKey("Id"); b.ToTable("Subscriptions"); diff --git a/subtrack.DAL/SubtrackDbContext.cs b/subtrack.DAL/SubtrackDbContext.cs index 4575fed..3bc79bb 100644 --- a/subtrack.DAL/SubtrackDbContext.cs +++ b/subtrack.DAL/SubtrackDbContext.cs @@ -23,6 +23,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { entity.Property(e => e.BillingOccurrence).HasDefaultValue(BillingOccurrence.Month).ValueGeneratedNever(); entity.Property(e => e.BillingInterval).HasDefaultValue(1).ValueGeneratedNever(); + entity.Property(e => e.PrimaryColor).HasDefaultValue("#282828").ValueGeneratedNever(); }); } } diff --git a/subtrack.MAUI/MauiProgram.cs b/subtrack.MAUI/MauiProgram.cs index 37bc39a..3fab0e9 100644 --- a/subtrack.MAUI/MauiProgram.cs +++ b/subtrack.MAUI/MauiProgram.cs @@ -4,6 +4,7 @@ using subtrack.MAUI.Services; using System.Runtime.CompilerServices; using subtrack.MAUI.Shared.JsInterop; +using subtrack.MAUI.Utilities; [assembly: InternalsVisibleTo("subtrack.Tests")] @@ -57,12 +58,13 @@ private static void SeedDb(SubtrackDbContext dbContext) dbContext.Database.Migrate(); var todayLastMonth = DateTime.Now.AddMonths(-1); + var availableBackgroundColors = CssUtil.AvailableBackgroundColors; dbContext.Subscriptions.AddRange( - new DAL.Entities.Subscription() { Name = "paramount", LastPayment = todayLastMonth.AddDays(-1), FirstPaymentDay = todayLastMonth.AddDays(-1).Day, Cost = 3m, BillingOccurrence = DAL.Entities.BillingOccurrence.Week, BillingInterval = 2 }, - new DAL.Entities.Subscription() { Name = "Disney+", LastPayment = todayLastMonth, FirstPaymentDay = todayLastMonth.Day, Cost = 3m, BillingOccurrence = DAL.Entities.BillingOccurrence.Month, BillingInterval = 1 }, - new DAL.Entities.Subscription() { Name = "Netflix", LastPayment = DateTime.Now.AddDays(-1), FirstPaymentDay = DateTime.Now.AddDays(-1).Day, IsAutoPaid = true, Description = "family plan", Cost = 10, BillingOccurrence = DAL.Entities.BillingOccurrence.Month, BillingInterval = 1 }, - new DAL.Entities.Subscription() { Name = "hbo", LastPayment = DateTime.Now, FirstPaymentDay = DateTime.Now.Day, Cost = 1.5m, BillingOccurrence = DAL.Entities.BillingOccurrence.Year, BillingInterval = 1 }, - new DAL.Entities.Subscription() { Name = "hulu", LastPayment = DateTime.Now.AddMonths(-2), FirstPaymentDay = 1, Cost = 1.5m, IsAutoPaid = true, BillingOccurrence = DAL.Entities.BillingOccurrence.Month, BillingInterval = 3 } + new DAL.Entities.Subscription() { Name = "paramount", LastPayment = todayLastMonth.AddDays(-1), FirstPaymentDay = todayLastMonth.AddDays(-1).Day, Cost = 3m, BillingOccurrence = DAL.Entities.BillingOccurrence.Week, BillingInterval = 2, PrimaryColor = availableBackgroundColors.First() }, + new DAL.Entities.Subscription() { Name = "Disney+", LastPayment = todayLastMonth, FirstPaymentDay = todayLastMonth.Day, Cost = 3m, BillingOccurrence = DAL.Entities.BillingOccurrence.Month, BillingInterval = 1, PrimaryColor = availableBackgroundColors.First() }, + new DAL.Entities.Subscription() { Name = "Netflix", LastPayment = DateTime.Now.AddDays(-1), FirstPaymentDay = DateTime.Now.AddDays(-1).Day, IsAutoPaid = true, Description = "family plan", Cost = 10, BillingOccurrence = DAL.Entities.BillingOccurrence.Month, BillingInterval = 1, PrimaryColor = availableBackgroundColors.First() }, + new DAL.Entities.Subscription() { Name = "hbo", LastPayment = DateTime.Now, FirstPaymentDay = DateTime.Now.Day, Cost = 1.5m, BillingOccurrence = DAL.Entities.BillingOccurrence.Year, BillingInterval = 1, PrimaryColor = availableBackgroundColors.First() }, + new DAL.Entities.Subscription() { Name = "hulu", LastPayment = DateTime.Now.AddMonths(-2), FirstPaymentDay = 1, Cost = 1.5m, IsAutoPaid = true, BillingOccurrence = DAL.Entities.BillingOccurrence.Month, BillingInterval = 3, PrimaryColor = availableBackgroundColors.First() } ); dbContext.SaveChanges(); diff --git a/subtrack.MAUI/Pages/Index.razor b/subtrack.MAUI/Pages/Index.razor index d92fddc..0fa6270 100644 --- a/subtrack.MAUI/Pages/Index.razor +++ b/subtrack.MAUI/Pages/Index.razor @@ -23,7 +23,7 @@ @foreach (var sub in _subscriptionResponses) { - Navigator.NavigateTo($"/details/{sub.Id}?ReturnUrl={Navigator.Uri}")) id="subscription-card" class="card border-primary mb-3 clickable" style="max-width: 20rem;"> + Navigator.NavigateTo($"/details/{sub.Id}?ReturnUrl={Navigator.Uri}")) id="subscription-card" class="card border-primary mb-3 clickable" style="max-width: 20rem;background-color:@sub.PrimaryColor"> @sub.Name @@ -36,7 +36,7 @@ } - @GetDueDaysText(sub.DueDays) + @GetDueDaysText(sub.DueDays) diff --git a/subtrack.MAUI/Pages/SubscriptionDetails.razor b/subtrack.MAUI/Pages/SubscriptionDetails.razor index c998255..509360f 100644 --- a/subtrack.MAUI/Pages/SubscriptionDetails.razor +++ b/subtrack.MAUI/Pages/SubscriptionDetails.razor @@ -15,7 +15,7 @@ else { - + @@ -26,8 +26,9 @@ else - - Billing + + + Billing @($"{_subscription.Cost:C}") @if (_subscription.IsAutoPaid) @@ -36,15 +37,17 @@ else } @GetOccurrenceText() + - + - Next payment - @_nextPaymentDate.ToString("MMMM dd, yyyy", _usCulture) + Next payment + @_nextPaymentDate.ToString("MMMM dd, yyyy", Constants.UsCulture) @_dueTimeText - + + @@ -52,25 +55,28 @@ else - - Latest payment + + + Latest payment - @_subscription.LastPayment.ToString("MMMM dd, yyyy", _usCulture) + @_subscription.LastPayment.ToString("MMMM dd, yyyy", Constants.UsCulture) - - Annually + + + Annually @($"~{Math.Round(_subscriptionsCost, 2):C}") - @if (!string.IsNullOrWhiteSpace(_subscription.Description)) - { - - @_subscription.Description - - } - + + + @if (!string.IsNullOrWhiteSpace(_subscription.Description)) + { + + @_subscription.Description + + } @@ -99,7 +105,6 @@ else bool _deleteButtonClicked; DateTime _nextPaymentDate; - private CultureInfo _usCulture = new CultureInfo("en-US"); protected override async Task OnInitializedAsync() { @@ -157,7 +162,7 @@ else return sb.ToString(); } - sb.Append(_subscription.BillingInterval.ToWords(_usCulture)); + sb.Append(_subscription.BillingInterval.ToWords(Constants.UsCulture)); sb.Append(" "); sb.Append(_subscription.BillingOccurrence.Humanize().ToLower().Pluralize()); return sb.ToString(); diff --git a/subtrack.MAUI/Pages/UpsertSubscription.razor b/subtrack.MAUI/Pages/UpsertSubscription.razor index 4aa7bdb..33034aa 100644 --- a/subtrack.MAUI/Pages/UpsertSubscription.razor +++ b/subtrack.MAUI/Pages/UpsertSubscription.razor @@ -8,7 +8,7 @@ @implements IAsyncDisposable - + @@ -24,28 +24,39 @@ - Last Payment - - - - Auto Paid - - - - - - Billing Cycle every - + @GetBillingOccurrenceDisplayText("Week") @GetBillingOccurrenceDisplayText("Month") @GetBillingOccurrenceDisplayText("Year") + + + Last Payment + + + + Auto Paid + + + + Primary Color + + + @foreach (var backgroundColor in backgroundColorOptions) + { + @backgroundColor.ToLower() + } + + + + + @@ -69,6 +80,8 @@ BillingOccurrence = BillingOccurrence.Month }; + private IEnumerable backgroundColorOptions = CssUtil.AvailableBackgroundColors; + protected override void OnInitialized() { RegionInfo ri = new RegionInfo(System.Threading.Thread.CurrentThread.CurrentUICulture.LCID); @@ -81,6 +94,9 @@ if (Id != null) { _subscription = await SubscriptionService.GetByIdIfExists(Id.Value); + } else + { + _subscription.PrimaryColor = backgroundColorOptions.First(); } } @@ -111,4 +127,6 @@ { return billingOccurrence.ToQuantity(_subscription.BillingInterval, showQuantityAs: ShowQuantityAs.None); } + + private void UpdateBackgroundColor(ChangeEventArgs e) => _subscription.PrimaryColor = e.Value!.ToString(); } \ No newline at end of file diff --git a/subtrack.MAUI/Responses/SubscriptionResponse.cs b/subtrack.MAUI/Responses/SubscriptionResponse.cs index 0f5c44e..04fd619 100644 --- a/subtrack.MAUI/Responses/SubscriptionResponse.cs +++ b/subtrack.MAUI/Responses/SubscriptionResponse.cs @@ -10,5 +10,6 @@ public class SubscriptionResponse public decimal Cost { get; set; } public DateTime LastPayment { get; set; } public int DueDays { get; set; } + public string PrimaryColor { get; set; } } } diff --git a/subtrack.MAUI/Services/SubscriptionService.cs b/subtrack.MAUI/Services/SubscriptionService.cs index df98aa4..cbca0bf 100644 --- a/subtrack.MAUI/Services/SubscriptionService.cs +++ b/subtrack.MAUI/Services/SubscriptionService.cs @@ -42,6 +42,7 @@ public async Task Update(Subscription subscriptionToUpdate) sub.IsAutoPaid = subscriptionToUpdate.IsAutoPaid; sub.BillingOccurrence = subscriptionToUpdate.BillingOccurrence; sub.BillingInterval = subscriptionToUpdate.BillingInterval; + sub.PrimaryColor = subscriptionToUpdate.PrimaryColor; AutoPay(sub); sub.Cost = subscriptionToUpdate.Cost; diff --git a/subtrack.MAUI/Shared/Components/BackButton.razor b/subtrack.MAUI/Shared/Components/BackButton.razor index 85dc08f..f40a8e4 100644 --- a/subtrack.MAUI/Shared/Components/BackButton.razor +++ b/subtrack.MAUI/Shared/Components/BackButton.razor @@ -1,6 +1,6 @@ @inject NavigationManager NavigationManager - NavigationManager.NavigateTo(Url)"> + NavigationManager.NavigateTo(Url)"> diff --git a/subtrack.MAUI/Shared/Components/EditButton.razor b/subtrack.MAUI/Shared/Components/EditButton.razor index d297978..ba9fe0e 100644 --- a/subtrack.MAUI/Shared/Components/EditButton.razor +++ b/subtrack.MAUI/Shared/Components/EditButton.razor @@ -1,6 +1,6 @@ @inject NavigationManager NavigationManager - NavigationManager.NavigateTo(Url)"> + NavigationManager.NavigateTo(Url)"> diff --git a/subtrack.MAUI/Shared/Components/SubscriptionMonthItem.razor b/subtrack.MAUI/Shared/Components/SubscriptionMonthItem.razor index ae86b12..b8d2f42 100644 --- a/subtrack.MAUI/Shared/Components/SubscriptionMonthItem.razor +++ b/subtrack.MAUI/Shared/Components/SubscriptionMonthItem.razor @@ -11,14 +11,17 @@ @foreach (var sub in SubscriptionMonth.Subscriptions) { - Navigator.NavigateTo($"/details/{sub.Id}?ReturnUrl={Navigator.Uri}")) class="card mb-2 clickable" style="max-width: 20rem;"> + Navigator.NavigateTo($"/details/{sub.Id}?ReturnUrl={Navigator.Uri}")) class="card mb-2 clickable" style="max-width: 20rem;background-color:@sub.PrimaryColor"> @sub.Name @($"{sub.Cost:C}") + @{ + int daysUntilDue = (int)(sub.LastPayment - DateTime.Now.Date).TotalDays; + } - @($"{sub.LastPayment.Day}{GetDateSuffix(sub.LastPayment.Day)}") + @($"{sub.LastPayment.Day}{GetDateSuffix(sub.LastPayment.Day)}") @if (sub.IsAutoPaid) { diff --git a/subtrack.MAUI/Shared/NavBar.razor b/subtrack.MAUI/Shared/NavBar.razor index 95fe54f..13af47b 100644 --- a/subtrack.MAUI/Shared/NavBar.razor +++ b/subtrack.MAUI/Shared/NavBar.razor @@ -1,24 +1,21 @@ - - - - - - - Home - - - - - - Monthly - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/subtrack.MAUI/Utilities/Constants.cs b/subtrack.MAUI/Utilities/Constants.cs new file mode 100644 index 0000000..3bee6f9 --- /dev/null +++ b/subtrack.MAUI/Utilities/Constants.cs @@ -0,0 +1,8 @@ +using System.Globalization; + +namespace subtrack.MAUI.Utilities; + +public static class Constants +{ + public static readonly CultureInfo UsCulture = new("en-US"); +} diff --git a/subtrack.MAUI/Utilities/CssUtil.cs b/subtrack.MAUI/Utilities/CssUtil.cs new file mode 100644 index 0000000..c8632c1 --- /dev/null +++ b/subtrack.MAUI/Utilities/CssUtil.cs @@ -0,0 +1,30 @@ +namespace subtrack.MAUI.Utilities; + +public static class CssUtil +{ + internal static readonly IEnumerable AvailableBackgroundColors = new[] + { + "#282828", + "#281439", + "#34126d", + "#38354a", + "#22202c", + "#4b013b", + "#141c39", + "#34424c", + "#203d50", + "#13516d", + "#050505", + "#242424", + "#2e2e2e", + "#2d0903" + }; + public static string GetDueClass(int daysUntilDue) => + daysUntilDue switch + { + < 0 => "overdue", + (>= 0) and (<= 2) => "text-warning", + _ => string.Empty, + }; + +} diff --git a/subtrack.MAUI/Utilities/DateTimeExtensions.cs b/subtrack.MAUI/Utilities/DateTimeExtensions.cs index 42c329c..33f1354 100644 --- a/subtrack.MAUI/Utilities/DateTimeExtensions.cs +++ b/subtrack.MAUI/Utilities/DateTimeExtensions.cs @@ -10,7 +10,7 @@ public static class DateTimeExtensions public static DateTime AddWeeks(this DateTime date, int weeks) => date.AddDays(weeks * 7); - public static string MonthName(this DateTime date) => date.ToString("MMMM"); + public static string MonthName(this DateTime date) => date.ToString("MMMM", Constants.UsCulture); public static DateTime LastDayOfMonthDate(this DateTime date) => new(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month)); diff --git a/subtrack.MAUI/Utilities/SubscriptionMapper.cs b/subtrack.MAUI/Utilities/SubscriptionMapper.cs index db7296a..f3c383a 100644 --- a/subtrack.MAUI/Utilities/SubscriptionMapper.cs +++ b/subtrack.MAUI/Utilities/SubscriptionMapper.cs @@ -16,7 +16,8 @@ public static IEnumerable ToResponses(this IEnumerable