Skip to content

Commit

Permalink
Add kudos transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
RikudouSage committed Jul 12, 2024
1 parent a2421d9 commit 35687bb
Show file tree
Hide file tree
Showing 15 changed files with 578 additions and 2 deletions.
14 changes: 14 additions & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
<li>
<a href="/register" class="block py-2 pl-3 pr-4 text-gray-500 bg-gray-400 rounded lg:bg-transparent lg:text-gray-500 lg:p-0 dark:text-white" aria-current="page">{{'register_account' | transloco}}</a>
</li>
<li>
<a routerLink="/transfer-v2" class="block py-2 pl-3 pr-4 text-gray-500 bg-gray-400 rounded lg:bg-transparent lg:text-gray-500 lg:p-0 dark:text-white" aria-current="page">{{'transfer' | transloco}}</a>
</li>
<li>
<a routerLink="/news" class="block py-2 pl-3 pr-4 text-gray-500 bg-gray-400 rounded lg:bg-transparent lg:text-gray-500 lg:p-0 dark:text-white" aria-current="page">{{'news' | transloco}}</a>
</li>
Expand Down Expand Up @@ -109,6 +112,17 @@ <h3 class="mb-6 text-sm font-semibold text-gray-900 uppercase dark:text-white">{
</li>
</ul>
</div>
<div>
<h3 class="mb-6 text-sm font-semibold text-gray-900 uppercase dark:text-white">{{'other_links' | transloco}}</h3>
<ul class="text-gray-500 dark:text-gray-400">
<li class="mb-4">
<a href="/register" class="hover:underline">{{'register_account' | transloco}}</a>
</li>
<li class="mb-4">
<a routerLink="/transfer-v2" class="hover:underline">{{'transfer' | transloco}}</a>
</li>
</ul>
</div>
</div>
<hr class="my-6 border-gray-200 sm:mx-auto dark:border-gray-700 lg:my-8">
<div class="text-center">
Expand Down
4 changes: 4 additions & 0 deletions src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ export const routes: Routes = [
path: 'terms',
loadComponent: () => import('./pages/terms/terms.component').then(c => c.TermsComponent),
},
{
path: 'transfer-v2',
loadComponent: () => import('./pages/transfer/transfer.component').then(c => c.TransferComponent),
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<label class="toggle" for="input{{random()}}">
<input class="toggle-checkbox" type="checkbox" id="input{{random()}}" [checked]="value()" (change)="value.set(input.checked)" #input>
<div class="toggle-switch"></div>
<span class="toggle-label">{{description()}}</span>
<ng-content />
</label>
88 changes: 88 additions & 0 deletions src/app/components/toggle-checkbox/toggle-checkbox.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
@import "../../../styles/colors";

$small: 576px;
@mixin mediaMax($maxWidth) {
@media screen and (max-width: $maxWidth) {
@content
}
}
$mainTextColor: $darkTextColor;
$shadowColor: rgba(0, 0, 0, 0.72);
$successColor: #1c64f2;

.toggle {
cursor: pointer;
display: inline-block;
}

.toggle-switch {
display: inline-block;
background: #ccc;
border-radius: 16px;
width: 48px;
height: 26px;
position: relative;
vertical-align: middle;
transition: background 0.25s;

@include mediaMax($small) {
width: 38px;
height: 22px;
}

&:before,
&:after {
content: "";
}

&:before {
display: block;
background: linear-gradient(to bottom, $mainTextColor 0%, lighten($mainTextColor, 10%) 100%);
border-radius: 50%;
box-shadow: 0 0 0 1px rgba(red($shadowColor), green($shadowColor), blue($shadowColor), 0.15);
width: 20px;
height: 20px;
position: absolute;
top: 3px;
left: 3px;
transition: left 0.25s;

@include mediaMax($small) {
width: 16px;
height: 16px;
}
}

.toggle:hover &:before {
background: linear-gradient(to bottom, $mainTextColor 0%, $mainTextColor 100%);
}

.toggle-checkbox:checked + & {
background: $successColor;

&:before {
left: 24px;

@include mediaMax($small) {
left: 18px;
}
}
}
}

.toggle-checkbox {
position: absolute;
visibility: hidden;
}

.toggle-label {
margin-left: 5px;
position: relative;
top: 2px;
font-size: 14px;
margin-right: 4px;

@include mediaMax($small) {
margin-left: 8px;
}
}
70 changes: 70 additions & 0 deletions src/app/components/toggle-checkbox/toggle-checkbox.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {Component, effect, input, OnInit, output, signal, WritableSignal} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";
import {OnChange, OnTouched} from "../../types/value-accessor";

@Component({
selector: 'app-toggle-checkbox',
standalone: true,
imports: [],
templateUrl: './toggle-checkbox.component.html',
styleUrl: './toggle-checkbox.component.scss',
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: ToggleCheckboxComponent,
},
],
})
export class ToggleCheckboxComponent implements ControlValueAccessor, OnInit {
private onChange: WritableSignal<OnChange<boolean> | null> = signal(null);
private onTouched: WritableSignal<OnTouched | null> = signal(null);

private formMode = signal(true);

public initialValue = input<boolean | null>(null);

public value = signal(false);
public disabled = signal(false);

public description = input.required<string>();
public random = signal(Math.random());

public valueChanged = output<boolean>();

constructor() {
effect(() => {
if (this.formMode()) {
if (this.onChange() === null) {
return;
}
(this.onChange()!)(this.value());
} else {
this.valueChanged.emit(this.value());
}
});
}

public async ngOnInit(): Promise<void> {
if (this.initialValue() !== null) {
this.formMode.set(false);
this.value.set(this.initialValue()!);
}
}

public writeValue(value: boolean): void {
this.value.set(value);
}

public registerOnChange(fn: OnChange<boolean>): void {
this.onChange.set(fn);
}

public registerOnTouched(fn: OnTouched): void {
this.onTouched.set(fn);
}

public setDisabledState(isDisabled: boolean): void {
this.disabled.set(isDisabled);
}
}
68 changes: 68 additions & 0 deletions src/app/pages/transfer/transfer.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<section class="bg-white dark:bg-gray-900">
<div class="grid max-w-screen-xl px-4 pt-20 pb-8 mx-auto lg:gap-8 xl:gap-0 lg:py-16 lg:pt-28">
<div class="mr-auto place-self-center lg:col-span-7">
<h1 class="mb-4 text-4xl font-extrabold leading-none tracking-tight md:text-5xl xl:text-6xl dark:text-white">
<transloco key="transfer" />
</h1>
</div>
</div>
</section>

<section class="bg-gray-50 dark:bg-gray-800">
<div class="max-w-screen-xl px-4 py-8 mx-auto space-y-12 lg:space-y-20 lg:py-24 lg:px-6">
<div class="items-center gap-8 lg:grid xl:gap-16">
<div class="text-gray-500 sm:text-lg dark:text-gray-400">
<p class="mb-4"><transloco key="transfer.visit_old" [params]="{oldUrl: '/transfer'}" /></p>
<form class="max-w-sm mx-auto" [formGroup]="form" (ngSubmit)="transfer()">
<div class="mb-2">
<label for="source_api_key" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{'transfer.source_api_key' | transloco}}</label>
<input formControlName="apiKey" type="text" id="source_api_key" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required [placeholder]="'transfer.source_api_key.description' | transloco" />
</div>
@if (form.value.apiKeyValidated === false) {
<p class="mb-1 text-red"><small>{{'invalid_api_key' | transloco}}</small></p>
}
@if (currentUser()) {
<p class="mb-1"><small>{{'current_user' | transloco:{user: currentUser()!.username} }}</small></p>
}

<div class="mb-5">
<app-toggle-checkbox [description]="'transfer.source_api_key.remember' | transloco" formControlName="remember" />
</div>

<div [class.mb-5]="form.value.targetUserValidated !== false" [class.mb-1]="form.value.targetUserValidated === false">
<label for="target_user" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{'transfer.target_user' | transloco}}</label>
<input formControlName="targetUser" type="text" id="target_user" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required [placeholder]="'transfer.target_user.description' | transloco:{exampleUser: exampleUser()}" />
</div>
@if (form.value.targetUserValidated === false) {
<p class="mb-5 text-red"><small>{{'invalid_target_user' | transloco}}</small></p>
}

<div [class.mb-5]="form.value.kudosAmountValidated !== false" [class.mb-1]="form.value.kudosAmountValidated === false">
<label for="kudos_amount" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">{{'transfer.kudos_amount' | transloco}}</label>
<input formControlName="kudosAmount" type="number" min="1" id="kudos_amount" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required [placeholder]="'transfer.kudos_amount.description' | transloco:{user: form.value.targetUser || ('transfer.kudos_amount.description.user_placeholder' | transloco)}" />
</div>
@if (form.value.kudosAmountValidated === false) {
<p class="mb-5 text-red"><small>{{'transfer.too_many_kudos' | transloco}}</small></p>
}

@if (sentSuccessfully() !== null) {
@if (sentSuccessfully()) {
<p class="mb-5 text-green-500">{{'transfer.success' | transloco}}</p>
} @else {
<p class="mb-5 text-red">{{'transfer.error' | transloco}}</p>
}
}
<button
[disabled]="!form.valid"
[class.cursor-not-allowed]="!form.valid"
[class.bg-gray-600]="!form.valid"
[class.text-gray-500]="!form.valid"
[class.bg-blue-700]="form.valid"
[class.dark:bg-blue-600]="form.valid"
[class.text-white]="form.valid"
type="submit" class="hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:hover:bg-blue-700 dark:focus:ring-blue-800">Submit</button>
</form>
</div>
</div>
</div>
</section>
Empty file.
Loading

0 comments on commit 35687bb

Please sign in to comment.