Browse Source

Feature/improve membership card (#2517)

* Improve style

* Add animated border
pull/2522/head
Thomas Kaul 1 year ago
committed by GitHub
parent
commit
6a19eab425
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 68
      apps/client/src/app/components/user-account-membership/user-account-membership.html
  2. 6
      libs/ui/src/lib/logo/logo.component.html
  3. 8
      libs/ui/src/lib/logo/logo.component.scss
  4. 1
      libs/ui/src/lib/logo/logo.component.ts
  5. 44
      libs/ui/src/lib/membership-card/membership-card.component.html
  6. 66
      libs/ui/src/lib/membership-card/membership-card.component.scss

68
apps/client/src/app/components/user-account-membership/user-account-membership.html

@ -2,40 +2,42 @@
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Membership</h1> <h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Membership</h1>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<gf-membership-card <div class="align-items-center d-flex flex-column">
class="mb-5 mx-auto" <gf-membership-card
[expiresAt]="(user?.subscription?.expiresAt | date: defaultDateFormat) ?? '∞'" [expiresAt]="user?.subscription?.expiresAt | date: defaultDateFormat"
[name]="user?.subscription?.type" [name]="user?.subscription?.type"
></gf-membership-card> ></gf-membership-card>
<div class="d-flex"> <div
<div class="mx-auto"> *ngIf="user?.subscription?.type === 'Basic'"
<div *ngIf="user?.subscription?.type === 'Basic'"> class="d-flex flex-column mt-5"
<ng-container >
*ngIf="hasPermissionForSubscription && hasPermissionToUpdateUserSettings" <ng-container
> *ngIf="hasPermissionForSubscription && hasPermissionToUpdateUserSettings"
<button color="primary" mat-flat-button (click)="onCheckout()"> >
<ng-container *ngIf="user.subscription.offer === 'default'" i18n <button color="primary" mat-flat-button (click)="onCheckout()">
>Upgrade</ng-container <ng-container *ngIf="user.subscription.offer === 'default'" i18n
> >Upgrade</ng-container
<ng-container *ngIf="user.subscription.offer === 'renewal'" i18n >
>Renew</ng-container <ng-container *ngIf="user.subscription.offer === 'renewal'" i18n
> >Renew</ng-container
</button> >
<div *ngIf="price" class="mt-1"> </button>
<ng-container *ngIf="coupon" <div *ngIf="price" class="mt-1 text-center">
><del class="text-muted" <ng-container *ngIf="coupon"
>{{ baseCurrency }}&nbsp;{{ price }}</del ><del class="text-muted"
>&nbsp;{{ baseCurrency }}&nbsp;{{ price - coupon >{{ baseCurrency }}&nbsp;{{ price }}</del
}}</ng-container >&nbsp;{{ baseCurrency }}&nbsp;{{ price - coupon
> }}</ng-container
<ng-container *ngIf="!coupon" >
>{{ baseCurrency }}&nbsp;{{ price }}</ng-container <ng-container *ngIf="!coupon"
>&nbsp;<span i18n>per year</span> >{{ baseCurrency }}&nbsp;{{ price }}</ng-container
</div> >&nbsp;<span i18n>per year</span>
</ng-container> </div>
</ng-container>
<div class="align-items-center d-flex justfiy-content-center mt-4">
<a <a
*ngIf="!user?.subscription?.expiresAt" *ngIf="!user?.subscription?.expiresAt"
class="mr-2 my-2" class="mx-1"
mat-stroked-button mat-stroked-button
[href]="trySubscriptionMail" [href]="trySubscriptionMail"
><span i18n>Try Premium</span> ><span i18n>Try Premium</span>
@ -46,7 +48,7 @@
></a> ></a>
<a <a
*ngIf="hasPermissionToUpdateUserSettings" *ngIf="hasPermissionToUpdateUserSettings"
class="mr-2 my-2" class="mx-1"
i18n i18n
mat-stroked-button mat-stroked-button
[routerLink]="" [routerLink]=""

6
libs/ui/src/lib/logo/logo.component.html

@ -1,8 +1,4 @@
<span class="align-items-center d-flex" <span class="align-items-center d-flex"
><span ><span class="d-inline-block logo" [ngClass]="{ 'mr-1': showLabel }"></span>
class="d-inline-block logo"
[ngClass]="{ 'mr-1': showLabel }"
[ngStyle]="{ 'background-color': color }"
></span>
<span *ngIf="showLabel" class="label">{{ label ?? 'Ghostfolio' }}</span></span <span *ngIf="showLabel" class="label">{{ label ?? 'Ghostfolio' }}</span></span
> >

8
libs/ui/src/lib/logo/logo.component.scss

@ -4,18 +4,12 @@
} }
.logo { .logo {
background-color: rgba(var(--dark-primary-text)); background-color: currentColor;
margin-top: -2px; margin-top: -2px;
mask: url('/assets/ghost.svg') no-repeat center; mask: url('/assets/ghost.svg') no-repeat center;
} }
} }
:host-context(.is-dark-theme) {
.logo {
background-color: rgba(var(--light-primary-text));
}
}
:host-context(.large) { :host-context(.large) {
.label { .label {
font-size: 3rem; font-size: 3rem;

1
libs/ui/src/lib/logo/logo.component.ts

@ -13,7 +13,6 @@ import {
}) })
export class LogoComponent { export class LogoComponent {
@HostBinding('class') @Input() size: 'large' | 'medium' = 'medium'; @HostBinding('class') @Input() size: 'large' | 'medium' = 'medium';
@Input() color: string;
@Input() label: string; @Input() label: string;
@Input() showLabel = true; @Input() showLabel = true;

44
libs/ui/src/lib/membership-card/membership-card.component.html

@ -1,25 +1,29 @@
<a <div
class="card-item d-flex flex-column justify-content-between p-4" class="card-container position-relative"
[ngClass]="{ premium: name === 'Premium' }" [ngClass]="{ premium: name === 'Premium' }"
[routerLink]="routerLinkPricing"
> >
<div class="d-flex justify-content-end"> <a
<gf-logo class="card-item d-flex flex-column justify-content-between p-4"
color="rgba(255, 255, 255, 1)" [routerLink]="routerLinkPricing"
size="large" >
[showLabel]="false" <div class="d-flex justify-content-end">
></gf-logo> <gf-logo
</div> size="large"
<div class="d-flex justify-content-between"> [ngClass]="{ 'text-muted': name === 'Basic' }"
<div> [showLabel]="false"
<div class="card-item-heading mb-1 text-muted" i18n>Membership</div> />
<div class="card-item-name line-height-1 text-truncate">{{ name }}</div>
</div> </div>
<div> <div class="d-flex justify-content-between">
<div class="card-item-heading mb-1 text-muted" i18n>Valid until</div> <div>
<div class="card-item-name line-height-1 text-truncate"> <div class="heading text-muted" i18n>Membership</div>
{{ expiresAt }} <div class="text-truncate value">{{ name }}</div>
</div>
<div *ngIf="expiresAt">
<div class="heading text-muted" i18n>Valid until</div>
<div class="text-truncate value">
{{ expiresAt }}
</div>
</div> </div>
</div> </div>
</div> </a>
</a> </div>

66
libs/ui/src/lib/membership-card/membership-card.component.scss

@ -1,24 +1,66 @@
:host { :host {
--borderRadius: 1rem;
--borderWidth: 2px;
display: block; display: block;
max-width: 25rem; max-width: 25rem;
padding-top: calc(1 * var(--borderWidth));
width: 100%;
.card-item { .card-container {
aspect-ratio: 1.586; border-radius: var(--borderRadius);
background-color: #343a40 !important; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
border-radius: 1rem;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
&.premium { &:after {
background-color: #1d2124 !important; animation: animatedborder 7s ease alternate infinite;
} background: linear-gradient(60deg, #5073b8, #1098ad, #07b39b, #6fba82);
background-size: 300% 300%;
border-radius: var(--borderRadius);
content: '';
height: calc(100% + var(--borderWidth) * 2);
left: calc(-1 * var(--borderWidth));
top: calc(-1 * var(--borderWidth));
position: absolute;
width: calc(100% + var(--borderWidth) * 2);
z-index: -1;
.card-item-heading { @keyframes animatedborder {
font-size: 13px; 0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
} }
.card-item-name { .card-item {
aspect-ratio: 1.586;
background-color: #1d2124;
border-radius: calc(var(--borderRadius) - var(--borderWidth));
color: rgba(var(--light-primary-text)); color: rgba(var(--light-primary-text));
font-size: 18px;
.heading {
font-size: 13px;
}
.value {
font-size: 18px;
}
}
&:not(.premium) {
&:after {
opacity: 0;
}
.card-item {
background-color: #ffffff;
color: rgba(var(--dark-primary-text));
}
} }
} }
} }

Loading…
Cancel
Save