Skip to content

Commit

Permalink
Merge pull request #505 from range-of-motion/support-registering-thro…
Browse files Browse the repository at this point in the history
…ugh-spa-prototype

Support registering through SPA prototype
  • Loading branch information
range-of-motion authored Sep 7, 2024
2 parents 54f3304 + 85339d0 commit 77d0ad6
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 1 deletion.
15 changes: 15 additions & 0 deletions app/Http/Controllers/Api/CurrencyController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\CurrencyResource;
use App\Models\Currency;

class CurrencyController extends Controller
{
public function index()
{
return CurrencyResource::collection(Currency::all());
}
}
50 changes: 50 additions & 0 deletions app/Http/Controllers/Api/RegisterController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Http\Controllers\Api;

use App\Actions\SendVerificationMailAction;
use App\Http\Controllers\Controller;
use App\Models\Space;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class RegisterController extends Controller
{
public function __invoke(Request $request)
{
if (config('app.disable_registration')) {
abort(404);
}

$request->validate([
'name' => ['required'],
'email' => ['required', 'email', 'unique:users'],
'password' => ['required', 'confirmed'],
'currency' => ['required', 'exists:currencies,id'],
]);

$user = User::query()
->create([
'name' => $request->input('name'),
'email' => $request->input('email'),
'password' => Hash::make($request->input('password')),
'verification_token' => Str::random(100),
]);

$space = Space::query()
->create([
'currency_id' => $request->input('currency'),
'name' => $user->name . '\'s Space',
]);

$user->spaces()->attach($space->id, ['role' => 'admin']);

(new SendVerificationMailAction())->execute($user->id);

return [
'success' => true,
];
}
}
19 changes: 19 additions & 0 deletions app/Http/Resources/CurrencyResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class CurrencyResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'symbol' => $this->symbol,
'iso' => $this->iso,
];
}
}
5 changes: 5 additions & 0 deletions resources/assets/js/prototype/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import translations from './translations';
import App from './components/App.vue';

import Login from './screens/Login.vue';
import Register from './screens/Register.vue';
import Dashboard from './screens/Dashboard.vue';
import TransactionsIndex from './screens/Transactions/Index.vue';
import TransactionsCreate from './screens/Transactions/Create.vue';
Expand All @@ -27,6 +28,10 @@ const routes = [
path: '/prototype/login',
name: 'login',
component: Login,
}, {
path: '/prototype/register',
name: 'register',
component: Register,
}, {
path: '/prototype/dashboard',
name: 'dashboard',
Expand Down
4 changes: 3 additions & 1 deletion resources/assets/js/prototype/screens/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ watch(showError, value => {
</div>
</button>
</div>
<div class="mt-5 text-sm text-center dark:text-white">{{ versionNumber }}</div>
<div class="mt-4 text-sm text-center">
<router-link class="text-gray-500 dark:text-white" :to="{ name: 'register' }">First time here? Register.</router-link>
</div>
</div>
<div v-if="showError" class="absolute top-0 left-0 right-0 flex">
<div class="mt-10 mx-auto py-3 px-5 flex bg-white border border-gray-200 rounded-lg shadow-sm">
Expand Down
96 changes: 96 additions & 0 deletions resources/assets/js/prototype/screens/Register.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<script setup>
import axios from 'axios';
import { Loader2 } from 'lucide-vue';
import { getCurrentInstance, ref } from 'vue';
const router = getCurrentInstance().proxy.$router;
const isBusy = ref(false);
const errors = ref({});
const name = ref('');
const email = ref('');
const password = ref('');
const repeatedPassword = ref('');
const currencies = ref([]);
const currency = ref(1);
const fetchCurrencies = () => {
axios
.get('/api/currencies')
.then(response => {
currencies.value = response.data;
});
};
const register = () => {
isBusy.value = true;
axios
.post('/api/register', { name: name.value, email: email.value, password: password.value, password_confirmation: repeatedPassword.value, currency: currency.value })
.then(response => {
const json = response.data;
if (json.success) {
router.push({ name: 'login' });
}
})
.catch(error => {
isBusy.value = false;
password.value = '';
repeatedPassword.value = '';
if (error.response && error.response.data) {
const json = error.response.data;
if (json.errors) {
errors.value = json.errors;
}
}
});
};
fetchCurrencies();
</script>

<template>
<div class="flex items-center justify-center min-h-screen">
<div class="flex-1 max-w-sm">
<div class="p-5 space-y-5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg">
<div>
<label class="block mb-2 text-sm dark:text-white">{{ $t('name') }}</label>
<input class="w-full px-3.5 py-2.5 text-sm dark:text-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg" type="text" v-model="name" @keyup.enter="register" />
<div v-if="errors.name" class="mt-1.5 text-sm text-red-500">{{ errors.name[0] }}</div>
</div>
<div>
<label class="block mb-2 text-sm dark:text-white">{{ $t('email') }}</label>
<input class="w-full px-3.5 py-2.5 text-sm dark:text-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg" type="email" v-model="email" @keyup.enter="register" />
<div v-if="errors.email" class="mt-1.5 text-sm text-red-500">{{ errors.email[0] }}</div>
</div>
<div>
<label class="block mb-2 text-sm dark:text-white">{{ $t('password') }}</label>
<input class="w-full px-3.5 py-2.5 text-sm dark:text-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg" type="password" v-model="password" @keyup.enter="register" />
<div v-if="errors.password" class="mt-1.5 text-sm text-red-500">{{ errors.password[0] }}</div>
</div>
<div>
<label class="block mb-2 text-sm dark:text-white">{{ $t('repeatPassword') }}</label>
<input class="w-full px-3.5 py-2.5 text-sm dark:text-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg" type="password" v-model="repeatedPassword" @keyup.enter="register" />
</div>
<div>
<label class="block mb-2 text-sm dark:text-white">{{ $t('currency') }}</label>
<select class="w-full px-3.5 py-2.5 text-sm dark:text-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg appearance-none" v-model="currency">
<option v-for="currency in currencies" :value="currency.id">{{ currency.name }} (<span v-html="currency.symbol"></span>)</option>
</select>
</div>
<button class="w-full py-3 text-sm text-white bg-gray-900 dark:bg-gray-950 rounded-lg" @click="register">
<span v-if="!isBusy">{{ $t('register') }}</span>
<div v-if="isBusy" class="flex justify-center h-5">
<Loader2 class="animate-spin" :size="18" :strokeWidth="2.4" />
</div>
</button>
</div>
<div class="mt-4 text-sm text-center">
<router-link class="text-gray-500 dark:text-white" :to="{ name: 'login' }">Already using Budget? Log in.</router-link>
</div>
</div>
</div>
</template>
4 changes: 4 additions & 0 deletions resources/assets/js/prototype/translations/de.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"amount": "Betrag",
"create": "Erstellen",
"currency": "Währung",
"dailyBalanceGraphDescription": "Hier ist dein Kontostand im Laufe des Monats",
"dashboard": "Dashboard",
"date": "Datum",
Expand All @@ -13,8 +14,11 @@
"goodMorning": "Guten Morgen",
"language": "Sprache",
"logIn": "Anmelden",
"name": "Name",
"password": "Passwort",
"recurringDescription": "Dies ist eine wiederkehrende Transaktion—erstelle sie auch in Zukunft für mich",
"register": "Registriere",
"repeatPassword": "Passwort wiederholen",
"spending": "Ausgabe",
"spendingDescriptionPlaceholder": "Geburtstagsgeschenk für Angela",
"tag": "Schlagwort",
Expand Down
4 changes: 4 additions & 0 deletions resources/assets/js/prototype/translations/en.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"amount": "Amount",
"create": "Create",
"currency": "Currency",
"dailyBalanceGraphDescription": "Here is your balance throughout the month",
"dashboard": "Dashboard",
"date": "Date",
Expand All @@ -13,8 +14,11 @@
"goodMorning": "Good morning",
"language": "Language",
"logIn": "Log in",
"name": "Name",
"password": "Password",
"recurringDescription": "This is a recurring transaction—create it for me in the future",
"register": "Register",
"repeatPassword": "Repeat password",
"spending": "Spending",
"spendingDescriptionPlaceholder": "Birthday present for Angela",
"tag": "Tag",
Expand Down
4 changes: 4 additions & 0 deletions resources/assets/js/prototype/translations/nl.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"amount": "Bedrag",
"create": "Creëer",
"currency": "Valuta",
"dailyBalanceGraphDescription": "Dit is je balans gedurende deze maand",
"dashboard": "Dashboard",
"date": "Datum",
Expand All @@ -13,8 +14,11 @@
"goodMorning": "Goedemorgen",
"language": "Taal",
"logIn": "Log in",
"name": "Naam",
"password": "Wachtwoord",
"recurringDescription": "Dit is een terugkerende transactie–maak deze in de toekomst voor mij aan",
"register": "Registreer",
"repeatPassword": "Herhaal wachtwoord",
"spending": "Uitgave",
"spendingDescriptionPlaceholder": "Verjaardagscadeau voor Angela",
"tag": "Etiket",
Expand Down
4 changes: 4 additions & 0 deletions resources/assets/js/prototype/translations/ru.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"amount": "Сумма",
"create": "Создать",
"currency": "Валюта",
"dailyBalanceGraphDescription": "Здесь отображается ваш баланс в течение месяца",
"dashboard": "Панель приборов",
"date": "Дата",
Expand All @@ -13,8 +14,11 @@
"goodMorning": "Доброе утро",
"language": "Язык",
"logIn": "Войти",
"name": "Имя",
"password": "Пароль",
"recurringDescription": "Это повторяющаяся транзакция—создайте ее для меня в будущем",
"register": "Зарегистрируй",
"repeatPassword": "Повтори пароль",
"spending": "Расход",
"spendingDescriptionPlaceholder": "Подарок на день рождения для Анжелы",
"tag": "Тег",
Expand Down
5 changes: 5 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
<?php

use App\Http\Controllers\Api\ActivitiesController;
use App\Http\Controllers\Api\CurrencyController;
use App\Http\Controllers\Api\DashboardController;
use App\Http\Controllers\Api\LogInController;
use App\Http\Controllers\Api\RecurringController;
use App\Http\Controllers\Api\RegisterController;
use App\Http\Controllers\Api\SettingsController;
use App\Http\Controllers\Api\TagController;
use App\Http\Controllers\Api\TransactionController;
use Illuminate\Support\Facades\Route;

Route::get('/currencies', [CurrencyController::class, 'index']);

Route::post('/log-in', LogInController::class);
Route::post('/register', RegisterController::class);

Route::middleware('resolve-api-key')
->group(function () {
Expand Down

0 comments on commit 77d0ad6

Please sign in to comment.