Skip to content

Commit

Permalink
Merge pull request #9 from lrdiv/signup-flow
Browse files Browse the repository at this point in the history
UI and UX improvements for initial signup
  • Loading branch information
lrdiv authored Jan 13, 2025
2 parents 3193624 + e15cbfe commit 7edfdea
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 47 deletions.
6 changes: 4 additions & 2 deletions apps/spin-cycle-client/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<a [routerLink]="['/history']">Spin Cycle</a>
<span class="pull-right">
@if (!authenticated()) {
<a [href]="authUrl">Login</a>
<a [href]="authUrl">Login with Discogs</a>
} @else {
<a [routerLink]="['/settings']">Settings</a>
<a href="#" (click)="logout($event)" role="button">Logout</a>
Expand All @@ -11,6 +11,8 @@
</nav>
<main class="main">
<div class="content">
<router-outlet />
<div class="container">
<router-outlet />
</div>
</div>
</main>
2 changes: 1 addition & 1 deletion apps/spin-cycle-client/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ export class AppComponent implements OnInit {
logout(e: MouseEvent): Promise<boolean> {
e.preventDefault();
this.authService.revokeToken();
return this.router.navigate(['/login']);
return this.router.navigate(['/']);
}
}
5 changes: 5 additions & 0 deletions apps/spin-cycle-client/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import { AuthGuard } from './auth/auth.guard';
import { UnauthGuard } from './auth/unauth.guard';
import { HistoryComponent } from './history/history.component';
import { SettingsComponent } from './settings/settings.component';
import { WelcomeComponent } from './welcome.component';

export const routes: Routes = [
{
path: '',
component: WelcomeComponent,
},
{
path: 'auth',
component: AuthComponent,
Expand Down
8 changes: 3 additions & 5 deletions apps/spin-cycle-client/src/app/auth/auth.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, DestroyRef, OnInit, WritableSignal, inject, signal } from '@angular/core';
import { Component, DestroyRef, OnInit, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute, ParamMap, Router } from '@angular/router';

Expand All @@ -17,18 +17,16 @@ export class AuthComponent implements OnInit {
private readonly route: ActivatedRoute = inject(ActivatedRoute);
private readonly router: Router = inject(Router);

public readonly error: WritableSignal<string | null> = signal(null);

ngOnInit(): void {
this.route.queryParamMap.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params: ParamMap) => {
const token = params.get('token');
if (!token) {
this.error.set('Unable to authenticate');
this.router.navigate(['/']);
return;
}

this.authService.setToken(token);
this.router.navigate(['/history']);
this.router.navigate(['/settings']);
});
}
}
75 changes: 40 additions & 35 deletions apps/spin-cycle-client/src/app/history/history.component.html
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
<div class="container">
<h1 class="margin-bottom">History</h1>
@if (spinsLoaded()) {
@if (loadedSpins()) {
<table>
<thead>
<tr>
<td>Date</td>
<td>Artist(s)</td>
<td>Album</td>
<td>Played</td>
@if (spinsCount() === 0) {
<div class="alert margin-bottom">
If you haven't received any recommendations, check the email address entered in the
<a [routerLink]="['/settings']">Settings</a> page.
</div>
}

<h1 class="margin-bottom">History</h1>
@if (spinsLoaded()) {
@if (loadedSpins()) {
<table>
<thead>
<tr>
<td>Date</td>
<td>Artist(s)</td>
<td>Album</td>
<td>Played</td>
</tr>
</thead>
<tbody>
@for (spin of spins(); track spin.id) {
<tr [class.text-gray-300]="!spin.played">
<td>{{ spin.createdAt | date }}</td>
<td>{{ spin.artistName }}</td>
<td>
<a [href]="'https://discogs.com/release/' + spin.discogsId" target="_blank">{{ spin.recordName }}</a>
</td>
<td>
<button (click)="updatePlayed(spin)">
{{ spin.played ? "I didn't play this" : 'I played this' }}
</button>
</td>
</tr>
</thead>
<tbody>
@for (spin of spins(); track spin.id) {
<tr [class.text-gray-300]="!spin.played">
<td>{{ spin.createdAt | date }}</td>
<td>{{ spin.artistName }}</td>
<td>
<a [href]="'https://discogs.com/release/' + spin.discogsId" target="_blank">{{ spin.recordName }}</a>
</td>
<td>
<button (click)="updatePlayed(spin)">
{{ spin.played ? "I didn't play this" : 'I played this' }}
</button>
</td>
</tr>
}
</tbody>
</table>
}
</tbody>
</table>

@if (hasMorePages()) {
<button (click)="getNextPage()">Load More</button>
} @else {
<h3 class="margin-top">No spins yet! Maybe tomorrow 🤞</h3>
}
@if (hasMorePages()) {
<button (click)="getNextPage()">Load More</button>
}
} @else {
<h3 class="margin-top">No spins yet! Maybe tomorrow 🤞</h3>
}
</div>
}
5 changes: 4 additions & 1 deletion apps/spin-cycle-client/src/app/history/history.component.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { DatePipe } from '@angular/common';
import { Component, OnInit, Signal, WritableSignal, computed, inject, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterLink } from '@angular/router';
import { Page, SpinOut } from '@spin-cycle-mono/shared';

import { HistoryService } from './history.service';

@Component({
selector: 'sc-history',
standalone: true,
imports: [DatePipe, FormsModule],
imports: [DatePipe, FormsModule, RouterLink],
templateUrl: './history.component.html',
styleUrl: './history.component.scss',
})
Expand All @@ -18,6 +19,7 @@ export class HistoryComponent implements OnInit {
public readonly currentPage: WritableSignal<number> = signal(0);
public readonly hasMorePages: WritableSignal<boolean> = signal(false);
public readonly spins: WritableSignal<SpinOut[] | null> = signal(null);
public readonly spinsCount: WritableSignal<number | null> = signal(null);

public readonly spinsLoaded: Signal<boolean> = computed(() => this.spins() !== null);
public readonly loadedSpins: Signal<SpinOut[]> = computed(() => this.spins() ?? []);
Expand Down Expand Up @@ -47,6 +49,7 @@ export class HistoryComponent implements OnInit {

private getSpins(): void {
this.historyService.getSpinsPage(this.currentPage() + 1).subscribe((spins: Page<SpinOut>) => {
this.spinsCount.set(spins.totalItems);
this.spins.update((existing: SpinOut[] | null) => [...(existing ?? []), ...spins.content]);
this.currentPage.set(spins.page);
this.hasMorePages.set(!spins.lastPage);
Expand Down
18 changes: 18 additions & 0 deletions apps/spin-cycle-client/src/app/welcome.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<h1 class="margin-bottom">Welcome to Spin Cycle</h1>

<h2 class="margin-top margin-bottom">What is Spin Cycle?</h2>
<p class="margin-bottom">
Spin Cycle is a simple service that sends you a daily email at 9am (Central) recommending a random album from your
<a href="https://discogs.com" target="_blank">Discogs</a> collection.
</p>
<p>
We make sure to never recommend the same record twice, allowing you to listen to your entire collection, one day at a
time. You can also mark a recommendation as "Not Played" to add it back into the mix for future recommendations.
</p>

<h2 class="margin-top margin-bottom">How Do I Join?</h2>
<ol>
<li><a [href]="authUrl">Login via Discogs</a></li>
<li>Tell us your email address, so we can send your recommendations</li>
<li>That's it! You'll get a daily email with a record from your collection</li>
</ol>
13 changes: 13 additions & 0 deletions apps/spin-cycle-client/src/app/welcome.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component, inject } from '@angular/core';

import { AuthService } from './auth/auth.service';

@Component({
selector: 'sc-welcome',
templateUrl: './welcome.component.html',
})
export class WelcomeComponent {
private readonly authService: AuthService = inject(AuthService);

public readonly authUrl: string = this.authService.authUrl;
}
1 change: 1 addition & 0 deletions apps/spin-cycle-client/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
@import './styles/boilerplate.css';
@import './styles/custom';
@import './styles/nav';
@import './styles/alert';
@import './styles/select';
5 changes: 5 additions & 0 deletions apps/spin-cycle-client/src/styles/_alert.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.alert {
background-color: var(--color_background--element);
padding: 10px;
width: 100%;
}
10 changes: 10 additions & 0 deletions apps/spin-cycle/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ import { RedisClientType, createClient } from 'redis';

import { AppModule } from './app.module';

const corsOrigin: string[] =
process.env.NODE_ENV === 'production'
? ['https://spincycle.lrdiv.co', 'https://discogs.com']
: ['http://localhost:4200'];

async function bootstrap() {
const app: NestExpressApplication = await NestFactory.create<NestExpressApplication>(AppModule, { cors: true });
app.setGlobalPrefix('api');
app.enableCors({
origin: corsOrigin,
methods: ['GET', 'PATCH', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
});
const redisClient: RedisClientType = createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379',
});
Expand Down
4 changes: 2 additions & 2 deletions apps/spin-cycle/src/users/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserEntity } from '@spin-cycle-mono/shared';
import { DeepPartial, Repository } from 'typeorm';
import { DeepPartial, IsNull, Not, Repository } from 'typeorm';

@Injectable()
export class UserService {
Expand All @@ -28,6 +28,6 @@ export class UserService {
}

findAllWithUnplayed(): Promise<UserEntity[]> {
return this.userRepository.find({ where: { allPlayed: false }, relations: [] });
return this.userRepository.find({ where: { allPlayed: false, email: Not(IsNull()) }, relations: [] });
}
}
2 changes: 1 addition & 1 deletion apps/spin-cycle/src/worker/worker.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class WorkerService {
} catch (e: unknown) {
this.handleSpinError(e, user);
}
await sleep(5);
await sleep(3);
}
}

Expand Down

0 comments on commit 7edfdea

Please sign in to comment.