Adds account management and subscription features
Introduces new account pages for managing subscriptions, payment methods, and invoice history Includes: - Subscription plan selection view - Payment method display component - Invoice history table - Account page layout and styling Updates main layout to include new CSS files for account management
This commit is contained in:
parent
5e0bd9db74
commit
1f400dcc6e
11 changed files with 724 additions and 1 deletions
|
|
@ -0,0 +1,108 @@
|
||||||
|
<swp-invoices-card>
|
||||||
|
<swp-invoices-header>
|
||||||
|
<swp-invoices-title>Faktura-historik</swp-invoices-title>
|
||||||
|
</swp-invoices-header>
|
||||||
|
|
||||||
|
<swp-invoice-table>
|
||||||
|
<swp-invoice-table-header>
|
||||||
|
<swp-invoice-row>
|
||||||
|
<swp-invoice-cell>Dato</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>Fakturanr.</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>Beløb</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>Status</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell></swp-invoice-cell>
|
||||||
|
</swp-invoice-row>
|
||||||
|
</swp-invoice-table-header>
|
||||||
|
<swp-invoice-table-body>
|
||||||
|
<swp-invoice-row>
|
||||||
|
<swp-invoice-cell>1. jan 2026</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell class="mono">INV-2026-0001</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>599,00 kr</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-invoice-status class="paid">
|
||||||
|
<i class="ph ph-check-circle"></i>
|
||||||
|
Betalt
|
||||||
|
</swp-invoice-status>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-download-btn>
|
||||||
|
<i class="ph ph-download"></i>
|
||||||
|
PDF
|
||||||
|
</swp-download-btn>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
</swp-invoice-row>
|
||||||
|
|
||||||
|
<swp-invoice-row>
|
||||||
|
<swp-invoice-cell>1. dec 2025</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell class="mono">INV-2025-0012</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>599,00 kr</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-invoice-status class="paid">
|
||||||
|
<i class="ph ph-check-circle"></i>
|
||||||
|
Betalt
|
||||||
|
</swp-invoice-status>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-download-btn>
|
||||||
|
<i class="ph ph-download"></i>
|
||||||
|
PDF
|
||||||
|
</swp-download-btn>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
</swp-invoice-row>
|
||||||
|
|
||||||
|
<swp-invoice-row>
|
||||||
|
<swp-invoice-cell>1. nov 2025</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell class="mono">INV-2025-0011</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>599,00 kr</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-invoice-status class="paid">
|
||||||
|
<i class="ph ph-check-circle"></i>
|
||||||
|
Betalt
|
||||||
|
</swp-invoice-status>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-download-btn>
|
||||||
|
<i class="ph ph-download"></i>
|
||||||
|
PDF
|
||||||
|
</swp-download-btn>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
</swp-invoice-row>
|
||||||
|
|
||||||
|
<swp-invoice-row>
|
||||||
|
<swp-invoice-cell>1. okt 2025</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell class="mono">INV-2025-0010</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>599,00 kr</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-invoice-status class="paid">
|
||||||
|
<i class="ph ph-check-circle"></i>
|
||||||
|
Betalt
|
||||||
|
</swp-invoice-status>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-download-btn>
|
||||||
|
<i class="ph ph-download"></i>
|
||||||
|
PDF
|
||||||
|
</swp-download-btn>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
</swp-invoice-row>
|
||||||
|
|
||||||
|
<swp-invoice-row>
|
||||||
|
<swp-invoice-cell>1. sep 2025</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell class="mono">INV-2025-0009</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>599,00 kr</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-invoice-status class="paid">
|
||||||
|
<i class="ph ph-check-circle"></i>
|
||||||
|
Betalt
|
||||||
|
</swp-invoice-status>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
<swp-invoice-cell>
|
||||||
|
<swp-download-btn>
|
||||||
|
<i class="ph ph-download"></i>
|
||||||
|
PDF
|
||||||
|
</swp-download-btn>
|
||||||
|
</swp-invoice-cell>
|
||||||
|
</swp-invoice-row>
|
||||||
|
</swp-invoice-table-body>
|
||||||
|
</swp-invoice-table>
|
||||||
|
</swp-invoices-card>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace PlanTempus.Application.Features.Account.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ViewComponent for the invoice history table.
|
||||||
|
/// Shows past invoices with status and download options.
|
||||||
|
/// </summary>
|
||||||
|
public class InvoiceHistoryViewComponent : ViewComponent
|
||||||
|
{
|
||||||
|
public IViewComponentResult Invoke()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<swp-payment-card>
|
||||||
|
<swp-payment-method>
|
||||||
|
<swp-payment-icon>
|
||||||
|
<i class="ph ph-credit-card"></i>
|
||||||
|
</swp-payment-icon>
|
||||||
|
<swp-payment-info>
|
||||||
|
<swp-payment-type>Visa</swp-payment-type>
|
||||||
|
<swp-payment-number>**** **** **** 4582</swp-payment-number>
|
||||||
|
</swp-payment-info>
|
||||||
|
<swp-btn class="secondary sm">
|
||||||
|
<i class="ph ph-pencil"></i>
|
||||||
|
Skift
|
||||||
|
</swp-btn>
|
||||||
|
</swp-payment-method>
|
||||||
|
|
||||||
|
<swp-payment-detail>
|
||||||
|
<swp-payment-label>Betalingsfrekvens</swp-payment-label>
|
||||||
|
<swp-payment-value>Månedlig</swp-payment-value>
|
||||||
|
</swp-payment-detail>
|
||||||
|
|
||||||
|
<swp-payment-detail>
|
||||||
|
<swp-payment-label>Næste betaling</swp-payment-label>
|
||||||
|
<swp-payment-value class="highlight">1. februar 2026</swp-payment-value>
|
||||||
|
</swp-payment-detail>
|
||||||
|
|
||||||
|
<swp-payment-detail>
|
||||||
|
<swp-payment-label>Beløb</swp-payment-label>
|
||||||
|
<swp-payment-value>599,00 kr</swp-payment-value>
|
||||||
|
</swp-payment-detail>
|
||||||
|
|
||||||
|
<swp-payment-detail>
|
||||||
|
<swp-payment-label>Kortudløb</swp-payment-label>
|
||||||
|
<swp-payment-value>08/2027</swp-payment-value>
|
||||||
|
</swp-payment-detail>
|
||||||
|
|
||||||
|
<swp-btn class="outline" style="margin-top: var(--spacing-2);">
|
||||||
|
<i class="ph ph-arrows-clockwise"></i>
|
||||||
|
Skift til årlig betaling (spar 15%)
|
||||||
|
</swp-btn>
|
||||||
|
</swp-payment-card>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace PlanTempus.Application.Features.Account.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ViewComponent for the payment method display.
|
||||||
|
/// Shows current card info, payment frequency, and next payment date.
|
||||||
|
/// </summary>
|
||||||
|
public class PaymentMethodViewComponent : ViewComponent
|
||||||
|
{
|
||||||
|
public IViewComponentResult Invoke()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
@using PlanTempus.Application.Features.Accounts.Models
|
||||||
|
@model IEnumerable<PlanInfo>
|
||||||
|
|
||||||
|
@{
|
||||||
|
var currentPlanKey = (string)ViewBag.CurrentPlanKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
<swp-plan-grid>
|
||||||
|
@foreach (var plan in Model)
|
||||||
|
{
|
||||||
|
var isCurrent = plan.Key == currentPlanKey;
|
||||||
|
var cardClass = plan.Key switch
|
||||||
|
{
|
||||||
|
"enterprise" => isCurrent ? "enterprise current" : "enterprise",
|
||||||
|
_ => isCurrent ? "current" : ""
|
||||||
|
};
|
||||||
|
|
||||||
|
var badgeClass = isCurrent ? "current" : plan.BadgeClass;
|
||||||
|
var badgeText = isCurrent ? "Nuværende plan" : plan.BadgeText;
|
||||||
|
var badgeIcon = isCurrent ? "ph-check" : plan.BadgeIcon;
|
||||||
|
|
||||||
|
var buttonText = isCurrent
|
||||||
|
? "Nuværende plan"
|
||||||
|
: plan.IsContactSales
|
||||||
|
? "Kontakt salg"
|
||||||
|
: $"Skift til {plan.Name}";
|
||||||
|
|
||||||
|
var buttonClass = isCurrent
|
||||||
|
? "secondary"
|
||||||
|
: plan.IsContactSales
|
||||||
|
? "outline"
|
||||||
|
: "secondary";
|
||||||
|
|
||||||
|
<swp-plan-card class="@cardClass">
|
||||||
|
<swp-plan-badge class="@badgeClass">
|
||||||
|
<i class="ph @badgeIcon"></i>
|
||||||
|
@badgeText
|
||||||
|
</swp-plan-badge>
|
||||||
|
<swp-plan-name>@plan.Name</swp-plan-name>
|
||||||
|
<swp-plan-users>@plan.UserRange</swp-plan-users>
|
||||||
|
<swp-plan-price>
|
||||||
|
@if (plan.PricePerMonth.HasValue)
|
||||||
|
{
|
||||||
|
<swp-plan-price-amount>@plan.PriceDisplay</swp-plan-price-amount>
|
||||||
|
<swp-plan-price-period>kr/md</swp-plan-price-period>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<swp-plan-price-amount>Kontakt os</swp-plan-price-amount>
|
||||||
|
}
|
||||||
|
</swp-plan-price>
|
||||||
|
<swp-plan-features>
|
||||||
|
@foreach (var feature in plan.Features)
|
||||||
|
{
|
||||||
|
<swp-plan-feature>
|
||||||
|
<i class="ph ph-check-circle"></i>
|
||||||
|
@feature
|
||||||
|
</swp-plan-feature>
|
||||||
|
}
|
||||||
|
</swp-plan-features>
|
||||||
|
<swp-plan-action>
|
||||||
|
<swp-btn class="@buttonClass">@buttonText</swp-btn>
|
||||||
|
</swp-plan-action>
|
||||||
|
</swp-plan-card>
|
||||||
|
}
|
||||||
|
</swp-plan-grid>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using PlanTempus.Application.Features.Accounts.Models;
|
||||||
|
|
||||||
|
namespace PlanTempus.Application.Features.Account.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ViewComponent for the subscription plan selection grid.
|
||||||
|
/// Shows all available plans with the current plan highlighted.
|
||||||
|
/// </summary>
|
||||||
|
public class SubscriptionPlansViewComponent : ViewComponent
|
||||||
|
{
|
||||||
|
public IViewComponentResult Invoke()
|
||||||
|
{
|
||||||
|
var plans = PlanCatalog.GetAllPlans();
|
||||||
|
// Mock: current plan is "pro"
|
||||||
|
var currentPlanKey = "pro";
|
||||||
|
|
||||||
|
ViewBag.CurrentPlanKey = currentPlanKey;
|
||||||
|
return View(plans);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
PlanTempus.Application/Features/Account/Pages/Index.cshtml
Normal file
45
PlanTempus.Application/Features/Account/Pages/Index.cshtml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
@page "/konto"
|
||||||
|
@using PlanTempus.Application.Features.Account.Pages
|
||||||
|
@model PlanTempus.Application.Features.Account.Pages.IndexModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Abonnement & Konto";
|
||||||
|
}
|
||||||
|
|
||||||
|
<swp-page-container>
|
||||||
|
|
||||||
|
<!-- Page Header -->
|
||||||
|
<swp-page-header>
|
||||||
|
<swp-page-title>
|
||||||
|
<h1>Abonnement & Konto</h1>
|
||||||
|
<p>Administrer dit abonnement og betalingsinfo</p>
|
||||||
|
</swp-page-title>
|
||||||
|
</swp-page-header>
|
||||||
|
|
||||||
|
<!-- Subscription Section -->
|
||||||
|
<swp-account-section>
|
||||||
|
<swp-account-section-header>
|
||||||
|
<swp-account-section-title>
|
||||||
|
<i class="ph ph-crown"></i>
|
||||||
|
Dit abonnement
|
||||||
|
</swp-account-section-title>
|
||||||
|
</swp-account-section-header>
|
||||||
|
|
||||||
|
@await Component.InvokeAsync("SubscriptionPlans")
|
||||||
|
</swp-account-section>
|
||||||
|
|
||||||
|
<!-- Billing Section -->
|
||||||
|
<swp-account-section>
|
||||||
|
<swp-account-section-header>
|
||||||
|
<swp-account-section-title>
|
||||||
|
<i class="ph ph-credit-card"></i>
|
||||||
|
Betaling & Fakturaer
|
||||||
|
</swp-account-section-title>
|
||||||
|
</swp-account-section-header>
|
||||||
|
|
||||||
|
<swp-billing-grid>
|
||||||
|
@await Component.InvokeAsync("PaymentMethod")
|
||||||
|
@await Component.InvokeAsync("InvoiceHistory")
|
||||||
|
</swp-billing-grid>
|
||||||
|
</swp-account-section>
|
||||||
|
|
||||||
|
</swp-page-container>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
namespace PlanTempus.Application.Features.Account.Pages;
|
||||||
|
|
||||||
|
public class IndexModel : PageModel
|
||||||
|
{
|
||||||
|
public void OnGet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -176,7 +176,7 @@ public class MockMenuService : IMenuService
|
||||||
Id = "account",
|
Id = "account",
|
||||||
Label = "Abonnement & Konto",
|
Label = "Abonnement & Konto",
|
||||||
Icon = "ph-credit-card",
|
Icon = "ph-credit-card",
|
||||||
Url = "/poc-konto.html",
|
Url = "/konto",
|
||||||
MinimumRole = UserRole.Admin,
|
MinimumRole = UserRole.Admin,
|
||||||
SortOrder = 2
|
SortOrder = 2
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@
|
||||||
<link rel="stylesheet" href="~/css/waitlist.css">
|
<link rel="stylesheet" href="~/css/waitlist.css">
|
||||||
<link rel="stylesheet" href="~/css/tabs.css">
|
<link rel="stylesheet" href="~/css/tabs.css">
|
||||||
<link rel="stylesheet" href="~/css/cash.css">
|
<link rel="stylesheet" href="~/css/cash.css">
|
||||||
|
<link rel="stylesheet" href="~/css/auth.css">
|
||||||
|
<link rel="stylesheet" href="~/css/account.css">
|
||||||
@await RenderSectionAsync("Styles", required: false)
|
@await RenderSectionAsync("Styles", required: false)
|
||||||
</head>
|
</head>
|
||||||
<body class="has-demo-banner">
|
<body class="has-demo-banner">
|
||||||
|
|
|
||||||
401
PlanTempus.Application/wwwroot/css/account.css
Normal file
401
PlanTempus.Application/wwwroot/css/account.css
Normal file
|
|
@ -0,0 +1,401 @@
|
||||||
|
/**
|
||||||
|
* Account Styles - Subscription & Billing Management
|
||||||
|
*
|
||||||
|
* For logged-in users to manage their subscription plan,
|
||||||
|
* payment method, and view invoice history.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
SECTION STYLING
|
||||||
|
=========================================== */
|
||||||
|
swp-account-section {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: var(--spacing-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-account-section-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: var(--spacing-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-account-section-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-3);
|
||||||
|
font-size: var(--font-size-lg);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-account-section-title i {
|
||||||
|
font-size: 22px;
|
||||||
|
color: var(--color-teal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
PLAN GRID
|
||||||
|
=========================================== */
|
||||||
|
swp-plan-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: var(--spacing-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
swp-plan-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Plan card current state (extends auth.css) */
|
||||||
|
swp-plan-card.current {
|
||||||
|
border-color: var(--color-teal);
|
||||||
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-teal) 15%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-plan-badge.current {
|
||||||
|
background: color-mix(in srgb, var(--color-teal) 15%, transparent);
|
||||||
|
color: var(--color-teal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disabled button for current plan */
|
||||||
|
swp-plan-card.current swp-btn.secondary {
|
||||||
|
background: var(--color-background-alt);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
cursor: default;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enterprise plan styling */
|
||||||
|
swp-plan-card.enterprise {
|
||||||
|
background: linear-gradient(135deg, var(--color-surface) 0%, color-mix(in srgb, var(--color-purple) 5%, var(--color-surface)) 100%);
|
||||||
|
border-color: var(--color-purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-plan-badge.popular {
|
||||||
|
background: color-mix(in srgb, var(--color-amber) 15%, transparent);
|
||||||
|
color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Plan action buttons */
|
||||||
|
swp-plan-action {
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: var(--spacing-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-plan-action swp-btn {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
BILLING GRID (2 columns)
|
||||||
|
=========================================== */
|
||||||
|
swp-billing-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 380px 1fr;
|
||||||
|
gap: var(--spacing-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
swp-billing-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
PAYMENT CARD
|
||||||
|
=========================================== */
|
||||||
|
swp-payment-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-5);
|
||||||
|
background: var(--color-surface);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||||
|
padding: var(--spacing-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-method {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-4);
|
||||||
|
padding: var(--spacing-4);
|
||||||
|
background: var(--color-background-alt);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 32px;
|
||||||
|
background: var(--color-surface);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-icon i {
|
||||||
|
font-size: 24px;
|
||||||
|
color: var(--color-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-info {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-type {
|
||||||
|
display: block;
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
color: var(--color-text);
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-number {
|
||||||
|
display: block;
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-detail {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--spacing-3) 0;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-detail:last-of-type {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-label {
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-value {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-value.highlight {
|
||||||
|
color: var(--color-teal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
INVOICES CARD
|
||||||
|
=========================================== */
|
||||||
|
swp-invoices-card {
|
||||||
|
display: block;
|
||||||
|
background: var(--color-surface);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoices-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: var(--spacing-4) var(--spacing-5);
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoices-title {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
INVOICE TABLE (Grid + Subgrid)
|
||||||
|
=========================================== */
|
||||||
|
swp-invoice-table {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 100px minmax(120px, 1fr) 100px 100px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-table-header {
|
||||||
|
display: grid;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-template-columns: subgrid;
|
||||||
|
background: var(--color-background-alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-table-body {
|
||||||
|
display: grid;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-template-columns: subgrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-row {
|
||||||
|
display: grid;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-template-columns: subgrid;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
transition: background var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-table-body swp-invoice-row:hover {
|
||||||
|
background: var(--color-background-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-row:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-cell {
|
||||||
|
padding: var(--spacing-3) var(--spacing-4);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-cell:first-child {
|
||||||
|
padding-left: var(--spacing-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-cell:last-child {
|
||||||
|
padding-right: var(--spacing-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header cells */
|
||||||
|
swp-invoice-table-header swp-invoice-cell {
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
padding-top: var(--spacing-3);
|
||||||
|
padding-bottom: var(--spacing-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoice number mono font */
|
||||||
|
swp-invoice-cell.mono {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
INVOICE STATUS BADGES
|
||||||
|
=========================================== */
|
||||||
|
swp-invoice-status {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-2);
|
||||||
|
padding: var(--spacing-1) var(--spacing-3);
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-status.paid {
|
||||||
|
background: color-mix(in srgb, var(--color-green) 15%, transparent);
|
||||||
|
color: var(--color-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-status.pending {
|
||||||
|
background: color-mix(in srgb, var(--color-amber) 15%, transparent);
|
||||||
|
color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-status.overdue {
|
||||||
|
background: color-mix(in srgb, var(--color-red) 15%, transparent);
|
||||||
|
color: var(--color-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-status i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
DOWNLOAD BUTTON
|
||||||
|
=========================================== */
|
||||||
|
swp-download-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--spacing-2);
|
||||||
|
padding: var(--spacing-2) var(--spacing-3);
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
color: var(--color-teal);
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid var(--color-teal);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-download-btn:hover {
|
||||||
|
background: color-mix(in srgb, var(--color-teal) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-download-btn i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
BUTTONS (account-specific)
|
||||||
|
=========================================== */
|
||||||
|
swp-btn.secondary {
|
||||||
|
background: var(--color-surface);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-btn.secondary:hover {
|
||||||
|
background: var(--color-background-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-btn.outline {
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid var(--color-teal);
|
||||||
|
color: var(--color-teal);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-btn.outline:hover {
|
||||||
|
background: color-mix(in srgb, var(--color-teal) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-btn.sm {
|
||||||
|
padding: var(--spacing-2) var(--spacing-3);
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-btn.sm i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
RESPONSIVE
|
||||||
|
=========================================== */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
swp-invoice-table {
|
||||||
|
grid-template-columns: 80px minmax(100px, 1fr) 80px 80px 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-cell {
|
||||||
|
padding: var(--spacing-2) var(--spacing-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-cell:first-child {
|
||||||
|
padding-left: var(--spacing-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-invoice-cell:last-child {
|
||||||
|
padding-right: var(--spacing-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
swp-payment-card {
|
||||||
|
padding: var(--spacing-4);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue