feat: manage genders (monicahq/chandler#11)

This commit is contained in:
Regis Freyd
2021-12-16 10:55:48 -05:00
committed by GitHub
parent d16a4e651b
commit 598e7043ee
55 changed files with 1640 additions and 989 deletions
+1
View File
@@ -0,0 +1 @@
/resources/js/app.js
+96
View File
@@ -0,0 +1,96 @@
module.exports = {
'env': {
'browser': true,
'es6': true
},
'extends': [
'plugin:vue/recommended'
],
'parserOptions': {
'ecmaVersion': 12,
'sourceType': 'module'
},
'plugins': [
'vue',
],
'rules': {
'array-bracket-spacing': [
'error',
'never'
],
'indent': [
'error',
2
],
'linebreak-style': [
'error',
'unix'
],
'no-trailing-spaces': [
'error',
{
'ignoreComments': true,
'skipBlankLines': true
}
],
'quotes': [
'error',
'single'
],
'semi': [
'error',
'always'
],
'semi-spacing': [
'error',
{
'after': true,
'before': false
}
],
'semi-style': [
'error',
'last'
],
// strongly recommended
'vue/component-name-in-template-casing': [
'error',
'kebab-case'
],
'vue/component-tags-order': [
'warn',
{
'order': [['style', 'template'], 'script']
}
],
'vue/html-end-tags': 'error',
'vue/html-self-closing': [
'error',
{
'html': {
'normal': 'always',
'void': 'never'
}
}
],
'vue/no-v-model-argument': 0,
'vue/no-v-html': 0,
'vue/max-attributes-per-line': [
// https://vuejs.org/v2/style-guide/#Multi-attribute-elements-strongly-recommended
'error',
{
'singleline': 5,
'multiline': {
'max': 5,
'allowFirstLine': true
}
}
],
'vue/singleline-html-element-content-newline': ['error', {
'ignoreWhenNoAttributes': true,
'ignoreWhenEmpty': true,
'ignores': ['pre', 'textarea', 'inertia-link', 'a', 'p', 'li']
}]
}
};
@@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers\Settings\Personalize\Genders;
use Inertia\Inertia;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Services\Account\ManageGenders\CreateGender;
use App\Services\Account\ManageGenders\UpdateGender;
use App\Services\Account\ManageGenders\DestroyGender;
use App\Http\Controllers\Vault\ViewHelpers\VaultIndexViewHelper;
use App\Http\Controllers\Settings\Personalize\Genders\ViewHelpers\PersonalizeGenderIndexViewHelper;
class PersonalizeGenderController extends Controller
{
public function index()
{
return Inertia::render('Settings/Personalize/Genders/Index', [
'layoutData' => VaultIndexViewHelper::layoutData(),
'data' => PersonalizeGenderIndexViewHelper::data(Auth::user()->account),
]);
}
public function store(Request $request)
{
$data = [
'account_id' => Auth::user()->account_id,
'author_id' => Auth::user()->id,
'name' => $request->input('name'),
];
$gender = (new CreateGender)->execute($data);
return response()->json([
'data' => PersonalizeGenderIndexViewHelper::dtoGender($gender),
], 201);
}
public function update(Request $request, int $genderId)
{
$data = [
'account_id' => Auth::user()->account_id,
'author_id' => Auth::user()->id,
'gender_id' => $genderId,
'name' => $request->input('name'),
];
$gender = (new UpdateGender)->execute($data);
return response()->json([
'data' => PersonalizeGenderIndexViewHelper::dtoGender($gender),
], 200);
}
public function destroy(Request $request, int $genderId)
{
$data = [
'account_id' => Auth::user()->account_id,
'author_id' => Auth::user()->id,
'gender_id' => $genderId,
];
(new DestroyGender)->execute($data);
return response()->json([
'data' => true,
], 200);
}
}
@@ -0,0 +1,46 @@
<?php
namespace App\Http\Controllers\Settings\Personalize\Genders\ViewHelpers;
use App\Models\Gender;
use App\Models\Account;
class PersonalizeGenderIndexViewHelper
{
public static function data(Account $account): array
{
$genders = $account->genders()
->orderBy('name', 'asc')
->get();
$collection = collect();
foreach ($genders as $gender) {
$collection->push(self::dtoGender($gender));
}
return [
'genders' => $collection,
'url' => [
'settings' => route('settings.index'),
'personalize' => route('settings.personalize.index'),
'gender_store' => route('settings.personalize.gender.store'),
],
];
}
public static function dtoGender(Gender $gender): array
{
return [
'id' => $gender->id,
'name' => $gender->name,
'url' => [
'update' => route('settings.personalize.gender.update', [
'gender' => $gender->id,
]),
'destroy' => route('settings.personalize.gender.destroy', [
'gender' => $gender->id,
]),
],
];
}
}
@@ -12,6 +12,7 @@ class PersonalizeIndexViewHelper
'back' => route('settings.index'),
'manage_relationships' => route('settings.personalize.relationship.index'),
'manage_labels' => route('settings.personalize.label.index'),
'manage_genders' => route('settings.personalize.gender.index'),
],
];
}
@@ -19,8 +19,8 @@ class DestroyGender extends BaseService implements ServiceInterface
{
return [
'account_id' => 'required|integer|exists:accounts,id',
'gender_id' => 'required|integer|exists:genders,id',
'author_id' => 'required|integer|exists:users,id',
'gender_id' => 'required|integer|exists:genders,id',
];
}
+3 -3
View File
@@ -1,5 +1,5 @@
<template>
<svg viewBox="0 0 316 316" xmlns="http://www.w3.org/2000/svg">
<path d="M305.8 81.125C305.77 80.995 305.69 80.885 305.65 80.755C305.56 80.525 305.49 80.285 305.37 80.075C305.29 79.935 305.17 79.815 305.07 79.685C304.94 79.515 304.83 79.325 304.68 79.175C304.55 79.045 304.39 78.955 304.25 78.845C304.09 78.715 303.95 78.575 303.77 78.475L251.32 48.275C249.97 47.495 248.31 47.495 246.96 48.275L194.51 78.475C194.33 78.575 194.19 78.725 194.03 78.845C193.89 78.955 193.73 79.045 193.6 79.175C193.45 79.325 193.34 79.515 193.21 79.685C193.11 79.815 192.99 79.935 192.91 80.075C192.79 80.285 192.71 80.525 192.63 80.755C192.58 80.875 192.51 80.995 192.48 81.125C192.38 81.495 192.33 81.875 192.33 82.265V139.625L148.62 164.795V52.575C148.62 52.185 148.57 51.805 148.47 51.435C148.44 51.305 148.36 51.195 148.32 51.065C148.23 50.835 148.16 50.595 148.04 50.385C147.96 50.245 147.84 50.125 147.74 49.995C147.61 49.825 147.5 49.635 147.35 49.485C147.22 49.355 147.06 49.265 146.92 49.155C146.76 49.025 146.62 48.885 146.44 48.785L93.99 18.585C92.64 17.805 90.98 17.805 89.63 18.585L37.18 48.785C37 48.885 36.86 49.035 36.7 49.155C36.56 49.265 36.4 49.355 36.27 49.485C36.12 49.635 36.01 49.825 35.88 49.995C35.78 50.125 35.66 50.245 35.58 50.385C35.46 50.595 35.38 50.835 35.3 51.065C35.25 51.185 35.18 51.305 35.15 51.435C35.05 51.805 35 52.185 35 52.575V232.235C35 233.795 35.84 235.245 37.19 236.025L142.1 296.425C142.33 296.555 142.58 296.635 142.82 296.725C142.93 296.765 143.04 296.835 143.16 296.865C143.53 296.965 143.9 297.015 144.28 297.015C144.66 297.015 145.03 296.965 145.4 296.865C145.5 296.835 145.59 296.775 145.69 296.745C145.95 296.655 146.21 296.565 146.45 296.435L251.36 236.035C252.72 235.255 253.55 233.815 253.55 232.245V174.885L303.81 145.945C305.17 145.165 306 143.725 306 142.155V82.265C305.95 81.875 305.89 81.495 305.8 81.125ZM144.2 227.205L100.57 202.515L146.39 176.135L196.66 147.195L240.33 172.335L208.29 190.625L144.2 227.205ZM244.75 114.995V164.795L226.39 154.225L201.03 139.625V89.825L219.39 100.395L244.75 114.995ZM249.12 57.105L292.81 82.265L249.12 107.425L205.43 82.265L249.12 57.105ZM114.49 184.425L96.13 194.995V85.305L121.49 70.705L139.85 60.135V169.815L114.49 184.425ZM91.76 27.425L135.45 52.585L91.76 77.745L48.07 52.585L91.76 27.425ZM43.67 60.135L62.03 70.705L87.39 85.305V202.545V202.555V202.565C87.39 202.735 87.44 202.895 87.46 203.055C87.49 203.265 87.49 203.485 87.55 203.695V203.705C87.6 203.875 87.69 204.035 87.76 204.195C87.84 204.375 87.89 204.575 87.99 204.745C87.99 204.745 87.99 204.755 88 204.755C88.09 204.905 88.22 205.035 88.33 205.175C88.45 205.335 88.55 205.495 88.69 205.635L88.7 205.645C88.82 205.765 88.98 205.855 89.12 205.965C89.28 206.085 89.42 206.225 89.59 206.325C89.6 206.325 89.6 206.325 89.61 206.335C89.62 206.335 89.62 206.345 89.63 206.345L139.87 234.775V285.065L43.67 229.705V60.135ZM244.75 229.705L148.58 285.075V234.775L219.8 194.115L244.75 179.875V229.705ZM297.2 139.625L253.49 164.795V114.995L278.85 100.395L297.21 89.825V139.625H297.2Z"/>
</svg>
<svg viewBox="0 0 316 316" xmlns="http://www.w3.org/2000/svg">
<path d="M305.8 81.125C305.77 80.995 305.69 80.885 305.65 80.755C305.56 80.525 305.49 80.285 305.37 80.075C305.29 79.935 305.17 79.815 305.07 79.685C304.94 79.515 304.83 79.325 304.68 79.175C304.55 79.045 304.39 78.955 304.25 78.845C304.09 78.715 303.95 78.575 303.77 78.475L251.32 48.275C249.97 47.495 248.31 47.495 246.96 48.275L194.51 78.475C194.33 78.575 194.19 78.725 194.03 78.845C193.89 78.955 193.73 79.045 193.6 79.175C193.45 79.325 193.34 79.515 193.21 79.685C193.11 79.815 192.99 79.935 192.91 80.075C192.79 80.285 192.71 80.525 192.63 80.755C192.58 80.875 192.51 80.995 192.48 81.125C192.38 81.495 192.33 81.875 192.33 82.265V139.625L148.62 164.795V52.575C148.62 52.185 148.57 51.805 148.47 51.435C148.44 51.305 148.36 51.195 148.32 51.065C148.23 50.835 148.16 50.595 148.04 50.385C147.96 50.245 147.84 50.125 147.74 49.995C147.61 49.825 147.5 49.635 147.35 49.485C147.22 49.355 147.06 49.265 146.92 49.155C146.76 49.025 146.62 48.885 146.44 48.785L93.99 18.585C92.64 17.805 90.98 17.805 89.63 18.585L37.18 48.785C37 48.885 36.86 49.035 36.7 49.155C36.56 49.265 36.4 49.355 36.27 49.485C36.12 49.635 36.01 49.825 35.88 49.995C35.78 50.125 35.66 50.245 35.58 50.385C35.46 50.595 35.38 50.835 35.3 51.065C35.25 51.185 35.18 51.305 35.15 51.435C35.05 51.805 35 52.185 35 52.575V232.235C35 233.795 35.84 235.245 37.19 236.025L142.1 296.425C142.33 296.555 142.58 296.635 142.82 296.725C142.93 296.765 143.04 296.835 143.16 296.865C143.53 296.965 143.9 297.015 144.28 297.015C144.66 297.015 145.03 296.965 145.4 296.865C145.5 296.835 145.59 296.775 145.69 296.745C145.95 296.655 146.21 296.565 146.45 296.435L251.36 236.035C252.72 235.255 253.55 233.815 253.55 232.245V174.885L303.81 145.945C305.17 145.165 306 143.725 306 142.155V82.265C305.95 81.875 305.89 81.495 305.8 81.125ZM144.2 227.205L100.57 202.515L146.39 176.135L196.66 147.195L240.33 172.335L208.29 190.625L144.2 227.205ZM244.75 114.995V164.795L226.39 154.225L201.03 139.625V89.825L219.39 100.395L244.75 114.995ZM249.12 57.105L292.81 82.265L249.12 107.425L205.43 82.265L249.12 57.105ZM114.49 184.425L96.13 194.995V85.305L121.49 70.705L139.85 60.135V169.815L114.49 184.425ZM91.76 27.425L135.45 52.585L91.76 77.745L48.07 52.585L91.76 27.425ZM43.67 60.135L62.03 70.705L87.39 85.305V202.545V202.555V202.565C87.39 202.735 87.44 202.895 87.46 203.055C87.49 203.265 87.49 203.485 87.55 203.695V203.705C87.6 203.875 87.69 204.035 87.76 204.195C87.84 204.375 87.89 204.575 87.99 204.745C87.99 204.745 87.99 204.755 88 204.755C88.09 204.905 88.22 205.035 88.33 205.175C88.45 205.335 88.55 205.495 88.69 205.635L88.7 205.645C88.82 205.765 88.98 205.855 89.12 205.965C89.28 206.085 89.42 206.225 89.59 206.325C89.6 206.325 89.6 206.325 89.61 206.335C89.62 206.335 89.62 206.345 89.63 206.345L139.87 234.775V285.065L43.67 229.705V60.135ZM244.75 229.705L148.58 285.075V234.775L219.8 194.115L244.75 179.875V229.705ZM297.2 139.625L253.49 164.795V114.995L278.85 100.395L297.21 89.825V139.625H297.2Z" />
</svg>
</template>
+10 -10
View File
@@ -1,16 +1,16 @@
<template>
<button :type="type" class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:shadow-outline-gray transition ease-in-out duration-150">
<slot />
</button>
<button :type="type" class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:shadow-outline-gray transition ease-in-out duration-150">
<slot />
</button>
</template>
<script>
export default {
props: {
type: {
type: String,
default: 'submit',
},
}
}
props: {
type: {
type: String,
default: 'submit',
},
}
};
</script>
+25 -23
View File
@@ -1,32 +1,34 @@
<template>
<input type="checkbox" :value="value" v-model="proxyChecked"
class="rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<input v-model="proxyChecked" type="checkbox" :value="value"
class="rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
>
</template>
<script>
export default {
emits: ['update:checked'],
props: {
checked: {
type: [Array, Boolean],
default: false,
},
value: {
default: null,
},
props: {
checked: {
type: [Array, Boolean],
default: false,
},
computed: {
proxyChecked: {
get() {
return this.checked;
},
set(val) {
this.$emit("update:checked", val);
},
},
value: {
type: [String, Number],
default: null,
},
}
},
emits: ['update:checked'],
computed: {
proxyChecked: {
get() {
return this.checked;
},
set(val) {
this.$emit('update:checked', val);
},
},
},
};
</script>
+75 -70
View File
@@ -1,81 +1,86 @@
<template>
<div class="relative">
<div @click="open = ! open">
<slot name="trigger" />
</div>
<!-- Full Screen Dropdown Overlay -->
<div v-show="open" class="fixed inset-0 z-40" @click="open = false"></div>
<transition
enter-active-class="transition ease-out duration-200"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95">
<div v-show="open"
class="absolute z-50 mt-2 rounded-md shadow-lg"
:class="[widthClass, alignmentClasses]"
style="display: none;"
@click="open = false">
<div class="rounded-md ring-1 ring-black ring-opacity-5" :class="contentClasses">
<slot name="content" />
</div>
</div>
</transition>
<div class="relative">
<div @click="open = ! open">
<slot name="trigger" />
</div>
<!-- Full Screen Dropdown Overlay -->
<div v-show="open" class="fixed inset-0 z-40" @click="open = false" />
<transition
enter-active-class="transition ease-out duration-200"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95"
>
<div v-show="open"
class="absolute z-50 mt-2 rounded-md shadow-lg"
:class="[widthClass, alignmentClasses]"
style="display: none;"
@click="open = false"
>
<div class="rounded-md ring-1 ring-black ring-opacity-5" :class="contentClasses">
<slot name="content" />
</div>
</div>
</transition>
</div>
</template>
<script>
import { onMounted, onUnmounted, ref } from 'vue'
import { onMounted, onUnmounted, ref } from 'vue';
export default {
props: {
align: {
default: 'right'
},
width: {
default: '48'
},
contentClasses: {
default: () => ['py-1', 'bg-white']
}
props: {
align: {
type: String,
default: 'right'
},
setup() {
let open = ref(false)
const closeOnEscape = (e) => {
if (open.value && e.keyCode === 27) {
open.value = false
}
}
onMounted(() => document.addEventListener('keydown', closeOnEscape))
onUnmounted(() => document.removeEventListener('keydown', closeOnEscape))
return {
open,
}
width: {
type: String,
default: '48'
},
computed: {
widthClass() {
return {
'48': 'w-48',
}[this.width.toString()]
},
alignmentClasses() {
if (this.align === 'left') {
return 'origin-top-left left-0'
} else if (this.align === 'right') {
return 'origin-top-right right-0'
} else {
return 'origin-top'
}
},
contentClasses: {
type: [String, Array],
default: () => ['py-1', 'bg-white']
}
}
},
setup() {
let open = ref(false);
const closeOnEscape = (e) => {
if (open.value && e.keyCode === 27) {
open.value = false;
}
};
onMounted(() => document.addEventListener('keydown', closeOnEscape));
onUnmounted(() => document.removeEventListener('keydown', closeOnEscape));
return {
open,
};
},
computed: {
widthClass() {
return {
'48': 'w-48',
}[this.width.toString()];
},
alignmentClasses() {
if (this.align === 'left') {
return 'origin-top-left left-0';
} else if (this.align === 'right') {
return 'origin-top-right right-0';
} else {
return 'origin-top';
}
},
}
};
</script>
+7 -8
View File
@@ -1,15 +1,14 @@
<template>
<Link class="block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out">
<slot />
</Link>
<inertia-link class="block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out">
<slot />
</inertia-link>
</template>
<script>
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
Link,
}
}
components: {
}
};
</script>
+13 -8
View File
@@ -1,17 +1,22 @@
<template>
<input class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" ref="input">
<input ref="input" class="border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
</template>
<script>
export default {
props: ['modelValue'],
props: {
'modelValue': {
type: String,
default: '',
},
},
emits: ['update:modelValue'],
emits: ['update:modelValue'],
methods: {
focus() {
this.$refs.input.focus()
}
methods: {
focus() {
this.$refs.input.focus();
}
}
}
};
</script>
+12 -7
View File
@@ -1,13 +1,18 @@
<template>
<div v-show="message">
<p class="text-sm text-red-600">
{{ message }}
</p>
</div>
<div v-show="message">
<p class="text-sm text-red-600">
{{ message }}
</p>
</div>
</template>
<script>
export default {
props: ['message']
}
props: {
'message': {
type: String,
default: '',
},
},
};
</script>
+15 -6
View File
@@ -1,12 +1,21 @@
<template>
<label class="block font-medium text-sm text-gray-700">
<span v-if="value">{{ value }}</span>
<span v-else><slot /></span>
</label>
<label class="block font-medium text-sm text-gray-700">
<span v-if="value">
{{ value }}
</span>
<span v-else>
<slot />
</span>
</label>
</template>
<script>
export default {
props: ['value']
}
props: {
value: {
type: String,
default: null,
},
},
};
</script>
+20 -15
View File
@@ -1,25 +1,30 @@
<template>
<Link :href="href" :class="classes">
<slot />
</Link>
<inertia-link :href="href" :class="classes">
<slot />
</inertia-link>
</template>
<script>
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
Link,
props: {
href: {
type: String,
default: null,
},
active: {
type: Boolean,
default: false,
},
},
props: ['href', 'active'],
computed: {
classes() {
return this.active
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out'
}
computed: {
classes() {
return this.active
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
}
}
}
};
</script>
+20 -15
View File
@@ -1,25 +1,30 @@
<template>
<Link :href="href" :class="classes">
<slot />
</Link>
<inertia-link :href="href" :class="classes">
<slot />
</inertia-link>
</template>
<script>
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
Link,
props: {
href: {
type: String,
default: null,
},
active: {
type: Boolean,
default: false,
},
},
props: ['href', 'active'],
computed: {
classes() {
return this.active
? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
: 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out'
}
computed: {
classes() {
return this.active
? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
: 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
}
}
}
};
</script>
+17 -15
View File
@@ -1,23 +1,25 @@
<template>
<div v-if="hasErrors">
<div class="font-medium text-red-600">Whoops! Something went wrong.</div>
<ul class="mt-3 list-disc list-inside text-sm text-red-600">
<li v-for="(error, key) in errors" :key="key">{{ error }}</li>
</ul>
<div v-if="hasErrors">
<div class="font-medium text-red-600">
Whoops! Something went wrong.
</div>
<ul class="mt-3 list-disc list-inside text-sm text-red-600">
<li v-for="(error, key) in errors" :key="key">{{ error }}</li>
</ul>
</div>
</template>
<script>
export default {
computed: {
errors() {
return this.$page.props.errors
},
computed: {
errors() {
return this.$page.props.errors;
},
hasErrors() {
return Object.keys(this.errors).length > 0
},
}
}
hasErrors() {
return Object.keys(this.errors).length > 0;
},
}
};
</script>
+47 -38
View File
@@ -1,59 +1,68 @@
<template>
<Head title="Register" />
<div>
<breeze-validation-errors class="mb-4" />
<BreezeValidationErrors class="mb-4" />
<form @submit.prevent="submit">
<h1 class="text-center mb-3 text-xl">
<span class="mr-2">
👋
</span> Welcome to Monica.
</h1>
<p class="mb-4 text-center">Please complete this form to finalize your account.</p>
<form @submit.prevent="submit">
<h1 class="text-center mb-3 text-xl"><span class="mr-2">👋</span> Welcome to Monica.</h1>
<p class="mb-4 text-center">Please complete this form to finalize your account.</p>
<div>
<breeze-label for="first_name" value="First name" />
<breeze-input id="first_name" v-model="form.first_name" type="text" class="mt-1 block w-full" required
autofocus autocomplete="first_name"
/>
</div>
<div>
<BreezeLabel for="first_name" value="First name" />
<BreezeInput id="first_name" type="text" class="mt-1 block w-full" v-model="form.first_name" required autofocus autocomplete="first_name" />
</div>
<div class="mt-4">
<breeze-label for="last_name" value="Last name" />
<breeze-input id="last_name" v-model="form.last_name" type="text" class="mt-1 block w-full" required
autocomplete="last_name"
/>
</div>
<div class="mt-4">
<BreezeLabel for="last_name" value="Last name" />
<BreezeInput id="last_name" type="text" class="mt-1 block w-full" v-model="form.last_name" required autocomplete="last_name" />
</div>
<div class="mt-4">
<breeze-label for="password" value="Password" />
<breeze-input id="password" v-model="form.password" type="password" class="mt-1 block w-full" required
autocomplete="new-password"
/>
</div>
<div class="mt-4">
<BreezeLabel for="password" value="Password" />
<BreezeInput id="password" type="password" class="mt-1 block w-full" v-model="form.password" required autocomplete="new-password" />
</div>
<div class="mt-4">
<breeze-label for="password_confirmation" value="Confirm Password" />
<breeze-input id="password_confirmation" v-model="form.password_confirmation" type="password" class="mt-1 block w-full" required
autocomplete="new-password"
/>
</div>
<div class="mt-4">
<BreezeLabel for="password_confirmation" value="Confirm Password" />
<BreezeInput id="password_confirmation" type="password" class="mt-1 block w-full" v-model="form.password_confirmation" required autocomplete="new-password" />
</div>
<div class="flex items-center justify-end mt-4">
<BreezeButton class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Create account
</BreezeButton>
</div>
<div class="flex items-center justify-end mt-4">
<breeze-button class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Create account
</breeze-button>
</div>
</form>
</div>
</template>
<script>
import BreezeButton from '@/Components/Button.vue'
import BreezeGuestLayout from '@/Shared/Guest.vue'
import BreezeInput from '@/Components/Input.vue'
import BreezeLabel from '@/Components/Label.vue'
import BreezeValidationErrors from '@/Components/ValidationErrors.vue'
import { Head, Link } from '@inertiajs/inertia-vue3';
import BreezeButton from '@/Components/Button.vue';
import BreezeGuestLayout from '@/Shared/Guest.vue';
import BreezeInput from '@/Components/Input.vue';
import BreezeLabel from '@/Components/Label.vue';
import BreezeValidationErrors from '@/Components/ValidationErrors.vue';
export default {
layout: BreezeGuestLayout,
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
Head,
Link,
},
layout: BreezeGuestLayout,
props: {
data: {
@@ -71,7 +80,7 @@ export default {
password_confirmation: '',
invitation_code: '',
},
}
};
},
mounted() {
@@ -92,5 +101,5 @@ export default {
});
},
}
}
};
</script>
+41 -41
View File
@@ -1,59 +1,59 @@
<template>
<Head title="Confirm Password" />
<div>
<div class="mb-4 text-sm text-gray-600">
This is a secure area of the application. Please confirm your password before continuing.
This is a secure area of the application. Please confirm your password before continuing.
</div>
<BreezeValidationErrors class="mb-4" />
<breeze-validation-errors class="mb-4" />
<form @submit.prevent="submit">
<div>
<BreezeLabel for="password" value="Password" />
<BreezeInput id="password" type="password" class="mt-1 block w-full" v-model="form.password" required autocomplete="current-password" autofocus />
</div>
<div>
<breeze-label for="password" value="Password" />
<breeze-input id="password" v-model="form.password" type="password" class="mt-1 block w-full" required
autocomplete="current-password" autofocus
/>
</div>
<div class="flex justify-end mt-4">
<BreezeButton class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Confirm
</BreezeButton>
</div>
<div class="flex justify-end mt-4">
<breeze-button class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Confirm
</breeze-button>
</div>
</form>
</div>
</template>
<script>
import BreezeButton from '@/Components/Button.vue'
import BreezeGuestLayout from '@/Shared/Guest.vue'
import BreezeInput from '@/Components/Input.vue'
import BreezeLabel from '@/Components/Label.vue'
import BreezeValidationErrors from '@/Components/ValidationErrors.vue'
import { Head } from '@inertiajs/inertia-vue3';
import BreezeButton from '@/Components/Button.vue';
import BreezeGuestLayout from '@/Shared/Guest.vue';
import BreezeInput from '@/Components/Input.vue';
import BreezeLabel from '@/Components/Label.vue';
import BreezeValidationErrors from '@/Components/ValidationErrors.vue';
export default {
layout: BreezeGuestLayout,
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
Head,
},
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
},
layout: BreezeGuestLayout,
data() {
return {
form: this.$inertia.form({
password: '',
})
}
},
data() {
return {
form: this.$inertia.form({
password: '',
})
};
},
methods: {
submit() {
this.form.post(this.route('password.confirm'), {
onFinish: () => this.form.reset(),
})
}
methods: {
submit() {
this.form.post(this.route('password.confirm'), {
onFinish: () => this.form.reset(),
});
}
}
}
};
</script>
+46 -43
View File
@@ -1,65 +1,68 @@
<template>
<Head title="Forgot Password" />
<div>
<div class="mb-4 text-sm text-gray-600">
Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.
Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.
</div>
<div v-if="status" class="mb-4 font-medium text-sm text-green-600">
{{ status }}
{{ status }}
</div>
<BreezeValidationErrors class="mb-4" />
<breeze-validation-errors class="mb-4" />
<form @submit.prevent="submit">
<div>
<BreezeLabel for="email" value="Email" />
<BreezeInput id="email" type="email" class="mt-1 block w-full" v-model="form.email" required autofocus autocomplete="username" />
</div>
<div>
<breeze-label for="email" value="Email" />
<breeze-input id="email" v-model="form.email" type="email" class="mt-1 block w-full" required
autofocus autocomplete="username"
/>
</div>
<div class="flex items-center justify-end mt-4">
<BreezeButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Email Password Reset Link
</BreezeButton>
</div>
<div class="flex items-center justify-end mt-4">
<breeze-button :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Email Password Reset Link
</breeze-button>
</div>
</form>
</div>
</template>
<script>
import BreezeButton from '@/Components/Button.vue'
import BreezeGuestLayout from '@/Shared/Guest.vue'
import BreezeInput from '@/Components/Input.vue'
import BreezeLabel from '@/Components/Label.vue'
import BreezeValidationErrors from '@/Components/ValidationErrors.vue'
import { Head } from '@inertiajs/inertia-vue3';
import BreezeButton from '@/Components/Button.vue';
import BreezeGuestLayout from '@/Shared/Guest.vue';
import BreezeInput from '@/Components/Input.vue';
import BreezeLabel from '@/Components/Label.vue';
import BreezeValidationErrors from '@/Components/ValidationErrors.vue';
export default {
layout: BreezeGuestLayout,
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
Head,
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
},
layout: BreezeGuestLayout,
props: {
status: {
type: String,
default: '',
},
},
props: {
status: String,
},
data() {
return {
form: this.$inertia.form({
email: ''
})
};
},
data() {
return {
form: this.$inertia.form({
email: ''
})
}
},
methods: {
submit() {
this.form.post(this.route('password.email'))
}
methods: {
submit() {
this.form.post(this.route('password.email'));
}
}
}
};
</script>
+71 -62
View File
@@ -1,85 +1,94 @@
<template>
<Head title="Log in" />
<BreezeValidationErrors class="mb-4" />
<div>
<breeze-validation-errors class="mb-4" />
<div v-if="status" class="mb-4 font-medium text-sm text-green-600">
{{ status }}
{{ status }}
</div>
<form @submit.prevent="submit">
<div>
<BreezeLabel for="email" value="Email" />
<BreezeInput id="email" type="email" class="mt-1 block w-full" v-model="form.email" required autofocus autocomplete="username" />
</div>
<div>
<breeze-label for="email" value="Email" />
<breeze-input id="email" v-model="form.email" type="email" class="mt-1 block w-full" required
autofocus autocomplete="username"
/>
</div>
<div class="mt-4">
<BreezeLabel for="password" value="Password" />
<BreezeInput id="password" type="password" class="mt-1 block w-full" v-model="form.password" required autocomplete="current-password" />
</div>
<div class="mt-4">
<breeze-label for="password" value="Password" />
<breeze-input id="password" v-model="form.password" type="password" class="mt-1 block w-full" required
autocomplete="current-password"
/>
</div>
<div class="block mt-4">
<label class="flex items-center">
<BreezeCheckbox name="remember" v-model:checked="form.remember" />
<span class="ml-2 text-sm text-gray-600">Remember me</span>
</label>
</div>
<div class="block mt-4">
<label class="flex items-center">
<breeze-checkbox v-model:checked="form.remember" name="remember" />
<span class="ml-2 text-sm text-gray-600">
Remember me
</span>
</label>
</div>
<div class="flex items-center justify-end mt-4">
<Link v-if="canResetPassword" :href="route('password.request')" class="underline text-sm text-gray-600 hover:text-gray-900">
Forgot your password?
</Link>
<div class="flex items-center justify-end mt-4">
<inertia-link v-if="canResetPassword" :href="route('password.request')" class="underline text-sm text-gray-600 hover:text-gray-900">
Forgot your password?
</inertia-link>
<BreezeButton class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Log in
</BreezeButton>
</div>
<breeze-button class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Log in
</breeze-button>
</div>
</form>
</div>
</template>
<script>
import BreezeButton from '@/Components/Button.vue'
import BreezeCheckbox from '@/Components/Checkbox.vue'
import BreezeGuestLayout from '@/Shared/Guest.vue'
import BreezeInput from '@/Components/Input.vue'
import BreezeLabel from '@/Components/Label.vue'
import BreezeValidationErrors from '@/Components/ValidationErrors.vue'
import { Head, Link } from '@inertiajs/inertia-vue3';
import BreezeButton from '@/Components/Button.vue';
import BreezeCheckbox from '@/Components/Checkbox.vue';
import BreezeGuestLayout from '@/Shared/Guest.vue';
import BreezeInput from '@/Components/Input.vue';
import BreezeLabel from '@/Components/Label.vue';
import BreezeValidationErrors from '@/Components/ValidationErrors.vue';
export default {
layout: BreezeGuestLayout,
components: {
BreezeButton,
BreezeCheckbox,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
Head,
Link,
components: {
BreezeButton,
BreezeCheckbox,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
},
layout: BreezeGuestLayout,
props: {
status: {
type: String,
default: null,
},
props: {
canResetPassword: Boolean,
status: String,
canResetPassword: {
type: Boolean,
default: false,
},
},
data() {
return {
form: this.$inertia.form({
email: '',
password: '',
remember: false
})
}
},
data() {
return {
form: this.$inertia.form({
email: '',
password: '',
remember: false
})
};
},
methods: {
submit() {
this.form.post(this.route('login'), {
onFinish: () => this.form.reset('password'),
})
}
methods: {
submit() {
this.form.post(this.route('login'), {
onFinish: () => this.form.reset('password'),
});
}
}
}
};
</script>
+72 -65
View File
@@ -1,85 +1,92 @@
<template>
<Head title="Register" />
<BreezeValidationErrors class="mb-4" />
<div>
<breeze-validation-errors class="mb-4" />
<form @submit.prevent="submit">
<div>
<BreezeLabel for="first_name" value="First name" />
<BreezeInput id="first_name" type="text" class="mt-1 block w-full" v-model="form.first_name" required autofocus autocomplete="first_name" />
</div>
<div>
<breeze-label for="first_name" value="First name" />
<breeze-input id="first_name" v-model="form.first_name" type="text" class="mt-1 block w-full" required
autofocus autocomplete="first_name"
/>
</div>
<div class="mt-4">
<BreezeLabel for="last_name" value="Last name" />
<BreezeInput id="last_name" type="text" class="mt-1 block w-full" v-model="form.last_name" required autocomplete="last_name" />
</div>
<div class="mt-4">
<breeze-label for="last_name" value="Last name" />
<breeze-input id="last_name" v-model="form.last_name" type="text" class="mt-1 block w-full" required
autocomplete="last_name"
/>
</div>
<div class="mt-4">
<BreezeLabel for="email" value="Email" />
<BreezeInput id="email" type="email" class="mt-1 block w-full" v-model="form.email" required autocomplete="username" />
</div>
<div class="mt-4">
<breeze-label for="email" value="Email" />
<breeze-input id="email" v-model="form.email" type="email" class="mt-1 block w-full" required
autocomplete="username"
/>
</div>
<div class="mt-4">
<BreezeLabel for="password" value="Password" />
<BreezeInput id="password" type="password" class="mt-1 block w-full" v-model="form.password" required autocomplete="new-password" />
</div>
<div class="mt-4">
<breeze-label for="password" value="Password" />
<breeze-input id="password" v-model="form.password" type="password" class="mt-1 block w-full" required
autocomplete="new-password"
/>
</div>
<div class="mt-4">
<BreezeLabel for="password_confirmation" value="Confirm Password" />
<BreezeInput id="password_confirmation" type="password" class="mt-1 block w-full" v-model="form.password_confirmation" required autocomplete="new-password" />
</div>
<div class="mt-4">
<breeze-label for="password_confirmation" value="Confirm Password" />
<breeze-input id="password_confirmation" v-model="form.password_confirmation" type="password" class="mt-1 block w-full" required
autocomplete="new-password"
/>
</div>
<div class="flex items-center justify-end mt-4">
<Link :href="route('login')" class="underline text-sm text-gray-600 hover:text-gray-900">
Already registered?
</Link>
<div class="flex items-center justify-end mt-4">
<inertia-link :href="route('login')" class="underline text-sm text-gray-600 hover:text-gray-900">
Already registered?
</inertia-link>
<BreezeButton class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Register
</BreezeButton>
</div>
<breeze-button class="ml-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Register
</breeze-button>
</div>
</form>
</div>
</template>
<script>
import BreezeButton from '@/Components/Button.vue'
import BreezeGuestLayout from '@/Shared/Guest.vue'
import BreezeInput from '@/Components/Input.vue'
import BreezeLabel from '@/Components/Label.vue'
import BreezeValidationErrors from '@/Components/ValidationErrors.vue'
import { Head, Link } from '@inertiajs/inertia-vue3';
import BreezeButton from '@/Components/Button.vue';
import BreezeGuestLayout from '@/Shared/Guest.vue';
import BreezeInput from '@/Components/Input.vue';
import BreezeLabel from '@/Components/Label.vue';
import BreezeValidationErrors from '@/Components/ValidationErrors.vue';
export default {
layout: BreezeGuestLayout,
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
Head,
Link,
},
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
},
layout: BreezeGuestLayout,
data() {
return {
form: this.$inertia.form({
first_name: '',
last_name: '',
email: '',
password: '',
password_confirmation: '',
terms: false,
})
}
},
data() {
return {
form: this.$inertia.form({
first_name: '',
last_name: '',
email: '',
password: '',
password_confirmation: '',
terms: false,
})
};
},
methods: {
submit() {
this.form.post(this.route('register'), {
onFinish: () => this.form.reset('password', 'password_confirmation'),
})
}
methods: {
submit() {
this.form.post(this.route('register'), {
onFinish: () => this.form.reset('password', 'password_confirmation'),
});
}
}
}
};
</script>
+64 -54
View File
@@ -1,73 +1,83 @@
<template>
<Head title="Reset Password" />
<BreezeValidationErrors class="mb-4" />
<div>
<breeze-validation-errors class="mb-4" />
<form @submit.prevent="submit">
<div>
<BreezeLabel for="email" value="Email" />
<BreezeInput id="email" type="email" class="mt-1 block w-full" v-model="form.email" required autofocus autocomplete="username" />
</div>
<div>
<breeze-label for="email" value="Email" />
<breeze-input id="email" v-model="form.email" type="email" class="mt-1 block w-full" required
autofocus autocomplete="username"
/>
</div>
<div class="mt-4">
<BreezeLabel for="password" value="Password" />
<BreezeInput id="password" type="password" class="mt-1 block w-full" v-model="form.password" required autocomplete="new-password" />
</div>
<div class="mt-4">
<breeze-label for="password" value="Password" />
<breeze-input id="password" v-model="form.password" type="password" class="mt-1 block w-full" required
autocomplete="new-password"
/>
</div>
<div class="mt-4">
<BreezeLabel for="password_confirmation" value="Confirm Password" />
<BreezeInput id="password_confirmation" type="password" class="mt-1 block w-full" v-model="form.password_confirmation" required autocomplete="new-password" />
</div>
<div class="mt-4">
<breeze-label for="password_confirmation" value="Confirm Password" />
<breeze-input id="password_confirmation" v-model="form.password_confirmation" type="password" class="mt-1 block w-full" required
autocomplete="new-password"
/>
</div>
<div class="flex items-center justify-end mt-4">
<BreezeButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Reset Password
</BreezeButton>
</div>
<div class="flex items-center justify-end mt-4">
<breeze-button :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Reset Password
</breeze-button>
</div>
</form>
</div>
</template>
<script>
import BreezeButton from '@/Components/Button.vue'
import BreezeGuestLayout from '@/Shared/Guest.vue'
import BreezeInput from '@/Components/Input.vue'
import BreezeLabel from '@/Components/Label.vue'
import BreezeValidationErrors from '@/Components/ValidationErrors.vue'
import { Head } from '@inertiajs/inertia-vue3';
import BreezeButton from '@/Components/Button.vue';
import BreezeGuestLayout from '@/Shared/Guest.vue';
import BreezeInput from '@/Components/Input.vue';
import BreezeLabel from '@/Components/Label.vue';
import BreezeValidationErrors from '@/Components/ValidationErrors.vue';
export default {
layout: BreezeGuestLayout,
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
Head,
components: {
BreezeButton,
BreezeInput,
BreezeLabel,
BreezeValidationErrors,
},
layout: BreezeGuestLayout,
props: {
email: {
type: String,
default: '',
},
props: {
email: String,
token: String,
token: {
type: String,
default: '',
},
},
data() {
return {
form: this.$inertia.form({
token: this.token,
email: this.email,
password: '',
password_confirmation: '',
})
}
},
data() {
return {
form: this.$inertia.form({
token: this.token,
email: this.email,
password: '',
password_confirmation: '',
})
};
},
methods: {
submit() {
this.form.post(this.route('password.update'), {
onFinish: () => this.form.reset('password', 'password_confirmation'),
})
}
methods: {
submit() {
this.form.post(this.route('password.update'), {
onFinish: () => this.form.reset('password', 'password_confirmation'),
});
}
}
}
};
</script>
+41 -39
View File
@@ -1,59 +1,61 @@
<template>
<Head title="Email Verification" />
<div>
<div class="mb-4 text-sm text-gray-600">
Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.
Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.
</div>
<div class="mb-4 font-medium text-sm text-green-600" v-if="verificationLinkSent" >
A new verification link has been sent to the email address you provided during registration.
<div v-if="verificationLinkSent" class="mb-4 font-medium text-sm text-green-600">
A new verification link has been sent to the email address you provided during registration.
</div>
<form @submit.prevent="submit">
<div class="mt-4 flex items-center justify-between">
<BreezeButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Resend Verification Email
</BreezeButton>
<div class="mt-4 flex items-center justify-between">
<breeze-button :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Resend Verification Email
</breeze-button>
<Link :href="route('logout')" method="post" as="button" class="underline text-sm text-gray-600 hover:text-gray-900">Log Out</Link>
</div>
<inertia-link :href="route('logout')" method="post" as="button" class="underline text-sm text-gray-600 hover:text-gray-900">
Log Out
</inertia-link>
</div>
</form>
</div>
</template>
<script>
import BreezeButton from '@/Components/Button.vue'
import BreezeGuestLayout from '@/Shared/Guest.vue'
import { Head, Link } from '@inertiajs/inertia-vue3';
import BreezeButton from '@/Components/Button.vue';
import BreezeGuestLayout from '@/Shared/Guest.vue';
export default {
layout: BreezeGuestLayout,
components: {
BreezeButton,
Head,
Link,
components: {
BreezeButton,
},
layout: BreezeGuestLayout,
props: {
status: {
type: String,
default: '',
},
},
props: {
status: String,
},
data() {
return {
form: this.$inertia.form()
};
},
data() {
return {
form: this.$inertia.form()
}
},
methods: {
submit() {
this.form.post(this.route('verification.send'))
},
},
computed: {
verificationLinkSent() {
return this.status === 'verification-link-sent';
}
computed: {
verificationLinkSent() {
return this.status === 'verification-link-sent';
}
}
},
methods: {
submit() {
this.form.post(this.route('verification.send'));
},
}
};
</script>
@@ -6,7 +6,7 @@
</style>
<template>
<Layout :layoutData="layoutData">
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -14,7 +14,7 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</Link>
<inertia-link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -29,12 +29,12 @@
<main class="sm:mt-24 relative">
<div class="max-w-lg mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<form @submit.prevent="destroy()" class="bg-white border border-gray-200 rounded-lg mb-6">
<form class="bg-white border border-gray-200 rounded-lg mb-6" @submit.prevent="destroy()">
<!-- title -->
<div class="p-5 border-b border-gray-200 bg-blue-50 section-head">
<h1 class="text-center text-2xl mb-4 font-medium">Cancel your account</h1>
<h1 class="text-center text-2xl mb-4 font-medium">
Cancel your account
</h1>
<p class="mb-2">Thanks for giving Monica a try.</p>
<p class="mb-2">Once you cancel,</p>
<ul class="pl-6 list-disc">
@@ -49,12 +49,13 @@
<errors :errors="form.errors" />
<text-input v-model="form.password"
:label="'Please enter your password to cancel the account'"
:type="'password'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255" />
:label="'Please enter your password to cancel the account'"
:type="'password'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
/>
</div>
<div class="p-5 flex justify-between">
@@ -64,7 +65,7 @@
</form>
</div>
</main>
</Layout>
</layout>
</template>
<script>
@@ -73,7 +74,6 @@ import PrettyLink from '@/Shared/PrettyLink';
import PrettyButton from '@/Shared/PrettyButton';
import TextInput from '@/Shared/TextInput';
import Errors from '@/Shared/Errors';
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
@@ -82,7 +82,6 @@ export default {
PrettyButton,
TextInput,
Errors,
Link,
},
props: {
+10 -12
View File
@@ -2,7 +2,7 @@
</style>
<template>
<Layout title="Dashboard" :layoutData="layoutData">
<layout title="Dashboard" :layout-data="layoutData">
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
<div class="flex items-baseline justify-between space-x-6">
@@ -16,42 +16,40 @@
<main class="sm:mt-20 relative">
<div class="max-w-md mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<h2 class="text-lg text-center mb-6">Account settings</h2>
<h2 class="text-lg text-center mb-6">
Account settings
</h2>
<div class="bg-white border border-gray-200 rounded-lg mb-6 p-5">
<ul>
<li class="mb-2">
<span class="mr-1">🥳</span>
<Link :href="data.url.preferences.index" class="text-sky-500 hover:text-blue-900">User preferences</Link>
<inertia-link :href="data.url.preferences.index" class="text-sky-500 hover:text-blue-900">User preferences</inertia-link>
</li>
<li v-if="data.is_account_administrator" class="mb-2">
<span class="mr-1">🥸</span>
<Link :href="data.url.users.index" class="text-sky-500 hover:text-blue-900">Manage users</Link>
<inertia-link :href="data.url.users.index" class="text-sky-500 hover:text-blue-900">Manage users</inertia-link>
</li>
<li v-if="data.is_account_administrator" class="mb-2">
<span class="mr-1">🎃</span>
<Link :href="data.url.personalize.index" class="text-sky-500 hover:text-blue-900">Personalize your contacts data</Link>
<inertia-link :href="data.url.personalize.index" class="text-sky-500 hover:text-blue-900">Personalize your contacts data</inertia-link>
</li>
<li v-if="data.is_account_administrator">
<span class="mr-1">💩</span>
<Link :href="data.url.cancel.index" class="text-sky-500 hover:text-blue-900">Cancel your account</Link>
<inertia-link :href="data.url.cancel.index" class="text-sky-500 hover:text-blue-900">Cancel your account</inertia-link>
</li>
</ul>
</div>
</div>
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
import PrettyLink from '@/Shared/PrettyLink';
export default {
components: {
Layout,
Link,
PrettyLink,
},
props: {
@@ -61,7 +59,7 @@ export default {
},
data: {
type: Array,
default: [],
default: () => [],
},
},
};
@@ -0,0 +1,242 @@
<style lang="scss" scoped>
.item-list {
&:hover:first-child {
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
&:last-child {
border-bottom: 0;
}
&:hover:last-child {
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
}
</style>
<template>
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
<div class="flex items-baseline justify-between space-x-6">
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<inertia-link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</li>
<li class="inline mr-2"><inertia-link :href="data.url.personalize" class="text-sky-500 hover:text-blue-900">Personalize your account</inertia-link></li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</li>
<li class="inline">Genders</li>
</ul>
</div>
</div>
</nav>
<main class="sm:mt-20 relative">
<div class="max-w-3xl mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<!-- title + cta -->
<div class="sm:flex items-center justify-between mb-6 sm:mt-0 mt-8">
<h3 class="mb-4 sm:mb-0">
<span class="mr-1">
🏷
</span> All the genders
</h3>
<pretty-button v-if="!createGenderModalShown" :text="'Add a label'" :icon="'plus'" @click="showGenderModal" />
</div>
<!-- modal to create a new group type -->
<form v-if="createGenderModalShown" class="bg-white border border-gray-200 rounded-lg mb-6" @submit.prevent="submit()">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input :ref="'newGender'"
v-model="form.name"
:label="'Name'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="createGenderModalShown = false"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click="createGenderModalShown = false" />
<pretty-button :text="'Create label'" :state="loadingState" :icon="'plus'" :classes="'save'" />
</div>
</form>
<!-- list of groups types -->
<ul v-if="localGenders.length > 0" class="bg-white border border-gray-200 rounded-lg mb-6">
<li v-for="gender in localGenders" :key="gender.id" class="border-b border-gray-200 hover:bg-slate-50 item-list">
<!-- detail of the group type -->
<div v-if="renameGenderModalShownId != gender.id" class="flex justify-between items-center px-5 py-2">
<span class="text-base">{{ gender.name }}</span>
<!-- actions -->
<ul class="text-sm">
<li class="cursor-pointer inline mr-4 text-sky-500 hover:text-blue-900" @click="updateGenderModal(gender)">Rename</li>
<li class="cursor-pointer inline text-red-500 hover:text-red-900" @click="destroy(gender)">Delete</li>
</ul>
</div>
<!-- rename a gender modal -->
<form v-if="renameGenderModalShownId == gender.id" class="border-b border-gray-200 hover:bg-slate-50 item-list" @submit.prevent="update(gender)">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input :ref="'rename' + gender.id"
v-model="form.name"
:label="'Name'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="renameGenderModalShownId = 0"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click.prevent="renameGenderModalShownId = 0" />
<pretty-button :text="'Rename'" :state="loadingState" :icon="'check'" :classes="'save'" />
</div>
</form>
</li>
</ul>
<!-- blank state -->
<div v-if="localGenders.length == 0" class="bg-white border border-gray-200 rounded-lg mb-6">
<p class="p-5 text-center">Labels let you classify contacts using a system that matters to you.</p>
</div>
</div>
</main>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import PrettyButton from '@/Shared/PrettyButton';
import PrettySpan from '@/Shared/PrettySpan';
import TextInput from '@/Shared/TextInput';
import Errors from '@/Shared/Errors';
export default {
components: {
Layout,
PrettyButton,
PrettySpan,
TextInput,
Errors,
},
props: {
layoutData: {
type: Object,
default: null,
},
data: {
type: Object,
default: null,
},
},
data() {
return {
loadingState: '',
createGenderModalShown: false,
renameGenderModalShownId: 0,
localGenders: [],
form: {
name: '',
errors: [],
},
};
},
mounted() {
this.localGenders = this.data.genders;
},
methods: {
showGenderModal() {
this.form.name = '';
this.createGenderModalShown = true;
this.$nextTick(() => {
this.$refs.newGender.focus();
});
},
updateGenderModal(label) {
this.form.name = label.name;
this.renameGenderModalShownId = label.id;
this.$nextTick(() => {
this.$refs[`rename${label.id}`].focus();
});
},
submit() {
this.loadingState = 'loading';
axios.post(this.data.url.gender_store, this.form)
.then(response => {
this.flash('The gender has been created', 'success');
this.localGenders.unshift(response.data.data);
this.loadingState = null;
this.createGenderModalShown = false;
})
.catch(error => {
this.loadingState = null;
this.form.errors = error.response.data;
});
},
update(gender) {
this.loadingState = 'loading';
axios.put(gender.url.update, this.form)
.then(response => {
this.flash('The gender has been updated', 'success');
this.localGenders[this.localGenders.findIndex(x => x.id === gender.id)] = response.data.data;
this.loadingState = null;
this.renameGenderModalShownId = 0;
})
.catch(error => {
this.loadingState = null;
this.form.errors = error.response.data;
});
},
destroy(gender) {
if(confirm('Are you sure? This will remove the genders from all contacts, but won\'t delete the contacts themselves.')) {
axios.delete(gender.url.destroy)
.then(response => {
this.flash('The gender has been deleted', 'success');
var id = this.localGenders.findIndex(x => x.id === gender.id);
this.localGenders.splice(id, 1);
})
.catch(error => {
this.loadingState = null;
this.form.errors = error.response.data;
});
}
},
},
};
</script>
@@ -6,7 +6,7 @@
</style>
<template>
<Layout :layoutData="layoutData">
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -14,7 +14,7 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</Link>
<inertia-link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -29,26 +29,27 @@
<main class="sm:mt-20 relative">
<div class="max-w-md mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<h2 class="text-lg text-center mb-6">Personalize the account</h2>
<h2 class="text-lg text-center mb-6">
Personalize the account
</h2>
<div class="bg-white border border-gray-200 rounded-lg p-5">
<ul>
<li class="mb-2"><span class="mr-1">🥸</span> <Link :href="data.url.manage_relationships" class="text-sky-500 hover:text-blue-900">Manage relationship types</Link></li>
<li class=""><span class="mr-1">🏷</span> <Link :href="data.url.manage_labels" class="text-sky-500 hover:text-blue-900">Manage labels</Link></li>
<li class="mb-2"><span class="mr-1">🥸</span> <inertia-link :href="data.url.manage_relationships" class="text-sky-500 hover:text-blue-900">Manage relationship types</inertia-link></li>
<li class="mb-2"><span class="mr-1">🏷</span> <inertia-link :href="data.url.manage_labels" class="text-sky-500 hover:text-blue-900">Manage labels</inertia-link></li>
<li class=""><span class="mr-1">🚻</span> <inertia-link :href="data.url.manage_genders" class="text-sky-500 hover:text-blue-900">Manage genders</inertia-link></li>
</ul>
</div>
</div>
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
Layout,
Link,
},
props: {
@@ -17,7 +17,7 @@
</style>
<template>
<Layout :layoutData="layoutData">
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -25,14 +25,14 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</Link>
<inertia-link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</li>
<li class="inline mr-2"><Link :href="data.url.personalize" class="text-sky-500 hover:text-blue-900">Personalize your account</Link></li>
<li class="inline mr-2"><inertia-link :href="data.url.personalize" class="text-sky-500 hover:text-blue-900">Personalize your account</inertia-link></li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
@@ -48,28 +48,33 @@
<div class="max-w-3xl mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<!-- title + cta -->
<div class="sm:flex items-center justify-between mb-6 sm:mt-0 mt-8">
<h3 class="mb-4 sm:mb-0"><span class="mr-1">🏷</span> All the labels used in the account</h3>
<pretty-button @click="showLabelModal" v-if="!createlabelModalShown" :text="'Add a label'" :icon="'plus'" />
<h3 class="mb-4 sm:mb-0">
<span class="mr-1">
🏷
</span> All the labels used in the account
</h3>
<pretty-button v-if="!createlabelModalShown" :text="'Add a label'" :icon="'plus'" @click="showLabelModal" />
</div>
<!-- modal to create a new group type -->
<form v-if="createlabelModalShown" @submit.prevent="submit()" class="bg-white border border-gray-200 rounded-lg mb-6">
<form v-if="createlabelModalShown" class="bg-white border border-gray-200 rounded-lg mb-6" @submit.prevent="submit()">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input v-model="form.name"
:label="'Name'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:ref="'newLabel'"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="createlabelModalShown = false" />
<text-input :ref="'newLabel'"
v-model="form.name"
:label="'Name'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="createlabelModalShown = false"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span @click="createlabelModalShown = false" :text="'Cancel'" :classes="'mr-3'" />
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click="createlabelModalShown = false" />
<pretty-button :text="'Create label'" :state="loadingState" :icon="'plus'" :classes="'save'" />
</div>
</form>
@@ -83,29 +88,30 @@
<!-- actions -->
<ul class="text-sm">
<li @click="updateLabelModal(label)" class="cursor-pointer inline mr-4 text-sky-500 hover:text-blue-900">Rename</li>
<li @click="destroy(label)" class="cursor-pointer inline text-red-500 hover:text-red-900">Delete</li>
<li class="cursor-pointer inline mr-4 text-sky-500 hover:text-blue-900" @click="updateLabelModal(label)">Rename</li>
<li class="cursor-pointer inline text-red-500 hover:text-red-900" @click="destroy(label)">Delete</li>
</ul>
</div>
<!-- rename a label modal -->
<form v-if="renamelabelModalShownId == label.id" @submit.prevent="update(label)" class="border-b border-gray-200 hover:bg-slate-50 item-list">
<form v-if="renamelabelModalShownId == label.id" class="border-b border-gray-200 hover:bg-slate-50 item-list" @submit.prevent="update(label)">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input v-model="form.name"
:label="'Name'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:ref="'rename' + label.id"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="renamelabelModalShownId = 0" />
<text-input :ref="'rename' + label.id"
v-model="form.name"
:label="'Name'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="renamelabelModalShownId = 0"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span @click.prevent="renamelabelModalShownId = 0" :text="'Cancel'" :classes="'mr-3'" />
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click.prevent="renamelabelModalShownId = 0" />
<pretty-button :text="'Rename'" :state="loadingState" :icon="'check'" :classes="'save'" />
</div>
</form>
@@ -118,14 +124,12 @@
</div>
</div>
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
import PrettyButton from '@/Shared/PrettyButton';
import PrettyLink from '@/Shared/PrettyLink';
import PrettySpan from '@/Shared/PrettySpan';
import TextInput from '@/Shared/TextInput';
import Errors from '@/Shared/Errors';
@@ -133,9 +137,7 @@ import Errors from '@/Shared/Errors';
export default {
components: {
Layout,
Link,
PrettyButton,
PrettyLink,
PrettySpan,
TextInput,
Errors,
@@ -222,7 +224,7 @@ export default {
},
destroy(label) {
if(confirm("Are you sure? This will remove the labels from all contacts, but won't delete the contacts themselves.")) {
if(confirm('Are you sure? This will remove the labels from all contacts, but won\'t delete the contacts themselves.')) {
axios.delete(label.url.destroy)
.then(response => {
@@ -234,7 +236,7 @@ export default {
this.loadingState = null;
this.form.errors = error.response.data;
});
}
}
},
},
};
@@ -22,7 +22,7 @@
</style>
<template>
<Layout :layoutData="layoutData">
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -30,14 +30,14 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</Link>
<inertia-link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</li>
<li class="inline mr-2"><Link :href="data.url.personalize" class="text-sky-500 hover:text-blue-900">Personalize your account</Link></li>
<li class="inline mr-2"><inertia-link :href="data.url.personalize" class="text-sky-500 hover:text-blue-900">Personalize your account</inertia-link></li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
@@ -53,8 +53,12 @@
<div class="max-w-3xl mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<!-- title + cta -->
<div class="sm:flex items-center justify-between mb-6 sm:mt-0 mt-8">
<h3 class="mb-4 sm:mb-0"><span class="mr-1">🥸</span> All the relationship types</h3>
<pretty-button @click="showGroupTypeModal" v-if="!createGroupTypeModalShown" :text="'Add a new group type'" :icon="'plus'" />
<h3 class="mb-4 sm:mb-0">
<span class="mr-1">
🥸
</span> All the relationship types
</h3>
<pretty-button v-if="!createGroupTypeModalShown" :text="'Add a new group type'" :icon="'plus'" @click="showGroupTypeModal" />
</div>
<!-- help text -->
@@ -74,23 +78,24 @@
</div>
<!-- modal to create a new group type -->
<form v-if="createGroupTypeModalShown" @submit.prevent="submitGroupType()" class="bg-white border border-gray-200 rounded-lg mb-6">
<form v-if="createGroupTypeModalShown" class="bg-white border border-gray-200 rounded-lg mb-6" @submit.prevent="submitGroupType()">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input v-model="form.groupTypeName"
:label="'Name of the new group type'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:ref="'newGroupType'"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="createGroupTypeModalShown = false" />
<text-input :ref="'newGroupType'"
v-model="form.groupTypeName"
:label="'Name of the new group type'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="createGroupTypeModalShown = false"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span @click="createGroupTypeModalShown = false" :text="'Cancel'" :classes="'mr-3'" />
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click="createGroupTypeModalShown = false" />
<pretty-button :text="'Create group type'" :state="loadingState" :icon="'plus'" :classes="'save'" />
</div>
</form>
@@ -104,36 +109,36 @@
<!-- actions -->
<ul class="text-sm">
<li @click="renameGroupTypeModal(groupType)" class="cursor-pointer inline mr-4 text-sky-500 hover:text-blue-900">Rename</li>
<li @click="destroyGroupType(groupType)" class="cursor-pointer inline text-red-500 hover:text-red-900">Delete</li>
<li class="cursor-pointer inline mr-4 text-sky-500 hover:text-blue-900" @click="renameGroupTypeModal(groupType)">Rename</li>
<li class="cursor-pointer inline text-red-500 hover:text-red-900" @click="destroyGroupType(groupType)">Delete</li>
</ul>
</div>
<!-- rename a group type modal -->
<form v-if="renameGroupTypeModalShownId == groupType.id" @submit.prevent="updateGroupType(groupType)" class="border-b border-gray-200 hover:bg-slate-50 item-list">
<form v-if="renameGroupTypeModalShownId == groupType.id" class="border-b border-gray-200 hover:bg-slate-50 item-list" @submit.prevent="updateGroupType(groupType)">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input v-model="form.groupTypeName"
:label="'Name of the new group type'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:ref="'rename' + groupType.id"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="renameGroupTypeModalShownId = 0" />
<text-input :ref="'rename' + groupType.id"
v-model="form.groupTypeName"
:label="'Name of the new group type'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="renameGroupTypeModalShownId = 0"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span @click.prevent="renameGroupTypeModalShownId = 0" :text="'Cancel'" :classes="'mr-3'" />
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click.prevent="renameGroupTypeModalShownId = 0" />
<pretty-button :text="'Rename'" :state="loadingState" :icon="'check'" :classes="'save'" />
</div>
</form>
<!-- list of relationship types -->
<div v-for="type in groupType.types" :key="type.id" class="px-5 py-2 border-b border-gray-200 hover:bg-slate-50 pl-6">
<!-- detail of the relationship type -->
<div v-if="renameRelationshipTypeModalId != type.id" class="flex justify-between items-center">
<div class="relative">
@@ -150,82 +155,85 @@
<!-- actions -->
<ul class="text-sm">
<li @click="renameRelationTypeModal(type)" class="cursor-pointer inline mr-4 text-sky-500 hover:text-blue-900">Rename</li>
<li @click="destroyRelationshipType(groupType, type)" class="cursor-pointer inline text-red-500 hover:text-red-900">Delete</li>
<li class="cursor-pointer inline mr-4 text-sky-500 hover:text-blue-900" @click="renameRelationTypeModal(type)">Rename</li>
<li class="cursor-pointer inline text-red-500 hover:text-red-900" @click="destroyRelationshipType(groupType, type)">Delete</li>
</ul>
</div>
<!-- rename the relationship type modal -->
<form v-if="renameRelationshipTypeModalId == type.id" @submit.prevent="updateRelationType(groupType, type)" class="border-b border-gray-200 hover:bg-slate-50 item-list">
<form v-if="renameRelationshipTypeModalId == type.id" class="border-b border-gray-200 hover:bg-slate-50 item-list" @submit.prevent="updateRelationType(groupType, type)">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input v-model="form.name"
:label="'Name of the relationship'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:ref="'rename' + type.id"
:div-outer-class="'mb-4'"
:placeholder="'Parent'"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="renameRelationshipTypeModalId = 0" />
<text-input :ref="'rename' + type.id"
v-model="form.name"
:label="'Name of the relationship'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:div-outer-class="'mb-4'"
:placeholder="'Parent'"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="renameRelationshipTypeModalId = 0"
/>
<text-input v-model="form.nameReverseRelationship"
:label="'Name of the reverse relationship'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:placeholder="'Child'"
:maxlength="255"
@esc-key-pressed="renameRelationshipTypeModalId = 0" />
:label="'Name of the reverse relationship'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:placeholder="'Child'"
:maxlength="255"
@esc-key-pressed="renameRelationshipTypeModalId = 0"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span @click.prevent="renameRelationshipTypeModalId = 0" :text="'Cancel'" :classes="'mr-3'" />
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click.prevent="renameRelationshipTypeModalId = 0" />
<pretty-button :text="'Rename'" :state="loadingState" :icon="'check'" :classes="'save'" />
</div>
</form>
</div>
<!-- create a new relationship type line -->
<div v-if="createRelationshipTypeModalId != groupType.id" class="px-5 py-2 border-b border-gray-200 hover:bg-slate-50 pl-6 item-list">
<span @click="showRelationshipTypeModal(groupType)" class="text-sky-500 hover:text-blue-900 text-sm cursor-pointer">Add a new relationship type</span>
<span class="text-sky-500 hover:text-blue-900 text-sm cursor-pointer" @click="showRelationshipTypeModal(groupType)">Add a new relationship type</span>
</div>
<!-- create a new relationship type -->
<form v-if="createRelationshipTypeModalId == groupType.id" @submit.prevent="storeRelationshipType(groupType)" class="border-b border-gray-200 hover:bg-slate-50 item-list">
<form v-if="createRelationshipTypeModalId == groupType.id" class="border-b border-gray-200 hover:bg-slate-50 item-list" @submit.prevent="storeRelationshipType(groupType)">
<div class="p-5 border-b border-gray-200">
<errors :errors="form.errors" />
<text-input v-model="form.name"
:label="'Name of the relationship'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:ref="'newRelationshipType'"
:div-outer-class="'mb-4'"
:placeholder="'Parent'"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="createRelationshipTypeModalId = 0" />
<text-input :ref="'newRelationshipType'"
v-model="form.name"
:label="'Name of the relationship'" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:required="true"
:div-outer-class="'mb-4'"
:placeholder="'Parent'"
:autocomplete="false"
:maxlength="255"
@esc-key-pressed="createRelationshipTypeModalId = 0"
/>
<text-input v-model="form.nameReverseRelationship"
:label="'Name of the reverse relationship'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:placeholder="'Child'"
:maxlength="255"
@esc-key-pressed="createRelationshipTypeModalId = 0" />
:label="'Name of the reverse relationship'"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:placeholder="'Child'"
:maxlength="255"
@esc-key-pressed="createRelationshipTypeModalId = 0"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-span @click.prevent="createRelationshipTypeModalId = 0" :text="'Cancel'" :classes="'mr-3'" />
<pretty-span :text="'Cancel'" :classes="'mr-3'" @click.prevent="createRelationshipTypeModalId = 0" />
<pretty-button :text="'Add'" :state="loadingState" :icon="'plus'" :classes="'save'" />
</div>
</form>
@@ -238,12 +246,11 @@
</div>
</div>
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
import PrettyButton from '@/Shared/PrettyButton';
import PrettySpan from '@/Shared/PrettySpan';
import TextInput from '@/Shared/TextInput';
@@ -252,7 +259,6 @@ import Errors from '@/Shared/Errors';
export default {
components: {
Layout,
Link,
PrettyButton,
PrettySpan,
TextInput,
@@ -363,7 +369,7 @@ export default {
},
destroyGroupType(groupType) {
if(confirm("Are you sure? This will delete all the relationships of this type for all the contacts that were using it.")) {
if(confirm('Are you sure? This will delete all the relationships of this type for all the contacts that were using it.')) {
axios.delete(groupType.url.destroy)
.then(response => {
@@ -375,7 +381,7 @@ export default {
this.loadingState = null;
this.form.errors = error.response.data;
});
}
}
},
storeRelationshipType(groupType) {
@@ -414,7 +420,7 @@ export default {
},
destroyRelationshipType(groupType, type) {
if(confirm("Are you sure? This will delete all the relationships of this type for all the contacts that were using it.")) {
if(confirm('Are you sure? This will delete all the relationships of this type for all the contacts that were using it.')) {
axios.delete(type.url.destroy)
.then(response => {
@@ -427,7 +433,7 @@ export default {
this.loadingState = null;
this.form.errors = error.response.data;
});
}
}
},
},
};
@@ -17,7 +17,7 @@
</style>
<template>
<Layout :layoutData="layoutData">
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -25,7 +25,7 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</Link>
<inertia-link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -43,26 +43,16 @@
<name-order :data="data.name_order" />
</div>
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
import PrettyButton from '@/Shared/PrettyButton';
import PrettyLink from '@/Shared/PrettyLink';
import PrettySpan from '@/Shared/PrettySpan';
import Errors from '@/Shared/Errors';
import NameOrder from '@/Pages/Settings/Preferences/Partials/NameOrder';
export default {
components: {
Layout,
Link,
PrettyButton,
PrettyLink,
PrettySpan,
Errors,
NameOrder,
},
@@ -14,8 +14,12 @@ pre {
<div>
<!-- title + cta -->
<div class="sm:flex items-center justify-between mb-3 sm:mt-0 mt-8">
<h3 class="mb-4 sm:mb-0"><span class="mr-1">👉</span> Customize how contacts should be displayed</h3>
<pretty-button @click="enableEditMode" :text="'Edit'" />
<h3 class="mb-4 sm:mb-0">
<span class="mr-1">
👉
</span> Customize how contacts should be displayed
</h3>
<pretty-button :text="'Edit'" @click="enableEditMode" />
</div>
<!-- help text -->
@@ -39,57 +43,73 @@ pre {
</div>
<!-- edit mode -->
<form v-if="editMode" @submit.prevent="submit()" class="bg-white border border-gray-200 rounded-lg mb-6">
<form v-if="editMode" class="bg-white border border-gray-200 rounded-lg mb-6" @submit.prevent="submit()">
<div class="px-5 py-2 border-b border-gray-200">
<Errors :errors="form.errors" />
<errors :errors="form.errors" />
<div class="flex items-center mb-2">
<input v-model="form.nameOrder" id="first_name_last_name" value="%first_name% %last_name%" name="name-order" type="radio" class="h-4 w-4 text-sky-500 border-gray-300">
<input id="first_name_last_name" v-model="form.nameOrder" value="%first_name% %last_name%" name="name-order" type="radio"
class="h-4 w-4 text-sky-500 border-gray-300"
>
<label for="first_name_last_name" class="ml-3 block text-sm font-medium text-gray-700 cursor-pointer">
First name Last name <span class="text-gray-500 font-normal ml-4">James Bond</span>
First name Last name <span class="text-gray-500 font-normal ml-4">
James Bond
</span>
</label>
</div>
<div class="flex items-center mb-2">
<input v-model="form.nameOrder" id="last_name_first_name" value="%last_name% %first_name%" name="name-order" type="radio" class="h-4 w-4 text-sky-500 border-gray-300">
<input id="last_name_first_name" v-model="form.nameOrder" value="%last_name% %first_name%" name="name-order" type="radio"
class="h-4 w-4 text-sky-500 border-gray-300"
>
<label for="last_name_first_name" class="ml-3 block text-sm font-medium text-gray-700 cursor-pointer">
Last name First name <span class="text-gray-500 font-normal ml-4">Bond James</span>
Last name First name <span class="text-gray-500 font-normal ml-4">
Bond James
</span>
</label>
</div>
<div class="flex items-center mb-2">
<input v-model="form.nameOrder" id="first_name_last_name_surname" value="%first_name% %last_name% (%surname%)" name="name-order" type="radio" class="h-4 w-4 text-sky-500 border-gray-300">
<input id="first_name_last_name_surname" v-model="form.nameOrder" value="%first_name% %last_name% (%surname%)" name="name-order" type="radio"
class="h-4 w-4 text-sky-500 border-gray-300"
>
<label for="first_name_last_name_surname" class="ml-3 block text-sm font-medium text-gray-700 cursor-pointer">
First name Last name (Surname) <span class="text-gray-500 font-normal ml-4">James Bond (007)</span>
First name Last name (Surname) <span class="text-gray-500 font-normal ml-4">
James Bond (007)
</span>
</label>
</div>
<div class="flex items-center mb-2">
<input v-model="form.nameOrder" id="surname" value="%surname%" name="name-order" type="radio" class="h-4 w-4 text-sky-500 border-gray-300">
<input id="surname" v-model="form.nameOrder" value="%surname%" name="name-order" type="radio"
class="h-4 w-4 text-sky-500 border-gray-300"
>
<label for="surname" class="ml-3 block text-sm font-medium text-gray-700 cursor-pointer">
Surname <span class="text-gray-500 font-normal ml-4">007</span>
Surname <span class="text-gray-500 font-normal ml-4">
007
</span>
</label>
</div>
<div class="flex items-center mb-2">
<input @click="focusNameOrder" id="custom" name="name-order" type="radio" class="h-4 w-4 text-sky-500 border-gray-300">
<input id="custom" name="name-order" type="radio" class="h-4 w-4 text-sky-500 border-gray-300" @click="focusNameOrder">
<label for="custom" class="ml-3 block text-sm font-medium text-gray-700 cursor-pointer">
Custom name order
</label>
</div>
<div class="ml-8">
<text-input v-model="form.nameOrder"
:type="'text'" :autofocus="true"
:input-class="'block w-full'"
:div-outer-class="'block mb-2'"
:disabled="disableNameOrder"
:ref="'nameOrder'"
:autocomplete="false"
:maxlength="255" />
<text-input :ref="'nameOrder'"
v-model="form.nameOrder" :type="'text'"
:autofocus="true"
:input-class="'block w-full'"
:div-outer-class="'block mb-2'"
:disabled="disableNameOrder"
:autocomplete="false"
:maxlength="255"
/>
<p class="mb-4 text-sm">Please read <a href="https://www.notion.so/monicahq/Customize-your-account-8e015b7488c143abab9eb8a6e2fbca77#b3fd57def37445f4a9cf234e373c52ca" target="_blank" class="text-sky-500 hover:text-blue-900">our documentation</a> to know more about this feature, and which variables you have access to.</p>
<p class="mb-4 text-sm">Please read <a href="https://www.notion.so/monicahq/Customize-your-account-8e015b7488c143abab9eb8a6e2fbca77#b3fd57def37445f4a9cf234e373c52ca" target="_blank" class="text-sky-500 hover:text-blue-900">our documentation</a> to know more about this feature, and which variables you have access to.</p>
</div>
</div>
<div class="p-5 flex justify-between">
<pretty-link @click="editMode = false" :text="'Cancel'" :classes="'mr-3'" />
<pretty-link :text="'Cancel'" :classes="'mr-3'" @click="editMode = false" />
<pretty-button :text="'Save'" :state="loadingState" :icon="'check'" :classes="'save'" />
</div>
</form>
@@ -97,19 +117,15 @@ pre {
</template>
<script>
import { Link } from '@inertiajs/inertia-vue3';
import PrettyButton from '@/Shared/PrettyButton';
import PrettyLink from '@/Shared/PrettyLink';
import PrettySpan from '@/Shared/PrettySpan';
import TextInput from '@/Shared/TextInput';
import Errors from '@/Shared/Errors';
export default {
components: {
Link,
PrettyButton,
PrettyLink,
PrettySpan,
TextInput,
Errors,
},
+16 -19
View File
@@ -6,7 +6,7 @@
</style>
<template>
<Layout :layoutData="layoutData">
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -14,7 +14,7 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</Link>
<inertia-link :href="data.url.settings" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -22,7 +22,7 @@
</svg>
</li>
<li class="inline mr-2">
<Link :href="data.url.back" class="text-sky-500 hover:text-blue-900">Users</Link>
<inertia-link :href="data.url.back" class="text-sky-500 hover:text-blue-900">Users</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -37,12 +37,12 @@
<main class="sm:mt-24 relative">
<div class="max-w-lg mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<form @submit.prevent="submit()" class="bg-white border border-gray-200 rounded-lg mb-6">
<form class="bg-white border border-gray-200 rounded-lg mb-6" @submit.prevent="submit()">
<!-- title -->
<div class="p-5 border-b border-gray-200 bg-blue-50 section-head">
<h1 class="text-center text-2xl mb-1 font-medium">Invite someone</h1>
<h1 class="text-center text-2xl mb-1 font-medium">
Invite someone
</h1>
<p class="text-center">This user will be part of your account, but won't get access to your vaults unless you give specific access to them. This person will be able to create vaults as well.</p>
</div>
@@ -51,13 +51,14 @@
<errors :errors="form.errors" />
<text-input v-model="form.email"
:label="'Email address to send the invitation to'"
:type="'email'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255" />
</div>
:label="'Email address to send the invitation to'"
:type="'email'" :autofocus="true"
:input-class="'block w-full'"
:required="true"
:autocomplete="false"
:maxlength="255"
/>
</div>
<div class="p-5 flex justify-between">
<pretty-link :href="data.url.back" :text="'Cancel'" :classes="'mr-3'" />
@@ -66,7 +67,7 @@
</form>
</div>
</main>
</Layout>
</layout>
</template>
<script>
@@ -75,8 +76,6 @@ import PrettyLink from '@/Shared/PrettyLink';
import PrettyButton from '@/Shared/PrettyButton';
import TextInput from '@/Shared/TextInput';
import Errors from '@/Shared/Errors';
import TextArea from '@/Shared/TextArea';
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
@@ -85,8 +84,6 @@ export default {
PrettyButton,
TextInput,
Errors,
TextArea,
Link,
},
props: {
+9 -9
View File
@@ -21,7 +21,7 @@
</style>
<template>
<Layout title="Dashboard" :layoutData="layoutData">
<layout title="Dashboard" :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -29,7 +29,7 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.settings.index" class="text-sky-500 hover:text-blue-900">Settings</Link>
<inertia-link :href="data.url.settings.index" class="text-sky-500 hover:text-blue-900">Settings</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -44,17 +44,19 @@
<main class="sm:mt-24 relative">
<div class="max-w-3xl mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<!-- title + cta -->
<div class="flex items-center justify-between mb-6">
<h3><span class="mr-1">🥸</span> All users in this account</h3>
<h3>
<span class="mr-1">
🥸
</span> All users in this account
</h3>
<pretty-link :href="data.url.users.create" :text="'Invite a new user'" :icon="'plus'" />
</div>
<!-- list of users -->
<ul class="bg-white border border-gray-200 rounded-lg mb-6 user-list">
<li v-for="user in data.users" :key="user.id" class="px-5 py-2 border-b border-gray-200 hover:bg-slate-50">
<!-- case user has been invited -->
<div v-if="!user.name" class="flex justify-between items-center">
<div>
@@ -86,18 +88,16 @@
</ul>
</div>
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
import PrettyLink from '@/Shared/PrettyLink';
export default {
components: {
Layout,
Link,
PrettyLink,
},
@@ -108,7 +108,7 @@ export default {
},
data: {
type: Array,
default: [],
default: () => [],
},
},
+11 -10
View File
@@ -6,7 +6,7 @@
</style>
<template>
<Layout :layoutData="layoutData">
<layout :layout-data="layoutData">
<!-- breadcrumb -->
<nav class="sm:border-b bg-white">
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
@@ -14,7 +14,7 @@
<ul class="text-sm">
<li class="inline mr-2 text-gray-600">You are here:</li>
<li class="inline mr-2">
<Link :href="data.url.back" class="text-sky-500 hover:text-blue-900">All the vaults</Link>
<inertia-link :href="data.url.back" class="text-sky-500 hover:text-blue-900">All the vaults</inertia-link>
</li>
<li class="inline mr-2 relative">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3 inline relative icon-breadcrumb" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -29,16 +29,19 @@
<main class="sm:mt-24 relative">
<div class="max-w-lg mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<form @submit.prevent="submit()" class="bg-white border border-gray-200 rounded-lg mb-6">
<form class="bg-white border border-gray-200 rounded-lg mb-6" @submit.prevent="submit()">
<div class="p-5 border-b border-gray-200 bg-blue-50 section-head">
<h1 class="text-center text-2xl mb-1 font-medium">Create a new vault</h1>
<h1 class="text-center text-2xl mb-1 font-medium">
Create a new vault
</h1>
<p class="text-center">Vaults contain all your contacts data.</p>
</div>
<div class="p-5 border-b border-gray-200">
<text-input v-model="form.name" :autofocus="true" :div-outer-class="'mb-5'" :input-class="'block w-full'" :required="true" :maxlength="255" :label="'Vault name'" />
<text-input v-model="form.name" :autofocus="true" :div-outer-class="'mb-5'" :input-class="'block w-full'" :required="true"
:maxlength="255" :label="'Vault name'"
/>
<text-area v-model="form.description" :label="'Description'" :maxlength="255" :textarea-class="'block w-full'" />
</div>
</div>
<div class="p-5 flex justify-between">
<pretty-link :href="data.url.back" :text="'Cancel'" :classes="'mr-3'" />
@@ -47,7 +50,7 @@
</form>
</div>
</main>
</Layout>
</layout>
</template>
<script>
@@ -56,7 +59,6 @@ import PrettyLink from '@/Shared/PrettyLink';
import PrettyButton from '@/Shared/PrettyButton';
import TextInput from '@/Shared/TextInput';
import TextArea from '@/Shared/TextArea';
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
@@ -65,7 +67,6 @@ export default {
PrettyButton,
TextInput,
TextArea,
Link,
},
props: {
+12 -12
View File
@@ -27,12 +27,14 @@ input[type=checkbox] {
</style>
<template>
<Layout title="Dashboard" :layoutData="layoutData">
<layout title="Dashboard" :layout-data="layoutData">
<main class="sm:mt-24 relative">
<!-- blank state -->
<div v-if="data.vaults.length == 0" class="max-w-md mx-auto px-2 py-2 sm:py-6 sm:px-6 lg:px-8">
<div class="bg-white border border-gray-200 rounded-lg mb-6 p-5">
<h2 class="text-lg text-center mb-6">Thanks for trying out Monica 👋</h2>
<h2 class="text-lg text-center mb-6">
Thanks for trying out Monica 👋
</h2>
<p class="mb-3">Monica is there to help you build better relationships.</p>
<p class="mb-3">Contacts in Monica are stored in vaults. You can have as many vaults as you want: one vault for your personal life, one for your professional life, and/or one vault shared with your spouse.</p>
<div class="text-center">
@@ -50,9 +52,9 @@ input[type=checkbox] {
<div class="vault-list grid grid-cols-1 sm:grid-cols-3 gap-6">
<div v-for="vault in data.vaults" :key="vault.id" class="bg-white border border-gray-200 rounded-lg">
<div class="grid vault-detail">
<Link :href="vault.url.show" class="border-b border-gray-200 text-lg px-3 py-1 font-medium">
<inertia-link :href="vault.url.show" class="border-b border-gray-200 text-lg px-3 py-1 font-medium">
{{ vault.name }}
</Link>
</inertia-link>
<!-- description -->
<p v-if="vault.description" class="border-b border-gray-200 p-3">
@@ -64,36 +66,34 @@ input[type=checkbox] {
<!-- actions -->
<div class="flex items-center justify-between px-3 py-2">
<Link :href="'href'">
<inertia-link :href="'href'">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 hover:text-gray-900 pointer" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</Link>
</inertia-link>
<Link :href="vault.url.show">
<inertia-link :href="vault.url.show">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400 hover:text-gray-900 pointer" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
</svg>
</Link>
</inertia-link>
</div>
</div>
</div>
</div>
</div>
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
import PrettyLink from '@/Shared/PrettyLink';
export default {
components: {
Layout,
Link,
PrettyLink,
},
@@ -104,7 +104,7 @@ export default {
},
data: {
type: Array,
default: [],
default: () => [],
},
},
+3 -7
View File
@@ -3,23 +3,19 @@
</style>
<template>
<Layout title="Dashboard" :inside-vault="true" :layoutData="layoutData">
<layout title="Dashboard" :inside-vault="true" :layout-data="layoutData">
<main class="sm:mt-24 relative">
d
</main>
</Layout>
</layout>
</template>
<script>
import Layout from '@/Shared/Layout';
import { Link } from '@inertiajs/inertia-vue3';
import PrettyLink from '@/Shared/PrettyLink';
export default {
components: {
Layout,
Link,
PrettyLink,
},
props: {
@@ -29,7 +25,7 @@ export default {
},
data: {
type: Array,
default: [],
default: () => [],
},
},
+137 -105
View File
@@ -1,115 +1,139 @@
<template>
<Head title="Welcome" />
<div>
<div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
<div v-if="canLogin" class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
<Link v-if="$page.props.auth.user" :href="route('dashboard')" class="text-sm text-gray-700 underline">
Dashboard
</Link>
<div v-if="canLogin" class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
<inertia-link v-if="$page.props.auth.user" :href="route('dashboard')" class="text-sm text-gray-700 underline">
Dashboard
</inertia-link>
<template v-else>
<Link :href="route('login')" class="text-sm text-gray-700 underline">
Log in
</Link>
<template v-else>
<inertia-link :href="route('login')" class="text-sm text-gray-700 underline">
Log in
</inertia-link>
<Link v-if="canRegister" :href="route('register')" class="ml-4 text-sm text-gray-700 underline">
Register
</Link>
</template>
<inertia-link v-if="canRegister" :href="route('register')" class="ml-4 text-sm text-gray-700 underline">
Register
</inertia-link>
</template>
</div>
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
<svg viewBox="0 0 651 192" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-16 w-auto text-gray-700 sm:h-20">
<g clip-path="url(#clip0)" fill="#EF3B2D">
<path d="M248.032 44.676h-16.466v100.23h47.394v-14.748h-30.928V44.676zM337.091 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.431 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162-.001 2.863-.479 5.584-1.432 8.161zM463.954 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.432 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162 0 2.863-.479 5.584-1.432 8.161zM650.772 44.676h-15.606v100.23h15.606V44.676zM365.013 144.906h15.607V93.538h26.776V78.182h-42.383v66.724zM542.133 78.182l-19.616 51.096-19.616-51.096h-15.808l25.617 66.724h19.614l25.617-66.724h-15.808zM591.98 76.466c-19.112 0-34.239 15.706-34.239 35.079 0 21.416 14.641 35.079 36.239 35.079 12.088 0 19.806-4.622 29.234-14.688l-10.544-8.158c-.006.008-7.958 10.449-19.832 10.449-13.802 0-19.612-11.127-19.612-16.884h51.777c2.72-22.043-11.772-40.877-33.023-40.877zm-18.713 29.28c.12-1.284 1.917-16.884 18.589-16.884 16.671 0 18.697 15.598 18.813 16.884h-37.402zM184.068 43.892c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002-35.648-20.524a2.971 2.971 0 00-2.964 0l-35.647 20.522-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v38.979l-29.706 17.103V24.493a3 3 0 00-.103-.776c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002L40.098 1.396a2.971 2.971 0 00-2.964 0L1.487 21.919l-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v122.09c0 1.063.568 2.044 1.489 2.575l71.293 41.045c.156.089.324.143.49.202.078.028.15.074.23.095a2.98 2.98 0 001.524 0c.069-.018.132-.059.2-.083.176-.061.354-.119.519-.214l71.293-41.045a2.971 2.971 0 001.489-2.575v-38.979l34.158-19.666a2.971 2.971 0 001.489-2.575V44.666a3.075 3.075 0 00-.106-.774zM74.255 143.167l-29.648-16.779 31.136-17.926.001-.001 34.164-19.669 29.674 17.084-21.772 12.428-43.555 24.863zm68.329-76.259v33.841l-12.475-7.182-17.231-9.92V49.806l12.475 7.182 17.231 9.92zm2.97-39.335l29.693 17.095-29.693 17.095-29.693-17.095 29.693-17.095zM54.06 114.089l-12.475 7.182V46.733l17.231-9.92 12.475-7.182v74.537l-17.231 9.921zM38.614 7.398l29.693 17.095-29.693 17.095L8.921 24.493 38.614 7.398zM5.938 29.632l12.475 7.182 17.231 9.92v79.676l.001.005-.001.006c0 .114.032.221.045.333.017.146.021.294.059.434l.002.007c.032.117.094.222.14.334.051.124.088.255.156.371a.036.036 0 00.004.009c.061.105.149.191.222.288.081.105.149.22.244.314l.008.01c.084.083.19.142.284.215.106.083.202.178.32.247l.013.005.011.008 34.139 19.321v34.175L5.939 144.867V29.632h-.001zm136.646 115.235l-65.352 37.625V148.31l48.399-27.628 16.953-9.677v33.862zm35.646-61.22l-29.706 17.102V66.908l17.231-9.92 12.475-7.182v33.841z" />
</g>
</svg>
</div>
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
<svg viewBox="0 0 651 192" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-16 w-auto text-gray-700 sm:h-20">
<g clip-path="url(#clip0)" fill="#EF3B2D">
<path d="M248.032 44.676h-16.466v100.23h47.394v-14.748h-30.928V44.676zM337.091 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.431 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162-.001 2.863-.479 5.584-1.432 8.161zM463.954 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.432 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162 0 2.863-.479 5.584-1.432 8.161zM650.772 44.676h-15.606v100.23h15.606V44.676zM365.013 144.906h15.607V93.538h26.776V78.182h-42.383v66.724zM542.133 78.182l-19.616 51.096-19.616-51.096h-15.808l25.617 66.724h19.614l25.617-66.724h-15.808zM591.98 76.466c-19.112 0-34.239 15.706-34.239 35.079 0 21.416 14.641 35.079 36.239 35.079 12.088 0 19.806-4.622 29.234-14.688l-10.544-8.158c-.006.008-7.958 10.449-19.832 10.449-13.802 0-19.612-11.127-19.612-16.884h51.777c2.72-22.043-11.772-40.877-33.023-40.877zm-18.713 29.28c.12-1.284 1.917-16.884 18.589-16.884 16.671 0 18.697 15.598 18.813 16.884h-37.402zM184.068 43.892c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002-35.648-20.524a2.971 2.971 0 00-2.964 0l-35.647 20.522-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v38.979l-29.706 17.103V24.493a3 3 0 00-.103-.776c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002L40.098 1.396a2.971 2.971 0 00-2.964 0L1.487 21.919l-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v122.09c0 1.063.568 2.044 1.489 2.575l71.293 41.045c.156.089.324.143.49.202.078.028.15.074.23.095a2.98 2.98 0 001.524 0c.069-.018.132-.059.2-.083.176-.061.354-.119.519-.214l71.293-41.045a2.971 2.971 0 001.489-2.575v-38.979l34.158-19.666a2.971 2.971 0 001.489-2.575V44.666a3.075 3.075 0 00-.106-.774zM74.255 143.167l-29.648-16.779 31.136-17.926.001-.001 34.164-19.669 29.674 17.084-21.772 12.428-43.555 24.863zm68.329-76.259v33.841l-12.475-7.182-17.231-9.92V49.806l12.475 7.182 17.231 9.92zm2.97-39.335l29.693 17.095-29.693 17.095-29.693-17.095 29.693-17.095zM54.06 114.089l-12.475 7.182V46.733l17.231-9.92 12.475-7.182v74.537l-17.231 9.921zM38.614 7.398l29.693 17.095-29.693 17.095L8.921 24.493 38.614 7.398zM5.938 29.632l12.475 7.182 17.231 9.92v79.676l.001.005-.001.006c0 .114.032.221.045.333.017.146.021.294.059.434l.002.007c.032.117.094.222.14.334.051.124.088.255.156.371a.036.036 0 00.004.009c.061.105.149.191.222.288.081.105.149.22.244.314l.008.01c.084.083.19.142.284.215.106.083.202.178.32.247l.013.005.011.008 34.139 19.321v34.175L5.939 144.867V29.632h-.001zm136.646 115.235l-65.352 37.625V148.31l48.399-27.628 16.953-9.677v33.862zm35.646-61.22l-29.706 17.102V66.908l17.231-9.92 12.475-7.182v33.841z"/>
</g>
</svg>
<div class="mt-8 bg-white dark:bg-gray-800 overflow-hidden shadow sm:rounded-lg">
<div class="grid grid-cols-1 md:grid-cols-2">
<div class="p-6">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"
>
<path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" /></svg>
<div class="ml-4 text-lg leading-7 font-semibold">
<a href="https://laravel.com/docs" class="underline text-gray-900 dark:text-white">Documentation</a>
</div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel has wonderful, thorough documentation covering every aspect of the framework. Whether you are new to the framework or have previous experience with Laravel, we recommend reading all of the documentation from beginning to end.
</div>
</div>
</div>
<div class="mt-8 bg-white dark:bg-gray-800 overflow-hidden shadow sm:rounded-lg">
<div class="grid grid-cols-1 md:grid-cols-2">
<div class="p-6">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel.com/docs" class="underline text-gray-900 dark:text-white">Documentation</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel has wonderful, thorough documentation covering every aspect of the framework. Whether you are new to the framework or have previous experience with Laravel, we recommend reading all of the documentation from beginning to end.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-t-0 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"></path><path d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laracasts.com" class="underline text-gray-900 dark:text-white">Laracasts</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript development. Check them out, see for yourself, and massively level up your development skills in the process.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel-news.com/" class="underline text-gray-900 dark:text-white">Laravel News</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel News is a community driven portal and newsletter aggregating all of the latest and most important news in the Laravel ecosystem, including new package releases and tutorials.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold text-gray-900 dark:text-white">Vibrant Ecosystem</div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel's robust library of first-party tools and libraries, such as <a href="https://forge.laravel.com" class="underline">Forge</a>, <a href="https://vapor.laravel.com" class="underline">Vapor</a>, <a href="https://nova.laravel.com" class="underline">Nova</a>, and <a href="https://envoyer.io" class="underline">Envoyer</a> help you take your projects to the next level. Pair them with powerful open source libraries like <a href="https://laravel.com/docs/billing" class="underline">Cashier</a>, <a href="https://laravel.com/docs/dusk" class="underline">Dusk</a>, <a href="https://laravel.com/docs/broadcasting" class="underline">Echo</a>, <a href="https://laravel.com/docs/horizon" class="underline">Horizon</a>, <a href="https://laravel.com/docs/sanctum" class="underline">Sanctum</a>, <a href="https://laravel.com/docs/telescope" class="underline">Telescope</a>, and more.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-t-0 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"
>
<path d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" /><path d="M15 13a3 3 0 11-6 0 3 3 0 016 0z" /></svg>
<div class="ml-4 text-lg leading-7 font-semibold">
<a href="https://laracasts.com" class="underline text-gray-900 dark:text-white">Laracasts</a>
</div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript development. Check them out, see for yourself, and massively level up your development skills in the process.
</div>
</div>
</div>
<div class="flex justify-center mt-4 sm:items-center sm:justify-between">
<div class="text-center text-sm text-gray-500 sm:text-left">
<div class="flex items-center">
<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor" class="-mt-px w-5 h-5 text-gray-400">
<path d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
<a href="https://laravel.bigcartel.com" class="ml-1 underline">
Shop
</a>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="ml-4 -mt-px w-5 h-5 text-gray-400">
<path d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
</svg>
<a href="https://github.com/sponsors/taylorotwell" class="ml-1 underline">
Sponsor
</a>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"
>
<path d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z" /></svg>
<div class="ml-4 text-lg leading-7 font-semibold">
<a href="https://laravel-news.com/" class="underline text-gray-900 dark:text-white">Laravel News</a>
</div>
</div>
<div class="ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
Laravel v{{ laravelVersion }} (PHP v{{ phpVersion }})
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel News is a community driven portal and newsletter aggregating all of the latest and most important news in the Laravel ecosystem, including new package releases and tutorials.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"
>
<path d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
<div class="ml-4 text-lg leading-7 font-semibold text-gray-900 dark:text-white">
Vibrant Ecosystem
</div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel's robust library of first-party tools and libraries, such as <a href="https://forge.laravel.com" class="underline">Forge</a>, <a href="https://vapor.laravel.com" class="underline">Vapor</a>, <a href="https://nova.laravel.com" class="underline">Nova</a>, and <a href="https://envoyer.io" class="underline">Envoyer</a> help you take your projects to the next level. Pair them with powerful open source libraries like <a href="https://laravel.com/docs/billing" class="underline">Cashier</a>, <a href="https://laravel.com/docs/dusk" class="underline">Dusk</a>, <a href="https://laravel.com/docs/broadcasting" class="underline">Echo</a>, <a href="https://laravel.com/docs/horizon" class="underline">Horizon</a>, <a href="https://laravel.com/docs/sanctum" class="underline">Sanctum</a>, <a href="https://laravel.com/docs/telescope" class="underline">Telescope</a>, and more.
</div>
</div>
</div>
</div>
</div>
<div class="flex justify-center mt-4 sm:items-center sm:justify-between">
<div class="text-center text-sm text-gray-500 sm:text-left">
<div class="flex items-center">
<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"
stroke="currentColor" class="-mt-px w-5 h-5 text-gray-400"
>
<path d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
<a href="https://laravel.bigcartel.com" class="ml-1 underline">
Shop
</a>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
viewBox="0 0 24 24" class="ml-4 -mt-px w-5 h-5 text-gray-400"
>
<path d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
</svg>
<a href="https://github.com/sponsors/taylorotwell" class="ml-1 underline">
Sponsor
</a>
</div>
</div>
<div class="ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
Laravel v{{ laravelVersion }} (PHP v{{ phpVersion }})
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
@@ -177,18 +201,26 @@
</style>
<script>
import { Head, Link } from '@inertiajs/inertia-vue3';
export default {
components: {
Head,
Link,
props: {
laravelVersion: {
type: String,
default: null,
},
props: {
canLogin: Boolean,
canRegister: Boolean,
laravelVersion: String,
phpVersion: String,
phpVersion: {
type: String,
default: null,
},
}
canLogin: {
type: Boolean,
default: false,
},
canRegister: {
type: Boolean,
default: false,
},
},
};
</script>
+2 -2
View File
@@ -33,9 +33,9 @@
<span class="mb0">
Exception {{ errors.exception }}
</span>
<br />
<br>
<span v-for="trace in errors.trace" :key="trace.id">
{{ trace.class }}{{ trace.type }}{{ trace.function }}<br />
{{ trace.class }}{{ trace.type }}{{ trace.function }}<br>
</span>
</p>
</template>
+16 -17
View File
@@ -1,25 +1,24 @@
<template>
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100">
<div>
<Link href="/">
<BreezeApplicationLogo class="w-20 h-20 fill-current text-gray-500" />
</Link>
</div>
<div class="w-full sm:max-w-md mt-6 px-6 py-6 bg-white shadow-md overflow-hidden sm:rounded-lg">
<slot />
</div>
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100">
<div>
<inertia-link href="/">
<breeze-application-logo class="w-20 h-20 fill-current text-gray-500" />
</inertia-link>
</div>
<div class="w-full sm:max-w-md mt-6 px-6 py-6 bg-white shadow-md overflow-hidden sm:rounded-lg">
<slot />
</div>
</div>
</template>
<script>
import BreezeApplicationLogo from '@/Components/ApplicationLogo.vue'
import { Link } from '@inertiajs/inertia-vue3';
import BreezeApplicationLogo from '@/Components/ApplicationLogo.vue';
export default {
components: {
BreezeApplicationLogo,
Link,
}
}
components: {
BreezeApplicationLogo,
}
};
</script>
+28 -28
View File
@@ -8,13 +8,12 @@ main {
<main>
<div class="min-h-full">
<div class="fixed w-full z-10 top-0">
<!-- main nav -->
<nav class="bg-gray-50 border-b max-w-8xl mx-auto px-3 sm:px-6 flex items-center justify-between h-10">
<div class="border border-gray-200 rounded-lg bg-white items-center sm:flex px-2 py-1 text-sm">
<Link :href="layoutData.url.vaults" class="flex-shrink-0">
<inertia-link :href="layoutData.url.vaults" class="flex-shrink-0">
{{ layoutData.user.name }}
</Link>
</inertia-link>
<!-- information about the current vault -->
<div v-if="layoutData.vault">
@@ -29,24 +28,26 @@ main {
<!-- search box -->
<div v-if="insideVault" class="flew-grow">
<input type="text" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md border border-gray-300 w-64 px-2 py-1" placeholder="Search a contact" />
<input type="text" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md border border-gray-300 w-64 px-2 py-1" placeholder="Search a contact">
</div>
<!-- icons -->
<div class="flew-grow">
<ul>
<li class="inline mr-4">
<Link :href="layoutData.url.settings" class="inline">
<svg xmlns="http://www.w3.org/2000/svg" class="inline-block text-gray-600 h-4 w-4 sm:h-5 sm:w-5 cursor-pointer" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</Link>
<inertia-link :href="layoutData.url.settings" class="inline">
<svg xmlns="http://www.w3.org/2000/svg" class="inline-block text-gray-600 h-4 w-4 sm:h-5 sm:w-5 cursor-pointer" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</inertia-link>
</li>
<li class="inline">
<svg @click="logout()" xmlns="http://www.w3.org/2000/svg" class="inline-block text-gray-600 h-4 w-4 sm:h-5 sm:w-5 cursor-pointer" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg xmlns="http://www.w3.org/2000/svg" class="inline-block text-gray-600 h-4 w-4 sm:h-5 sm:w-5 cursor-pointer" fill="none" viewBox="0 0 24 24" stroke="currentColor"
@click="logout()"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
/>
@@ -61,36 +62,36 @@ main {
<div class="max-w-8xl mx-auto px-4 sm:px-6 py-2 hidden md:block">
<div class="flex items-baseline justify-between space-x-6">
<div>
<Link href="" class="bg-blue-700 text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
<inertia-link href="" class="bg-blue-700 text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
Dashboard
</Link>
</inertia-link>
<Link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
<inertia-link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
Reports
</Link>
</inertia-link>
<Link href="contacts'" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
<inertia-link href="contacts'" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
Contacts
</Link>
</inertia-link>
<Link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
<inertia-link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
Gift center
</Link>
</inertia-link>
<Link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
<inertia-link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 mr-2 rounded-md text-sm font-medium">
Loans & debts center
</Link>
</inertia-link>
<Link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 rounded-md text-sm font-medium">
<inertia-link href="" class="hover:bg-gray-700 hover:text-white px-2 py-1 rounded-md text-sm font-medium">
Vault settings
</Link>
</inertia-link>
</div>
</div>
</div>
</nav>
</div>
<main class="mt-10 relative">
<slot></slot>
<slot />
</main>
</div>
@@ -99,12 +100,11 @@ main {
</template>
<script>
import { Link } from '@inertiajs/inertia-vue3';
import Toaster from '@/Shared/Toaster';
export default {
components: {
Link,
Toaster,
},
+10 -5
View File
@@ -37,18 +37,21 @@ button {
<template>
<button :class="classes" :disabled="state == 'loading'" class="relative text-sm" name="save" type="submit">
<span v-if="state == 'loading'">Loading</span>
<span v-if="state == 'loading'">
Loading
</span>
<!-- + icon -->
<svg v-if="icon === 'plus' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
<!-- check icon -->
<svg v-if="icon === 'check' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg v-if="icon === 'check' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
@@ -57,7 +60,9 @@ button {
</span>
<!-- arrow icon -->
<svg v-if="icon === 'arrow' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="ml-1 h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg v-if="icon === 'arrow' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="ml-1 h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</button>
+6 -6
View File
@@ -28,31 +28,31 @@ a {
</style>
<template>
<Link :class="classes" class="relative text-sm" :href="href">
<inertia-link :class="classes" class="relative text-sm" :href="href">
<!-- + icon -->
<svg v-if="icon === 'plus' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
<!-- check icon -->
<svg v-if="icon === 'check' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<svg v-if="icon === 'check' && state != 'loading'" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline relative icon" fill="none" viewBox="0 0 24 24"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
<span>
{{ text }}
</span>
</Link>
</inertia-link>
</template>
<script>
import { Link } from '@inertiajs/inertia-vue3';
export default {
components: {
Link,
},
props: {
+25 -16
View File
@@ -28,18 +28,18 @@
</label>
<div class="relative">
<textarea @input="$emit('update:modelValue', $event.target.value)"
v-model="modelValue"
:id="id"
:class="localTextAreaClasses"
:required="required"
:type="type"
:rows="rows"
:maxlength="maxlength"
@keydown.esc="sendEscKey"
@focus="showMaxLength"
@blur="displayMaxLength = false"
></textarea>
<textarea :id="id"
v-model="proxyValue"
:class="localTextAreaClasses"
:required="required"
:type="type"
:rows="rows"
:maxlength="maxlength"
@input="$emit('update:modelValue', $event.target.value)"
@keydown.esc="sendEscKey"
@focus="showMaxLength"
@blur="displayMaxLength = false"
/>
<span v-if="maxlength && displayMaxLength" class="length absolute text-xs rounded">
{{ charactersLeft }}
</span>
@@ -109,11 +109,16 @@ export default {
};
},
created() {
this.localTextAreaClasses = 'border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm ' + this.textareaClass;
},
computed: {
proxyValue: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
},
},
charactersLeft() {
var char = 0;
if (this.modelValue) {
@@ -124,6 +129,10 @@ export default {
},
},
created() {
this.localTextAreaClasses = 'border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm ' + this.textareaClass;
},
methods: {
sendEscKey() {
this.$emit('esc-key-pressed');
+6 -6
View File
@@ -29,17 +29,17 @@
<div class="relative component">
<input
:id="id"
:ref="ref"
:class="localInputClasses"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
:ref="ref"
:type="type"
:maxlength="maxlength"
:id="id"
:required="required"
:autofocus="autofocus"
:autocomplete="autocomplete"
:disabled="disabled"
@input="$emit('update:modelValue', $event.target.value)"
@keydown.esc="sendEscKey"
@focus="showMaxLength"
@blur="displayMaxLength = false"
@@ -57,7 +57,6 @@
<script>
export default {
emits: ['update:modelValue'],
props: {
id: {
@@ -121,6 +120,7 @@ export default {
default: 'input',
},
},
emits: ['update:modelValue'],
data() {
return {
@@ -146,7 +146,7 @@ export default {
methods: {
focus() {
this.$refs.input.focus()
this.$refs.input.focus();
},
showMaxLength() {
@@ -157,5 +157,5 @@ export default {
this.$emit('esc-key-pressed');
},
}
}
};
</script>
+3 -1
View File
@@ -24,7 +24,9 @@
levelClass, isOpen ? isVisibleClass : ''
]"
>
<span class="mr-1">👋</span> {{ messageText }}
<span class="mr-1">
👋
</span> {{ messageText }}
</div>
</template>
+2 -1
View File
@@ -1,7 +1,7 @@
require('./bootstrap');
import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/inertia-vue3';
import { createInertiaApp, Link } from '@inertiajs/inertia-vue3';
import { InertiaProgress } from '@inertiajs/progress';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
@@ -13,6 +13,7 @@ createInertiaApp({
return createApp({ render: () => h(app, props) })
.use(plugin)
.mixin({ methods: _.assign({ route }, require('./methods').default) })
.component('inertia-link', Link)
.mount(el);
},
});
+1 -1
View File
@@ -9,7 +9,7 @@
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
<link rel="stylesheet" href="{{ mix('css/app.css') }}" />
<!-- Scripts -->
@routes
+1 -1
View File
@@ -7,7 +7,7 @@
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet" />
<!-- Styles -->
<style>
+7
View File
@@ -11,6 +11,7 @@ use App\Http\Controllers\Settings\Personalize\PersonalizeController;
use App\Http\Controllers\Settings\Preferences\PreferencesController;
use App\Http\Controllers\Settings\CancelAccount\CancelAccountController;
use App\Http\Controllers\Settings\Personalize\Labels\PersonalizeLabelController;
use App\Http\Controllers\Settings\Personalize\Genders\PersonalizeGenderController;
use App\Http\Controllers\Settings\Personalize\Relationships\PersonalizeRelationshipController;
use App\Http\Controllers\Settings\Personalize\Relationships\PersonalizeRelationshipTypeController;
@@ -80,6 +81,12 @@ Route::middleware(['auth', 'verified'])->group(function () {
Route::post('labels', [PersonalizeLabelController::class, 'store'])->name('settings.personalize.label.store');
Route::put('labels/{label}', [PersonalizeLabelController::class, 'update'])->name('settings.personalize.label.update');
Route::delete('labels/{label}', [PersonalizeLabelController::class, 'destroy'])->name('settings.personalize.label.destroy');
// genders
Route::get('genders', [PersonalizeGenderController::class, 'index'])->name('settings.personalize.gender.index');
Route::post('genders', [PersonalizeGenderController::class, 'store'])->name('settings.personalize.gender.store');
Route::put('genders/{gender}', [PersonalizeGenderController::class, 'update'])->name('settings.personalize.gender.update');
Route::delete('genders/{gender}', [PersonalizeGenderController::class, 'destroy'])->name('settings.personalize.gender.destroy');
});
// cancel
+13 -13
View File
@@ -1,20 +1,20 @@
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
'./resources/js/**/*.vue',
],
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
'./resources/js/**/*.vue',
],
theme: {
extend: {
fontFamily: {
sans: ['Nunito', ...defaultTheme.fontFamily.sans],
},
},
theme: {
extend: {
fontFamily: {
sans: ['Nunito', ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [require('@tailwindcss/forms')],
plugins: [require('@tailwindcss/forms')],
};
@@ -0,0 +1,56 @@
<?php
namespace Tests\Unit\Controllers\Settings\Personalize\Genders\ViewHelpers;
use function env;
use Tests\TestCase;
use App\Models\Gender;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Http\Controllers\Settings\Personalize\Genders\ViewHelpers\PersonalizeGenderIndexViewHelper;
class PersonalizeGenderIndexViewHelperTest extends TestCase
{
use DatabaseTransactions;
/** @test */
public function it_gets_the_data_needed_for_the_view(): void
{
$gender = Gender::factory()->create();
$array = PersonalizeGenderIndexViewHelper::data($gender->account);
$this->assertEquals(
2,
count($array)
);
$this->assertArrayHasKey('genders', $array);
$this->assertEquals(
[
'settings' => env('APP_URL').'/settings',
'personalize' => env('APP_URL').'/settings/personalize',
'gender_store' => env('APP_URL').'/settings/personalize/genders',
],
$array['url']
);
}
/** @test */
public function it_gets_the_data_needed_for_the_data_transfer_object(): void
{
$gender = Gender::factory()->create();
$array = PersonalizeGenderIndexViewHelper::dtoGender($gender);
$this->assertEquals(
[
'id' => $gender->id,
'name' => $gender->name,
'url' => [
'update' => route('settings.personalize.gender.update', [
'gender' => $gender->id,
]),
'destroy' => route('settings.personalize.gender.destroy', [
'gender' => $gender->id,
]),
],
],
$array
);
}
}
@@ -22,6 +22,7 @@ class PersonalizeIndexViewHelperTest extends TestCase
'back' => env('APP_URL').'/settings',
'manage_relationships' => env('APP_URL').'/settings/personalize/relationships',
'manage_labels' => env('APP_URL').'/settings/personalize/labels',
'manage_genders' => env('APP_URL').'/settings/personalize/genders',
],
],
$array
+4 -4
View File
@@ -1,9 +1,9 @@
const path = require('path');
module.exports = {
resolve: {
alias: {
'@': path.resolve('resources/js'),
},
resolve: {
alias: {
'@': path.resolve('resources/js'),
},
},
};
+8 -8
View File
@@ -1,14 +1,14 @@
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.vue()
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
])
.webpackConfig(require('./webpack.config'));
.vue()
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
])
.webpackConfig(require('./webpack.config'));
if (mix.inProduction()) {
mix.version();
mix.version();
}