Skip to content

Commit

Permalink
feat: upcoming reminders on dashboard (monicahq/chandler#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
djaiss authored Jul 21, 2022
1 parent 2a26a8f commit 35e1b87
Show file tree
Hide file tree
Showing 15 changed files with 522 additions and 108 deletions.
264 changes: 214 additions & 50 deletions composer.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public function show(Request $request, int $vaultId)
return Inertia::render('Vault/Dashboard/Index', [
'layoutData' => VaultIndexViewHelper::layoutData($vault),
'lastUpdatedContacts' => VaultShowViewHelper::lastUpdatedContacts($vault),
'upcomingReminders' => VaultShowViewHelper::upcomingReminders($vault, Auth::user()),
]);
}

Expand Down
60 changes: 60 additions & 0 deletions domains/Vault/ManageVault/Web/ViewHelpers/VaultShowViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

namespace App\Vault\ManageVault\Web\ViewHelpers;

use App\Helpers\DateHelper;
use App\Models\ContactReminder;
use App\Models\User;
use App\Models\UserNotificationChannel;
use App\Models\Vault;
use Carbon\Carbon;
use DB;
use Illuminate\Support\Collection;

class VaultShowViewHelper
Expand All @@ -27,4 +33,58 @@ public static function lastUpdatedContacts(Vault $vault): Collection
];
});
}

public static function upcomingReminders(Vault $vault, User $user): Collection
{
// this query is a bit long and tough to do, and it could surely
// be optimized if I knew how to properly join queries
// first we get all the users the vault
$usersInVaultIds = $vault->users->pluck('id')->toArray();

// then we get all the user notification channels for those users
$userNotificationChannelIds = UserNotificationChannel::whereIn('user_id', $usersInVaultIds)
->get()
->pluck('id')
->unique('id')
->toArray();

// then we get all the contact reminders scheduled for those channels
$currentDate = Carbon::now()->copy();
$currentDate->second = 0;

$contactRemindersScheduled = DB::table('contact_reminder_scheduled')
->whereDate('scheduled_at', '<=', $currentDate->addDays(30))
->where('triggered_at', null)
->whereIn('user_notification_channel_id', $userNotificationChannelIds)
->get();

// finally, we get all the details about those reminders
// yeah, it's painful
$remindersCollection = collect();
foreach ($contactRemindersScheduled as $contactReminderScheduled) {
$reminder = ContactReminder::where('id', $contactReminderScheduled->contact_reminder_id)->with('contact')->first();
$contact = $reminder->contact;

$scheduledAtDate = Carbon::createFromFormat('Y-m-d H:i:s', $contactReminderScheduled->scheduled_at);

$remindersCollection->push([
'id' => $reminder->id,
'label' => $reminder->label,
'scheduled_at' => DateHelper::format($scheduledAtDate, $user),
'contact' => [
'id' => $contact->id,
'name' => $contact->name,
'avatar' => $contact->avatar,
'url' => [
'show' => route('contact.show', [
'vault' => $contact->vault_id,
'contact' => $contact->id,
]),
],
],
]);
}

return $remindersCollection;
}
}
3 changes: 3 additions & 0 deletions lang/en/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
'breadcrumb_vault_index' => 'All the vaults',
'breadcrumb_vault_create' => 'add a vault',
'breadcrumb_contact_index' => 'Contacts',
'breadcrumb_contact_show' => 'Profile of :name',
'breadcrumb_contact_create' => 'Create a contact',
'breadcrumb_contact_note_index' => 'All the notes',
'breadcrumb_settings' => 'Settings',
'breadcrumb_settings_preferences' => 'User preferences',
'breadcrumb_settings_notification_channels' => 'Notification channels',
Expand Down Expand Up @@ -52,6 +54,7 @@
'view_all' => 'View all',
'previous' => 'Previous',
'next' => 'Next',
'view_all' => 'View all',

'error_title' => '👇 Oops. An error occured.',

Expand Down
2 changes: 2 additions & 0 deletions lang/en/vault.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
**************************************************************/

'dashboard_last_updated_contacts_title' => 'Last updated',
'dashboard_reminders_title' => 'Reminders for the next 30 days',
'dashboard_reminders_blank' => 'No planned reminders.',

/***************************************************************
* VAULT SETTINGS
Expand Down
3 changes: 3 additions & 0 deletions lang/fr/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
'breadcrumb_vault_index' => 'Toutes les voûtes',
'breadcrumb_vault_create' => 'Ajouter une nouvelle voûte',
'breadcrumb_contact_index' => 'Contacts',
'breadcrumb_contact_show' => 'Profil de :name',
'breadcrumb_contact_create' => 'Créer un contact',
'breadcrumb_contact_note_index' => 'Toutes les notes',
'breadcrumb_settings' => 'Paramètres',
'breadcrumb_settings_preferences' => 'Préférences de l’utilisateur',
'breadcrumb_settings_notification_channels' => 'Chaînes de notification',
Expand Down Expand Up @@ -52,6 +54,7 @@
'view_all' => 'Tout voir',
'previous' => 'Précédent',
'next' => 'Suivant',
'view_all' => 'Tout voir',

'error_title' => '👇 Oops. Une erreur est survenue.',

Expand Down
2 changes: 2 additions & 0 deletions lang/fr/vault.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
**************************************************************/

'dashboard_last_updated_contacts_title' => 'Récemment mis à jour',
'dashboard_reminders_title' => 'Rappels dans les 30 prochains jours',
'dashboard_reminders_blank' => 'Aucun rappel planifié.',

/***************************************************************
* VAULT SETTINGS
Expand Down
10 changes: 5 additions & 5 deletions resources/js/Pages/Vault/Contact/Notes/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<li class="mr-2 inline text-gray-600 dark:text-slate-200">{{ $t('app.breadcrumb_location') }}</li>
<li class="mr-2 inline">
<inertia-link :href="layoutData.vault.url.contacts" class="text-blue-500 hover:underline">
Contacts
{{ $t('app.breadcrumb_contact_index') }}
</inertia-link>
</li>
<li class="relative mr-2 inline">
Expand All @@ -24,9 +24,9 @@
</svg>
</li>
<li class="mr-2 inline">
<inertia-link :href="data.url.contact" class="text-blue-500 hover:underline">
Profile of {{ data.contact.name }}
</inertia-link>
<inertia-link :href="data.url.contact" class="text-blue-500 hover:underline">{{
$t('app.breadcrumb_contact_show', { name: data.contact.name })
}}</inertia-link>
</li>
<li class="relative mr-2 inline">
<svg
Expand All @@ -38,7 +38,7 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</li>
<li class="inline">All the notes</li>
<li class="inline">{{ $t('app.breadcrumb_contact_note_index') }}</li>
</ul>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions resources/js/Pages/Vault/Contact/Show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
<ul class="text-sm">
<li class="mr-2 inline text-gray-600 dark:text-slate-200">{{ $t('app.breadcrumb_location') }}</li>
<li class="mr-2 inline">
<inertia-link :href="layoutData.vault.url.contacts" class="text-blue-500 hover:underline"
>Contacts</inertia-link
>
<inertia-link :href="layoutData.vault.url.contacts" class="text-blue-500 hover:underline">
{{ $t('app.breadcrumb_contact_index') }}
</inertia-link>
</li>
<li class="relative mr-2 inline">
<svg
Expand All @@ -37,7 +37,7 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</li>
<li class="inline">Profile of {{ data.contact_name.name }}</li>
<li class="inline">{{ $t('app.breadcrumb_contact_show', { name: data.contact_name.name }) }}</li>
</ul>
</div>
</div>
Expand Down
62 changes: 15 additions & 47 deletions resources/js/Pages/Vault/Dashboard/Index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<style lang="scss" scoped>
.grid {
grid-template-columns: 200px 1fr 200px;
grid-template-columns: 200px 1fr 300px;
}
@media (max-width: 480px) {
Expand Down Expand Up @@ -28,7 +28,7 @@ input[type='checkbox'] {
<!-- left -->
<div class="p-3 sm:p-0">
<!-- favorites -->
<h3 class="mb-3 border-b border-gray-200 font-medium">
<h3 class="mb-3 border-b border-gray-200 pb-1 font-medium">
<span class="relative">
<svg
xmlns="http://www.w3.org/2000/svg"
Expand All @@ -47,27 +47,7 @@ input[type='checkbox'] {
</h3>

<!-- last updated contacts -->
<h3 class="mb-3 border-b border-gray-200 font-medium">
<span class="relative">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon-sidebar relative inline h-4 w-4 text-gray-300 hover:text-gray-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="{2}">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
{{ $t('vault.dashboard_last_updated_contacts_title') }}
</h3>
<div v-for="contact in lastUpdatedContacts" :key="contact.id" class="mb-2 flex items-center text-sm">
<div v-html="contact.avatar" class="mr-2 h-5 w-5"></div>

<inertia-link :href="contact.url.show" class="text-blue-500 hover:underline">{{
contact.name
}}</inertia-link>
</div>
<last-updated :data="lastUpdatedContacts" />
</div>

<!-- middle -->
Expand Down Expand Up @@ -153,30 +133,10 @@ input[type='checkbox'] {

<!-- right -->
<div class="p-3 sm:p-0">
<div class="mb-10">
<h3 class="mb-3 border-b border-gray-200 font-medium">
<span class="relative">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon-sidebar relative inline h-4 w-4 text-gray-300 hover:text-gray-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</span>
Reminders
</h3>
<p class="text-xs text-gray-400">Nov 09</p>
<p class="mb-3 text-sm">Birthday John</p>
<p class="text-xs text-gray-400">Nov 13</p>
<p class="mb-3 text-sm">Wedding Henri</p>
</div>
<h3 class="mb-3 border-b border-gray-200 font-medium">
<!-- upcoming reminders -->
<upcoming-reminders :data="upcomingReminders" />

<h3 class="mb-3 border-b border-gray-200 pb-1 font-medium">
<span class="relative">
<svg
xmlns="http://www.w3.org/2000/svg"
Expand Down Expand Up @@ -221,6 +181,8 @@ input[type='checkbox'] {
<script>
import Layout from '@/Shared/Layout';
import SmallContact from '@/Shared/SmallContact';
import LastUpdated from '@/Pages/Vault/Dashboard/Partials/LastUpdated';
import UpcomingReminders from '@/Pages/Vault/Dashboard/Partials/UpcomingReminders';
import Activity from '@/Pages/Vault/Dashboard/Partials/Feed/Activity';
import Entry from '@/Pages/Vault/Dashboard/Partials/Feed/Entry';
import Goal from '@/Pages/Vault/Dashboard/Partials/Feed/Goal';
Expand All @@ -231,6 +193,8 @@ import PrettyButton from '@/Shared/Form/PrettyButton';
export default {
components: {
Layout,
LastUpdated,
UpcomingReminders,
PrettyButton,
SmallContact,
Entry,
Expand All @@ -249,6 +213,10 @@ export default {
type: Object,
default: null,
},
upcomingReminders: {
type: Object,
default: null,
},
},
data() {
Expand Down
41 changes: 41 additions & 0 deletions resources/js/Pages/Vault/Dashboard/Partials/LastUpdated.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<style lang="scss" scoped>
.icon-sidebar {
color: #737e8d;
top: -2px;
}
</style>

<template>
<div>
<h3 class="mb-3 border-b border-gray-200 pb-1 font-medium">
<span class="relative">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon-sidebar relative inline h-4 w-4 text-gray-300 hover:text-gray-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="{2}">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
{{ $t('vault.dashboard_last_updated_contacts_title') }}
</h3>
<div v-for="contact in data" :key="contact.id" class="mb-2 flex items-center text-sm">
<div v-html="contact.avatar" class="mr-2 h-5 w-5"></div>

<inertia-link :href="contact.url.show" class="text-blue-500 hover:underline">{{ contact.name }}</inertia-link>
</div>
</div>
</template>

<script>
export default {
props: {
data: {
type: Object,
default: null,
},
},
};
</script>
Loading

0 comments on commit 35e1b87

Please sign in to comment.