Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions app/Services/SyncContact.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Services;

use App\Models\Contact;

class SyncContact
{
public function __construct(public Contact $contact)
{ }

public function __invoke(): Contact
{
if ($this->contact->last_synced_at < now()->subMinutes(5)) {
// fetch and store the contact
$contact = (new GetContact($this->contact->vault, $this->contact->id))->store();

if ($contact !== null) {
return $contact;
}
}

return $this->contact;
}
}
26 changes: 26 additions & 0 deletions app/Services/SyncVault.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\Services;

use App\Models\Vault;
use Illuminate\Database\Eloquent\Collection;

class SyncVault
{
public function __construct(public Vault $vault)
{ }

public function __invoke(): Vault
{
if ($this->vault->last_synced_at < now()->subMinutes(5)) {
// fetch and store the vault
$vault = (new GetVault($this->vault->id))->store();

if ($vault !== null) {
return $vault;
}
}

return $this->vault;
}
}
1 change: 1 addition & 0 deletions resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
@theme {
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
}
@custom-variant dark (&:where(.dark, .dark *));
20 changes: 15 additions & 5 deletions resources/views/components/layouts/app.blade.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
@props([
'vault' => null,
'breadcrumbs' => null,
])

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
@include('components.layouts.meta')
<x-layouts.meta />
</head>
<body class="font-sans text-gray-900 antialiased">
<div class="flex min-h-screen flex-col items-center bg-gray-100 pt-6 sm:justify-center sm:pt-0 dark:bg-neutral-950 dark:text-white">
<div>
<body class="nativephp-safe-area font-sans text-gray-900 dark:text-white antialiased">

<x-layouts.app.header :vault="$vault != null ? $vault->attributes->get('vault') : null" :breadcrumbs="$breadcrumbs != null ? $breadcrumbs->attributes->get('breadcrumbs') : null" />

<main class="flex flex-1 flex-col min-h-screen bg-gray-50 sm:justify-center sm:pt-0 px-2 py-px dark:bg-[#151B23]">
<div class="mx-auto flex w-full grow flex-col items-stretch rounded-lg bg-[#F9FBFC] shadow-xs ring-1 ring-[#E6E7E9] dark:bg-[#202830] dark:ring-gray-700">
{{ $slot }}
</div>
</div>
</main>

<x-layouts.app.footer />

@fluxScripts
@livewireScripts
Expand Down
2 changes: 2 additions & 0 deletions resources/views/components/layouts/app/footer.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<footer {{ $attributes->class(['flex w-full items-center pr-4 pl-9 dark:bg-[#151B23]']) }}>
</footer>
100 changes: 100 additions & 0 deletions resources/views/components/layouts/app/header.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
@props([
'vault' => null,
'breadcrumbs' => null,
])

<header class="top-0 left-0 w-full pl-[var(--inset-left)] pr-[var(--inset-right)]" x-data="{
settings: false,
vault: false,
}">

<div class="flex">
@if ($breadcrumbs && count($breadcrumbs) > 0)
<nav class="flex items-center gap-2 ms-3 text-sm text-gray-600 dark:text-gray-400" aria-label="Breadcrumb">
@foreach ($breadcrumbs as $breadcrumb)
<x-link href="{{ $breadcrumb['url'] }}" title="{{ isset($breadcrumb['title']) ? $breadcrumb['title'] : '' }}">
<x-phosphor-caret-left class="size-5 min-w-3 text-gray-400 dark:text-gray-600" />
{{ isset($breadcrumb['label']) ? $breadcrumb['label'] : '' }}
</x-link>
@endforeach
</nav>
@endif

<search class="flex-1 items-center gap-3 pt-3 pb-3" aria-label="Main navigation">
<!-- search -->
<flux:input type="text" name="search" placeholder="{{ __('Search...') }}" class="w-full rounded-md border-0 px-3 py-2 text-sm placeholder-gray-400 focus:bg-white focus:ring-2 focus:ring-blue-500 dark:focus:bg-[#2A3745]">
<x-slot name="iconLeading">
<flux:button size="sm" variant="subtle" x-on:click="settings = true" icon="bars-3" class="ms-1" />
</x-slot>

@if ($vault)
<x-slot name="iconTrailing">
<flux:button size="sm" variant="subtle" x-on:click="vault = true" icon="cube" class="me-1" />
</x-slot>
@endif
</flux:input>
</search>
</div>

<!-- settings overlay -->
<div x-cloak x-show="settings" x-transition:enter.duration.100ms x-transition:leave.duration.50ms class="fixed inset-0 z-50 bg-white dark:bg-gray-900">
<div class="flex h-full flex-col">
<!-- menu header -->
<div class="flex items-center justify-between border-b border-gray-200 px-2 py-1 dark:border-gray-700">
<button x-on:click="settings = false" class="flex items-center gap-2 rounded-md border border-transparent py-2 font-medium hover:border-gray-200 hover:bg-gray-100 dark:hover:border-gray-600 dark:hover:bg-gray-800">
<x-phosphor-x class="size-5 text-gray-600 dark:text-gray-400" />
</button>
</div>

<!-- menu content -->
<div class="flex-1 space-y-4 p-4">
<x-link x-on:click="settings = false" href="" class="flex items-center gap-3 rounded-md p-3 text-lg font-medium text-gray-800 transition-colors hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-800">
<x-phosphor-user class="size-5 text-gray-600 dark:text-gray-400" />
{{ __('Profile') }}
</x-link>
</div>
</div>
</div>

@if ($vault)
<!-- vault overlay -->
<div x-cloak x-show="vault" x-transition:enter.duration.100ms x-transition:leave.duration.50ms class="fixed inset-0 z-50 bg-white dark:bg-gray-900">
<div class="flex h-full flex-col">
<!-- menu header -->
<div class="flex items-center justify-between border-b border-gray-200 px-2 py-1 dark:border-gray-700">
<button x-on:click="vault = false" class="flex items-center gap-2 rounded-md border border-transparent py-2 font-medium hover:border-gray-200 hover:bg-gray-100 dark:hover:border-gray-600 dark:hover:bg-gray-800">
<x-phosphor-x class="size-5 text-gray-600 dark:text-gray-400" />
</button>
</div>

<!-- menu content -->
<div class="flex-1 space-y-4 p-4">

<h1 class="text-lg">{{ __('Vault') }}</h1>
<div class="ms-2">
@foreach (\App\Models\Vault::all() as $vaultItem)
<x-link href="{{ route('vaults.show', $vaultItem) }}" class="flex items-center p-3">
{{ $vaultItem->name }}
@if ($vault->id === $vaultItem->id)
<x-phosphor-check-circle class="ms-2 size-5 text-green-500 dark:text-green-500" />
@endif
<br/>
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ $vaultItem->description }}
</span>
</x-link>
@endforeach
</div>

<x-link href="{{ route('vaults.create') }}" class="flex items-center gap-3 text-lg">
{{ __('Add a vault') }}
</x-link>

<x-link href="{{ route('home') }}" class="flex items-center gap-3 text-lg">
{{ __('Manage your account') }}
</x-link>
</div>
</div>
</div>
@endif
</header>
2 changes: 1 addition & 1 deletion resources/views/components/layouts/meta.blade.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover">

<title>{{ $title ?? config('app.name') }}</title>

Expand Down
2 changes: 1 addition & 1 deletion resources/views/components/link.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@props([
'external' => false,
'navigate' => true,
'noUnderline' => false,
'noUnderline' => true,
])

<a @if ($external) target="_blank" @endif @if ($navigate) wire:navigate @endif
Expand Down
11 changes: 6 additions & 5 deletions resources/views/livewire/contacts/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use function Livewire\Volt\mount;
use function Livewire\Volt\state;
use function Livewire\Volt\with;

state(['vault'])->locked();
state(['name']);
Expand All @@ -31,17 +32,17 @@
<div>
<livewire:contacts.lazy.index :$vault lazy />

<x-box
<div
x-data="{
showForm: false,
toggle: function() { this.showForm = !this.showForm }
}">
<div class="flex justify-center" x-show="!showForm" x-transition:enter.duration.200ms>
<flux:button icon="plus-circle" @click.prevent="toggle()">{{ __('Add a contact') }}</flux:button>
<div class="fixed right-6 bottom-2 pl-[var(--inset-left)] pr-[var(--inset-right)] pb-[var(--inset-bottom)]" x-show="!showForm" x-transition:enter.duration.200ms>
<flux:button icon="plus-circle" variant="subtle" @click.prevent="toggle()" icon:class="size-16 text-sky-300 dark:text-sky-700" />
</div>

<!-- create contact form -->
<form method="POST" wire:submit="create" class="space-y-6" wire:cloak x-show="showForm" x-transition:enter.duration.200ms>
<form method="POST" wire:submit="create" wire:cloak x-show="showForm" x-transition:enter="transition duration-50 ease-out" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition duration-50 ease-in" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" class="fixed inset-0 z-50 space-y-6 bg-white dark:bg-gray-900 flex flex-col gap-2">
<x-input wire:model="name" id="name" :label="__('Contact name')" type="text" required />

<div class="flex items-center justify-between">
Expand All @@ -62,5 +63,5 @@
</div>
</div>
</form>
</x-box>
</div>
</div>
1 change: 0 additions & 1 deletion resources/views/livewire/contacts/lazy/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

placeholder(<<<'HTML'
<div>
Loading...
<livewire:contacts.partials.index :$vault :contacts="$vault->contacts" />
</div>
HTML
Expand Down
13 changes: 2 additions & 11 deletions resources/views/livewire/contacts/lazy/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use App\Models\Contact;
use App\Models\Vault;
use App\Services\GetContact;
use App\Services\SyncContact;

use function Livewire\Volt\mount;
use function Livewire\Volt\placeholder;
Expand All @@ -19,16 +19,7 @@

mount(function (Vault $vault, Contact $contact) {
$this->vault = $vault;
$this->contact = $contact;

if ($contact->last_synced_at < now()->subMinutes(5)) {
// fetch and store the contact
$updateContact = (new GetContact($this->vault, $contact->id))->store();

if ($updateContact !== null) {
$this->contact = $updateContact;
}
}
$this->contact = (new SyncContact($contact))();
});
?>

Expand Down
2 changes: 1 addition & 1 deletion resources/views/livewire/contacts/partials/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<div>
@foreach ($contacts as $contact)
<div class="mb-2">
<x-link href="{{ route('contact.show', [$vault, $contact]) }}">
<x-link href="{{ route('contacts.show', [$vault, $contact]) }}">
{{ $contact->name }}
</x-link>
</div>
Expand Down
9 changes: 0 additions & 9 deletions resources/views/livewire/contacts/partials/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,6 @@
?>

<div>
<x-link href="{{ route('vault.show', $vault) }}">
<div class="flex items-center gap-2">
<x-phosphor-caret-left class="size-4 min-w-3" />
<span>
{{ __('Vault') }}
</span>
</div>
</x-link>

<h1 class="text-2xl font-bold mb-4">
{{ $contact->name }}
</h1>
Expand Down
10 changes: 10 additions & 0 deletions resources/views/livewire/contacts/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@
});
?>

<x-slot:vault :vault="$vault"></x-slot>

<x-slot:breadcrumbs :breadcrumbs="[
['title' => $vault->name, 'url' => route('vaults.show', $vault)],
]"></x-slot>

<x-slot:title>
{{ __('Contact Details') }} - {{ $contact->name }}
</x-slot>

<div>
<livewire:contacts.lazy.show :$vault :$contact lazy />
</div>
56 changes: 56 additions & 0 deletions resources/views/livewire/vaults/create.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

use App\Services\CreateVault;

use function Livewire\Volt\state;

state(['name', 'description']);

$create = function() {
$validated = $this->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string|max:255',
]);

$vault = (new CreateVault)->store($validated);

$this->reset(['name', 'description']);

$this->dispatch('vault-created');

return redirect()->route('vaults.show', $vault);
};

$back = function() {
xdebug_break();
return back();
};
?>

<div class="w-full max-w-96 mx-auto p-4">
<h2 class="text-xl font-semibold mb-2">{{ __('Create a vault') }}</h2>

<!-- create vault form -->
<form method="POST" wire:submit="create" class="space-y-6">
<x-input wire:model="name" id="name" :label="__('Vault name')" type="text" required />
<x-input wire:model="description" id="description" :label="__('Vault description')" type="text" :optional="true" />

<div class="flex items-center justify-between">
<flux:button variant="filled" x-on:click.prevent="$wire.back()">
{{ __('Cancel') }}
</flux:button>

<div class="flex items-center gap-4">
<div class="flex items-center justify-end">
<flux:button variant="primary" type="submit" class="w-full">
{{ __('Create') }}
</flux:button>
</div>

<x-action-message class="me-3" on="vault-created">
{{ __('Created.') }}
</x-action-message>
</div>
</div>
</form>
</div>
Loading