Skip to content

Commit 85339d0

Browse files
Support registering through SPA prototype
1 parent 54f3304 commit 85339d0

File tree

11 files changed

+209
-1
lines changed

11 files changed

+209
-1
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Api;
4+
5+
use App\Http\Controllers\Controller;
6+
use App\Http\Resources\CurrencyResource;
7+
use App\Models\Currency;
8+
9+
class CurrencyController extends Controller
10+
{
11+
public function index()
12+
{
13+
return CurrencyResource::collection(Currency::all());
14+
}
15+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Api;
4+
5+
use App\Actions\SendVerificationMailAction;
6+
use App\Http\Controllers\Controller;
7+
use App\Models\Space;
8+
use App\Models\User;
9+
use Illuminate\Http\Request;
10+
use Illuminate\Support\Facades\Hash;
11+
use Illuminate\Support\Str;
12+
13+
class RegisterController extends Controller
14+
{
15+
public function __invoke(Request $request)
16+
{
17+
if (config('app.disable_registration')) {
18+
abort(404);
19+
}
20+
21+
$request->validate([
22+
'name' => ['required'],
23+
'email' => ['required', 'email', 'unique:users'],
24+
'password' => ['required', 'confirmed'],
25+
'currency' => ['required', 'exists:currencies,id'],
26+
]);
27+
28+
$user = User::query()
29+
->create([
30+
'name' => $request->input('name'),
31+
'email' => $request->input('email'),
32+
'password' => Hash::make($request->input('password')),
33+
'verification_token' => Str::random(100),
34+
]);
35+
36+
$space = Space::query()
37+
->create([
38+
'currency_id' => $request->input('currency'),
39+
'name' => $user->name . '\'s Space',
40+
]);
41+
42+
$user->spaces()->attach($space->id, ['role' => 'admin']);
43+
44+
(new SendVerificationMailAction())->execute($user->id);
45+
46+
return [
47+
'success' => true,
48+
];
49+
}
50+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Http\Resources;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Http\Resources\Json\JsonResource;
7+
8+
class CurrencyResource extends JsonResource
9+
{
10+
public function toArray(Request $request): array
11+
{
12+
return [
13+
'id' => $this->id,
14+
'name' => $this->name,
15+
'symbol' => $this->symbol,
16+
'iso' => $this->iso,
17+
];
18+
}
19+
}

resources/assets/js/prototype/app.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import translations from './translations';
88
import App from './components/App.vue';
99

1010
import Login from './screens/Login.vue';
11+
import Register from './screens/Register.vue';
1112
import Dashboard from './screens/Dashboard.vue';
1213
import TransactionsIndex from './screens/Transactions/Index.vue';
1314
import TransactionsCreate from './screens/Transactions/Create.vue';
@@ -27,6 +28,10 @@ const routes = [
2728
path: '/prototype/login',
2829
name: 'login',
2930
component: Login,
31+
}, {
32+
path: '/prototype/register',
33+
name: 'register',
34+
component: Register,
3035
}, {
3136
path: '/prototype/dashboard',
3237
name: 'dashboard',

resources/assets/js/prototype/screens/Login.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ watch(showError, value => {
6969
</div>
7070
</button>
7171
</div>
72-
<div class="mt-5 text-sm text-center dark:text-white">{{ versionNumber }}</div>
72+
<div class="mt-4 text-sm text-center">
73+
<router-link class="text-gray-500 dark:text-white" :to="{ name: 'register' }">First time here? Register.</router-link>
74+
</div>
7375
</div>
7476
<div v-if="showError" class="absolute top-0 left-0 right-0 flex">
7577
<div class="mt-10 mx-auto py-3 px-5 flex bg-white border border-gray-200 rounded-lg shadow-sm">
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<script setup>
2+
import axios from 'axios';
3+
import { Loader2 } from 'lucide-vue';
4+
import { getCurrentInstance, ref } from 'vue';
5+
6+
const router = getCurrentInstance().proxy.$router;
7+
8+
const isBusy = ref(false);
9+
const errors = ref({});
10+
const name = ref('');
11+
const email = ref('');
12+
const password = ref('');
13+
const repeatedPassword = ref('');
14+
const currencies = ref([]);
15+
const currency = ref(1);
16+
17+
const fetchCurrencies = () => {
18+
axios
19+
.get('/api/currencies')
20+
.then(response => {
21+
currencies.value = response.data;
22+
});
23+
};
24+
25+
const register = () => {
26+
isBusy.value = true;
27+
28+
axios
29+
.post('/api/register', { name: name.value, email: email.value, password: password.value, password_confirmation: repeatedPassword.value, currency: currency.value })
30+
.then(response => {
31+
const json = response.data;
32+
33+
if (json.success) {
34+
router.push({ name: 'login' });
35+
}
36+
})
37+
.catch(error => {
38+
isBusy.value = false;
39+
password.value = '';
40+
repeatedPassword.value = '';
41+
42+
if (error.response && error.response.data) {
43+
const json = error.response.data;
44+
45+
if (json.errors) {
46+
errors.value = json.errors;
47+
}
48+
}
49+
});
50+
};
51+
52+
fetchCurrencies();
53+
</script>
54+
55+
<template>
56+
<div class="flex items-center justify-center min-h-screen">
57+
<div class="flex-1 max-w-sm">
58+
<div class="p-5 space-y-5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg">
59+
<div>
60+
<label class="block mb-2 text-sm dark:text-white">{{ $t('name') }}</label>
61+
<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" />
62+
<div v-if="errors.name" class="mt-1.5 text-sm text-red-500">{{ errors.name[0] }}</div>
63+
</div>
64+
<div>
65+
<label class="block mb-2 text-sm dark:text-white">{{ $t('email') }}</label>
66+
<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" />
67+
<div v-if="errors.email" class="mt-1.5 text-sm text-red-500">{{ errors.email[0] }}</div>
68+
</div>
69+
<div>
70+
<label class="block mb-2 text-sm dark:text-white">{{ $t('password') }}</label>
71+
<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" />
72+
<div v-if="errors.password" class="mt-1.5 text-sm text-red-500">{{ errors.password[0] }}</div>
73+
</div>
74+
<div>
75+
<label class="block mb-2 text-sm dark:text-white">{{ $t('repeatPassword') }}</label>
76+
<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" />
77+
</div>
78+
<div>
79+
<label class="block mb-2 text-sm dark:text-white">{{ $t('currency') }}</label>
80+
<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">
81+
<option v-for="currency in currencies" :value="currency.id">{{ currency.name }} (<span v-html="currency.symbol"></span>)</option>
82+
</select>
83+
</div>
84+
<button class="w-full py-3 text-sm text-white bg-gray-900 dark:bg-gray-950 rounded-lg" @click="register">
85+
<span v-if="!isBusy">{{ $t('register') }}</span>
86+
<div v-if="isBusy" class="flex justify-center h-5">
87+
<Loader2 class="animate-spin" :size="18" :strokeWidth="2.4" />
88+
</div>
89+
</button>
90+
</div>
91+
<div class="mt-4 text-sm text-center">
92+
<router-link class="text-gray-500 dark:text-white" :to="{ name: 'login' }">Already using Budget? Log in.</router-link>
93+
</div>
94+
</div>
95+
</div>
96+
</template>

resources/assets/js/prototype/translations/de.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"amount": "Betrag",
33
"create": "Erstellen",
4+
"currency": "Währung",
45
"dailyBalanceGraphDescription": "Hier ist dein Kontostand im Laufe des Monats",
56
"dashboard": "Dashboard",
67
"date": "Datum",
@@ -13,8 +14,11 @@
1314
"goodMorning": "Guten Morgen",
1415
"language": "Sprache",
1516
"logIn": "Anmelden",
17+
"name": "Name",
1618
"password": "Passwort",
1719
"recurringDescription": "Dies ist eine wiederkehrende Transaktion—erstelle sie auch in Zukunft für mich",
20+
"register": "Registriere",
21+
"repeatPassword": "Passwort wiederholen",
1822
"spending": "Ausgabe",
1923
"spendingDescriptionPlaceholder": "Geburtstagsgeschenk für Angela",
2024
"tag": "Schlagwort",

resources/assets/js/prototype/translations/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"amount": "Amount",
33
"create": "Create",
4+
"currency": "Currency",
45
"dailyBalanceGraphDescription": "Here is your balance throughout the month",
56
"dashboard": "Dashboard",
67
"date": "Date",
@@ -13,8 +14,11 @@
1314
"goodMorning": "Good morning",
1415
"language": "Language",
1516
"logIn": "Log in",
17+
"name": "Name",
1618
"password": "Password",
1719
"recurringDescription": "This is a recurring transaction—create it for me in the future",
20+
"register": "Register",
21+
"repeatPassword": "Repeat password",
1822
"spending": "Spending",
1923
"spendingDescriptionPlaceholder": "Birthday present for Angela",
2024
"tag": "Tag",

resources/assets/js/prototype/translations/nl.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"amount": "Bedrag",
33
"create": "Creëer",
4+
"currency": "Valuta",
45
"dailyBalanceGraphDescription": "Dit is je balans gedurende deze maand",
56
"dashboard": "Dashboard",
67
"date": "Datum",
@@ -13,8 +14,11 @@
1314
"goodMorning": "Goedemorgen",
1415
"language": "Taal",
1516
"logIn": "Log in",
17+
"name": "Naam",
1618
"password": "Wachtwoord",
1719
"recurringDescription": "Dit is een terugkerende transactie–maak deze in de toekomst voor mij aan",
20+
"register": "Registreer",
21+
"repeatPassword": "Herhaal wachtwoord",
1822
"spending": "Uitgave",
1923
"spendingDescriptionPlaceholder": "Verjaardagscadeau voor Angela",
2024
"tag": "Etiket",

resources/assets/js/prototype/translations/ru.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"amount": "Сумма",
33
"create": "Создать",
4+
"currency": "Валюта",
45
"dailyBalanceGraphDescription": "Здесь отображается ваш баланс в течение месяца",
56
"dashboard": "Панель приборов",
67
"date": "Дата",
@@ -13,8 +14,11 @@
1314
"goodMorning": "Доброе утро",
1415
"language": "Язык",
1516
"logIn": "Войти",
17+
"name": "Имя",
1618
"password": "Пароль",
1719
"recurringDescription": "Это повторяющаяся транзакция—создайте ее для меня в будущем",
20+
"register": "Зарегистрируй",
21+
"repeatPassword": "Повтори пароль",
1822
"spending": "Расход",
1923
"spendingDescriptionPlaceholder": "Подарок на день рождения для Анжелы",
2024
"tag": "Тег",

0 commit comments

Comments
 (0)