mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
Use DaisyUI for styling the Family feature
This commit is contained in:
parent
c6fc4328d7
commit
0a61f9bf68
6 changed files with 167 additions and 172 deletions
|
|
@ -1,25 +1,24 @@
|
|||
<div class="container mx-auto px-4 py-8">
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<div class="bg-white dark:bg-gray-800 shadow dark:shadow-gray-700 rounded-lg p-6">
|
||||
<div class="bg-base-200 rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100">
|
||||
<h1 class="text-2xl font-bold text-base-content">
|
||||
<%= t('families.edit.title', default: 'Edit Family') %>
|
||||
</h1>
|
||||
<%= link_to family_path(@family),
|
||||
class: "text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200 font-medium" do %>
|
||||
class: "btn btn-ghost" do %>
|
||||
<%= t('families.edit.back', default: '← Back to Family') %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= form_with model: @family, local: true, class: "space-y-6" do |form| %>
|
||||
<% if @family.errors.any? %>
|
||||
<div class="bg-red-50 dark:bg-red-900/50 border border-red-200 dark:border-red-700 rounded-md p-4">
|
||||
<div class="flex">
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-red-800 dark:text-red-200">
|
||||
<div class="alert alert-error">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium">
|
||||
<%= t('families.edit.error_title', default: 'There were problems with your submission:') %>
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-red-700 dark:text-red-300">
|
||||
<div class="mt-2 text-sm">
|
||||
<ul class="list-disc pl-5 space-y-1">
|
||||
<% @family.errors.full_messages.each do |message| %>
|
||||
<li><%= message %></li>
|
||||
|
|
@ -28,49 +27,48 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div>
|
||||
<%= form.label :name, t('families.form.name', default: 'Family Name'), class: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2" %>
|
||||
<%= form.label :name, t('families.form.name', default: 'Family Name'), class: "label label-text font-medium mb-2" %>
|
||||
<%= form.text_field :name,
|
||||
class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
|
||||
class: "input input-bordered w-full",
|
||||
placeholder: t('families.form.name_placeholder', default: 'Enter your family name') %>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
<p class="mt-1 text-sm text-base-content opacity-50">
|
||||
<%= t('families.edit.name_help', default: 'Choose a name that all family members will recognize.') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-md">
|
||||
<h3 class="text-sm font-medium text-gray-900 dark:text-gray-100 mb-2">
|
||||
<div class="bg-base-300 p-4 rounded-md">
|
||||
<h3 class="text-sm font-medium text-base-content mb-2">
|
||||
<%= t('families.edit.family_info', default: 'Family Information') %>
|
||||
</h3>
|
||||
<dl class="grid grid-cols-1 gap-x-4 gap-y-2 sm:grid-cols-2">
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
|
||||
<dt class="text-sm font-medium text-base-content opacity-60">
|
||||
<%= t('families.edit.creator', default: 'Created by') %>
|
||||
</dt>
|
||||
<dd class="text-sm text-gray-900 dark:text-gray-100"><%= @family.creator.email %></dd>
|
||||
<dd class="text-sm text-base-content"><%= @family.creator.email %></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
|
||||
<dt class="text-sm font-medium text-base-content opacity-60">
|
||||
<%= t('families.edit.created_on', default: 'Created on') %>
|
||||
</dt>
|
||||
<dd class="text-sm text-gray-900 dark:text-gray-100"><%= @family.created_at.strftime('%B %d, %Y') %></dd>
|
||||
<dd class="text-sm text-base-content"><%= @family.created_at.strftime('%B %d, %Y') %></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
|
||||
<dt class="text-sm font-medium text-base-content opacity-60">
|
||||
<%= t('families.edit.members_count', default: 'Members') %>
|
||||
</dt>
|
||||
<dd class="text-sm text-gray-900 dark:text-gray-100">
|
||||
<dd class="text-sm text-base-content">
|
||||
<%= pluralize(@family.members.count, 'member') %>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
|
||||
<dt class="text-sm font-medium text-base-content opacity-60">
|
||||
<%= t('families.edit.last_updated', default: 'Last updated') %>
|
||||
</dt>
|
||||
<dd class="text-sm text-gray-900 dark:text-gray-100"><%= @family.updated_at.strftime('%B %d, %Y') %></dd>
|
||||
<dd class="text-sm text-base-content"><%= @family.updated_at.strftime('%B %d, %Y') %></dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
@ -78,9 +76,9 @@
|
|||
<div class="flex items-center justify-between pt-4">
|
||||
<div class="flex space-x-3">
|
||||
<%= form.submit t('families.edit.save_changes', default: 'Save Changes'),
|
||||
class: "bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 text-white px-6 py-2 rounded-md font-medium transition-colors duration-200" %>
|
||||
class: "btn btn-primary" %>
|
||||
<%= link_to family_path(@family),
|
||||
class: "bg-gray-300 hover:bg-gray-400 dark:bg-gray-600 dark:hover:bg-gray-500 text-gray-700 dark:text-gray-200 px-6 py-2 rounded-md font-medium transition-colors duration-200" do %>
|
||||
class: "btn btn-neutral" do %>
|
||||
<%= t('families.edit.cancel', default: 'Cancel') %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
@ -89,7 +87,8 @@
|
|||
<%= link_to family_path(@family),
|
||||
method: :delete,
|
||||
data: { confirm: 'Are you sure you want to delete this family? This action cannot be undone.', turbo_confirm: 'Are you sure you want to delete this family? This action cannot be undone.' },
|
||||
class: "text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300 font-medium" do %>
|
||||
class: "btn btn-outline btn-error" do %>
|
||||
<%= icon 'trash-2', class: "inline-block w-4 h-4 mr-2 -mt-1" %>
|
||||
Delete Family
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
<div class="container mx-auto px-4 py-8">
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<div class="text-center mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
<h1 class="text-3xl font-bold text-base-content mb-4">
|
||||
<%= t('families.index.title', default: 'Family Management') %>
|
||||
</h1>
|
||||
<p class="text-gray-600 dark:text-gray-400">
|
||||
<p class="text-base-content opacity-60">
|
||||
<%= t('families.index.description', default: 'Create or join a family to share your location data with loved ones.') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white dark:bg-gray-800 shadow dark:shadow-gray-700 rounded-lg p-6">
|
||||
<h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-gray-100">
|
||||
<div class="bg-base-200 rounded-lg p-6">
|
||||
<h2 class="text-xl font-semibold mb-4 text-base-content">
|
||||
<%= t('families.index.create_family', default: 'Create Your Family') %>
|
||||
</h2>
|
||||
|
||||
<%= form_with model: Family.new, local: true, class: "space-y-4" do |form| %>
|
||||
<div>
|
||||
<%= form.label :name, t('families.form.name', default: 'Family Name'), class: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1" %>
|
||||
<%= form.label :name, t('families.form.name', default: 'Family Name'), class: "label label-text font-medium mb-1" %>
|
||||
<%= form.text_field :name,
|
||||
placeholder: t('families.form.name_placeholder', default: 'Enter your family name'),
|
||||
class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" %>
|
||||
class: "input input-bordered w-full" %>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<%= form.submit t('families.form.create', default: 'Create Family'),
|
||||
class: "bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 text-white px-6 py-2 rounded-md font-medium transition-colors duration-200" %>
|
||||
class: "btn btn-primary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 text-center">
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
|
||||
<h3 class="text-lg font-medium text-base-content mb-4">
|
||||
<%= t('families.index.have_invitation', default: 'Have an invitation?') %>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-4">
|
||||
<p class="text-base-content opacity-60 mb-4">
|
||||
<%= t('families.index.invitation_instructions', default: 'If someone has invited you to join their family, you should have received an email with an invitation link.') %>
|
||||
</p>
|
||||
<div class="text-sm text-gray-500 dark:text-gray-400">
|
||||
<div class="text-sm text-base-content opacity-50">
|
||||
<%= t('families.index.invitation_help', default: 'Check your email for an invitation link that looks like: ') %>
|
||||
<code class="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-xs">
|
||||
<code class="bg-base-300 text-base-content px-2 py-1 rounded text-xs">
|
||||
<%= "#{request.base_url}/invitations/..." %>
|
||||
</code>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,23 @@
|
|||
<div class="container mx-auto px-4 py-8">
|
||||
<div class="max-w-2xl mx-auto">
|
||||
<div class="text-center mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4">
|
||||
<h1 class="text-3xl font-bold text-base-content mb-4">
|
||||
<%= t('families.new.title', default: 'Create Your Family') %>
|
||||
</h1>
|
||||
<p class="text-gray-600 dark:text-gray-400">
|
||||
<p class="text-base-content opacity-60">
|
||||
<%= t('families.new.description', default: 'Create a family to share your location data with your loved ones.') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-white dark:bg-gray-800 shadow dark:shadow-gray-700 rounded-lg p-6">
|
||||
<div class="bg-base-200 rounded-lg p-6">
|
||||
<%= form_with model: @family, local: true, class: "space-y-6" do |form| %>
|
||||
<% if @family.errors.any? %>
|
||||
<div class="bg-red-50 dark:bg-red-900/50 border border-red-200 dark:border-red-700 rounded-md p-4">
|
||||
<div class="flex">
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-red-800 dark:text-red-200">
|
||||
<div class="alert alert-error">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium">
|
||||
<%= t('families.new.error_title', default: 'There were problems with your submission:') %>
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-red-700 dark:text-red-300">
|
||||
<div class="mt-2 text-sm">
|
||||
<ul class="list-disc pl-5 space-y-1">
|
||||
<% @family.errors.full_messages.each do |message| %>
|
||||
<li><%= message %></li>
|
||||
|
|
@ -27,36 +26,37 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div>
|
||||
<%= form.label :name, t('families.form.name', default: 'Family Name'), class: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2" %>
|
||||
<%= form.label :name, t('families.form.name', default: 'Family Name'), class: "label label-text font-medium mb-2" %>
|
||||
<%= form.text_field :name,
|
||||
class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
|
||||
class: "input input-bordered w-full",
|
||||
placeholder: t('families.form.name_placeholder', default: 'Enter your family name') %>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
<p class="mt-1 text-sm text-base-content opacity-50">
|
||||
<%= t('families.new.name_help', default: 'Choose a name that all family members will recognize, like "The Smith Family" or "Our Travel Group".') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-blue-50 dark:bg-blue-900/30 p-4 rounded-md">
|
||||
<h3 class="text-sm font-medium text-blue-900 dark:text-blue-200 mb-2">
|
||||
<div class="alert alert-info">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium mb-2">
|
||||
<%= t('families.new.what_happens_title', default: 'What happens next?') %>
|
||||
</h3>
|
||||
<ul class="text-sm text-blue-800 dark:text-blue-300 space-y-1">
|
||||
<ul class="text-sm space-y-1">
|
||||
<li>• <%= t('families.new.what_happens_1', default: 'You will become the family owner') %></li>
|
||||
<li>• <%= t('families.new.what_happens_2', default: 'You can invite others to join your family') %></li>
|
||||
<li>• <%= t('families.new.what_happens_3', default: 'Family members can view shared location data') %></li>
|
||||
<li>• <%= t('families.new.what_happens_4', default: 'You can manage family settings and members') %></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<%= form.submit t('families.new.create_family', default: 'Create Family'),
|
||||
class: "bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 text-white px-6 py-2 rounded-md font-medium transition-colors duration-200" %>
|
||||
class: "btn btn-primary" %>
|
||||
<%= link_to families_path,
|
||||
class: "text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200 font-medium" do %>
|
||||
class: "btn btn-ghost" do %>
|
||||
<%= t('families.new.back', default: '← Back') %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<div class="container mx-auto px-4 py-8">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<!-- Family Header -->
|
||||
<div class="bg-white dark:bg-gray-800 shadow dark:shadow-gray-700 rounded-lg p-6 mb-6">
|
||||
<div class="bg-base-200 rounded-lg p-6 mb-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100"><%= @family.name %></h1>
|
||||
<p class="text-gray-600 dark:text-gray-400 mt-1">
|
||||
<h1 class="text-2xl font-bold text-base-content"><%= @family.name %></h1>
|
||||
<p class="text-base-content opacity-60 mt-1">
|
||||
<%= t('families.show.created_by', default: 'Created by') %>
|
||||
<%= @family.creator.email %>
|
||||
<%= t('families.show.on_date', default: 'on') %>
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
<div class="flex space-x-3">
|
||||
<% if policy(@family).update? %>
|
||||
<%= link_to edit_family_path(@family),
|
||||
class: "bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 text-white px-4 py-2 rounded-md font-medium transition-colors duration-200" do %>
|
||||
class: "btn btn-outline btn-info" do %>
|
||||
<%= icon 'square-pen', class: "inline-block w-4 h-4 mr-2 -mt-1" %>
|
||||
<%= t('families.show.edit', default: 'Edit') %>
|
||||
<% end %>
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
<%= link_to leave_family_path(@family),
|
||||
method: :delete,
|
||||
data: { confirm: 'Are you sure you want to leave this family?', turbo_confirm: 'Are you sure you want to leave this family?' },
|
||||
class: "bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white px-4 py-2 rounded-md font-medium transition-colors duration-200" do %>
|
||||
class: "btn btn-outline btn-warning" do %>
|
||||
Leave Family
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
<%= link_to family_path(@family),
|
||||
method: :delete,
|
||||
data: { confirm: 'Are you sure you want to delete this family? This action cannot be undone.', turbo_confirm: 'Are you sure you want to delete this family? This action cannot be undone.' },
|
||||
class: "bg-red-600 hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 text-white px-4 py-2 rounded-md font-medium transition-colors duration-200" do %>
|
||||
class: "btn btn-outline btn-error" do %>
|
||||
<%= icon 'trash-2', class: "inline-block w-4 h-4 mr-2 -mt-1" %>
|
||||
Delete
|
||||
<% end %>
|
||||
|
|
@ -45,11 +45,11 @@
|
|||
</div>
|
||||
|
||||
<!-- Family Members -->
|
||||
<div class="bg-white dark:bg-gray-800 shadow dark:shadow-gray-700 rounded-lg p-6 mb-6">
|
||||
<div class="bg-base-200 rounded-lg p-6 mb-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-gray-100">
|
||||
<h2 class="text-xl font-semibold text-base-content">
|
||||
<%= t('families.show.members_title', default: 'Family Members') %>
|
||||
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">(<%= @members.count %>)</span>
|
||||
<span class="text-sm font-normal opacity-50">(<%= @members.count %>)</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
|
|
@ -164,25 +164,25 @@
|
|||
</div>
|
||||
|
||||
<!-- Pending Invitations -->
|
||||
<div class="bg-white dark:bg-gray-800 shadow dark:shadow-gray-700 rounded-lg p-6">
|
||||
<div class="bg-base-200 rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-gray-100">
|
||||
<h2 class="text-xl font-semibold text-base-content">
|
||||
<%= t('families.show.invitations_title', default: 'Pending Invitations') %>
|
||||
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">(<%= @pending_invitations.count %>)</span>
|
||||
<span class="text-sm font-normal opacity-50">(<%= @pending_invitations.count %>)</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<% if @pending_invitations.any? %>
|
||||
<div class="space-y-3 mb-4">
|
||||
<% @pending_invitations.each do |invitation| %>
|
||||
<div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded-lg">
|
||||
<div class="flex items-center justify-between p-3 bg-base-100 rounded-lg">
|
||||
<div>
|
||||
<div class="font-medium text-gray-900 dark:text-gray-100"><%= invitation.email %></div>
|
||||
<div class="text-sm text-gray-500 dark:text-gray-400">
|
||||
<div class="font-medium text-base-content"><%= invitation.email %></div>
|
||||
<div class="text-sm text-base-content opacity-60">
|
||||
<%= t('families.show.invited_on', default: 'Invited') %>
|
||||
<%= invitation.created_at.strftime('%b %d, %Y') %>
|
||||
</div>
|
||||
<div class="text-xs text-gray-400 dark:text-gray-500">
|
||||
<div class="text-xs text-base-content opacity-50">
|
||||
<%= t('families.show.expires_on', default: 'Expires') %>
|
||||
<%= invitation.expires_at.strftime('%b %d, %Y at %I:%M %p') %>
|
||||
</div>
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
<%= link_to family_invitation_path(@family, invitation),
|
||||
method: :delete,
|
||||
data: { confirm: 'Are you sure you want to cancel this invitation?', turbo_confirm: 'Are you sure you want to cancel this invitation?' },
|
||||
class: "text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300 text-sm font-medium" do %>
|
||||
class: "text-error hover:brightness-90 text-sm font-medium" do %>
|
||||
Cancel
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
@ -199,7 +199,7 @@
|
|||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-center py-4">
|
||||
<p class="text-base-content opacity-50 text-center py-4">
|
||||
<%= t('families.show.no_pending_invitations', default: 'No pending invitations') %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
|
@ -207,39 +207,36 @@
|
|||
<!-- Invite New Member -->
|
||||
<% if policy(@family).invite? && @family.can_add_members? %>
|
||||
<div class="border-t pt-4">
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-3">
|
||||
<h3 class="text-lg font-medium text-base-content mb-3">
|
||||
<%= t('families.show.invite_member', default: 'Invite New Member') %>
|
||||
</h3>
|
||||
|
||||
<%= form_with model: [@family, FamilyInvitation.new], url: family_invitations_path(@family), local: true, class: "space-y-3" do |form| %>
|
||||
<div>
|
||||
<%= form.label :email, t('families.show.email_label', default: 'Email Address'), class: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1" %>
|
||||
<%= form.label :email, t('families.show.email_label', default: 'Email Address'), class: "label label-text font-medium mb-1" %>
|
||||
<%= form.email_field :email,
|
||||
placeholder: t('families.show.email_placeholder', default: 'Enter email address'),
|
||||
class: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" %>
|
||||
class: "input input-bordered w-full" %>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<%= form.submit t('families.show.send_invitation', default: 'Send Invitation'),
|
||||
class: "bg-green-600 hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-600 text-white px-4 py-2 rounded-md font-medium transition-colors duration-200" %>
|
||||
class: "btn btn-primary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% elsif policy(@family).invite? %>
|
||||
<!-- Family at capacity message -->
|
||||
<div class="border-t pt-4">
|
||||
<div class="bg-amber-50 dark:bg-amber-900/30 border border-amber-200 dark:border-amber-700 rounded-md p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<svg class="h-5 w-5 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<div class="alert alert-warning">
|
||||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-amber-800 dark:text-amber-200">
|
||||
<div>
|
||||
<h3 class="text-sm font-medium">
|
||||
Family at Capacity
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-amber-700 dark:text-amber-300">
|
||||
<div class="mt-2 text-sm">
|
||||
<p>
|
||||
Your family has reached the maximum of <%= @family.class::MAX_MEMBERS %> members (including pending invitations).
|
||||
Cancel existing invitations or wait for them to expire to invite new members.
|
||||
|
|
@ -248,7 +245,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<div class="container mx-auto px-4 py-8">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<div class="bg-white shadow rounded-lg p-6">
|
||||
<div class="bg-base-200 rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">
|
||||
<h1 class="text-2xl font-bold text-base-content">
|
||||
<%= t('family_invitations.index.title', default: 'Family Invitations') %>
|
||||
</h1>
|
||||
<%= link_to family_path(@family),
|
||||
class: "bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-md font-medium transition-colors duration-200" do %>
|
||||
class: "btn btn-neutral" do %>
|
||||
<%= t('family_invitations.index.back_to_family', default: 'Back to Family') %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
@ -14,14 +14,14 @@
|
|||
<% if @pending_invitations.any? %>
|
||||
<div class="space-y-4">
|
||||
<% @pending_invitations.each do |invitation| %>
|
||||
<div class="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
|
||||
<div class="flex items-center justify-between p-4 bg-base-100 rounded-lg">
|
||||
<div>
|
||||
<div class="font-medium text-gray-900"><%= invitation.email %></div>
|
||||
<div class="text-sm text-gray-500">
|
||||
<div class="font-medium text-base-content"><%= invitation.email %></div>
|
||||
<div class="text-sm text-base-content opacity-60">
|
||||
<%= t('family_invitations.index.invited_on', default: 'Invited') %>
|
||||
<%= invitation.created_at.strftime('%B %d, %Y') %>
|
||||
</div>
|
||||
<div class="text-xs text-gray-400">
|
||||
<div class="text-xs text-base-content opacity-50">
|
||||
<%= t('family_invitations.index.expires_on', default: 'Expires') %>
|
||||
<%= invitation.expires_at.strftime('%B %d, %Y at %I:%M %p') %>
|
||||
</div>
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<div class="flex space-x-2">
|
||||
<%= link_to public_invitation_path(invitation.token),
|
||||
class: "text-blue-600 hover:text-blue-800 text-sm font-medium" do %>
|
||||
class: "btn btn-ghost btn-sm text-info" do %>
|
||||
<%= t('family_invitations.index.view_invitation', default: 'View') %>
|
||||
<% end %>
|
||||
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
<%= link_to family_invitation_path(@family, invitation),
|
||||
method: :delete,
|
||||
confirm: t('family_invitations.index.cancel_confirm', default: 'Are you sure you want to cancel this invitation?'),
|
||||
class: "text-red-600 hover:text-red-800 text-sm font-medium" do %>
|
||||
class: "btn btn-ghost btn-sm text-error" do %>
|
||||
<%= t('family_invitations.index.cancel', default: 'Cancel') %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
</div>
|
||||
<% else %>
|
||||
<div class="text-center py-8">
|
||||
<p class="text-gray-500 text-lg">
|
||||
<p class="text-base-content opacity-50 text-lg">
|
||||
<%= t('family_invitations.index.no_invitations', default: 'No pending invitations') %>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,93 +1,93 @@
|
|||
<div class="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50 dark:from-gray-900 dark:via-gray-800 dark:to-gray-900 py-12 px-4 mx-auto">
|
||||
<div class="min-h-screen bg-gradient-to-br from-base-100 to-base-200 py-12 px-4 mx-auto">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<!-- Hero Section -->
|
||||
<div class="text-center mb-12">
|
||||
<div class="mx-auto flex items-center justify-center h-24 w-24 rounded-full bg-blue-500 mb-6 shadow-xl">
|
||||
<%= icon 'users', class: "h-12 w-12 text-white" %>
|
||||
<div class="mx-auto flex items-center justify-center h-24 w-24 rounded-full bg-primary mb-6 shadow-xl">
|
||||
<%= icon 'users', class: "h-12 w-12 text-primary-content" %>
|
||||
</div>
|
||||
|
||||
<h1 class="text-5xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
<h1 class="text-5xl font-bold text-base-content mb-4">
|
||||
Join <%= @invitation.family.name %>!
|
||||
</h1>
|
||||
|
||||
<p class="text-xl text-gray-700 dark:text-gray-200 mb-2">
|
||||
You've been invited by <strong class="text-gray-900 dark:text-white"><%= @invitation.invited_by.email %></strong> to join their family. Create your account to accept the invitation and start sharing location data.
|
||||
<p class="text-xl text-base-content opacity-80 mb-2">
|
||||
You've been invited by <strong class="text-base-content"><%= @invitation.invited_by.email %></strong> to join their family. Create your account to accept the invitation and start sharing location data.
|
||||
</p>
|
||||
|
||||
<div class="inline-flex items-center bg-blue-100 dark:bg-blue-900/40 border border-blue-300 dark:border-blue-600 rounded-full px-4 py-2 mt-4">
|
||||
<%= icon 'info', class: "h-5 w-5 text-blue-600 dark:text-blue-400 mr-2" %>
|
||||
<span class="text-sm font-medium text-blue-900 dark:text-blue-100">
|
||||
<div class="alert alert-info inline-flex rounded-full px-4 py-2 mt-4">
|
||||
<%= icon 'info', class: "h-5 w-5 mr-2" %>
|
||||
<span class="text-sm font-medium">
|
||||
Your email (<%= @invitation.email %>) will be used for this account
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Benefits Section -->
|
||||
<div class="bg-white dark:bg-gray-800 shadow-xl rounded-2xl p-8 mb-8">
|
||||
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-6 text-center">
|
||||
<div class="bg-base-200 shadow-xl rounded-2xl p-8 mb-8">
|
||||
<h2 class="text-2xl font-bold text-base-content mb-6 text-center">
|
||||
What benefits does joining a family bring?
|
||||
</h2>
|
||||
|
||||
<div class="grid md:grid-cols-2 gap-6 mb-8">
|
||||
<div class="flex items-start space-x-4 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-100 dark:border-blue-700">
|
||||
<div class="flex items-start space-x-4 p-4 bg-info/10 rounded-lg border border-info/20">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="h-10 w-10 rounded-full bg-blue-600 dark:bg-blue-500 flex items-center justify-center">
|
||||
<%= icon 'map-pin', class: "h-6 w-6 text-white" %>
|
||||
<div class="h-10 w-10 rounded-full bg-info flex items-center justify-center">
|
||||
<%= icon 'map-pin', class: "h-6 w-6 text-info-content" %>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-white mb-1">
|
||||
<h3 class="font-semibold text-base-content mb-1">
|
||||
Share Location Data
|
||||
</h3>
|
||||
<p class="text-sm text-gray-700 dark:text-gray-200">
|
||||
<p class="text-sm text-base-content opacity-70">
|
||||
Share your location history with family members and see where they are
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start space-x-4 p-4 bg-purple-50 dark:bg-purple-900/20 rounded-lg border border-purple-100 dark:border-purple-700">
|
||||
<div class="flex items-start space-x-4 p-4 bg-secondary/10 rounded-lg border border-secondary/20">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="h-10 w-10 rounded-full bg-purple-600 dark:bg-purple-500 flex items-center justify-center">
|
||||
<%= icon 'chart-column', class: "h-6 w-6 text-white" %>
|
||||
<div class="h-10 w-10 rounded-full bg-secondary flex items-center justify-center">
|
||||
<%= icon 'chart-column', class: "h-6 w-6 text-secondary-content" %>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-white mb-1">
|
||||
<h3 class="font-semibold text-base-content mb-1">
|
||||
Track your location history
|
||||
</h3>
|
||||
<p class="text-sm text-gray-700 dark:text-gray-200">
|
||||
<p class="text-sm text-base-content opacity-70">
|
||||
Access interactive maps and personal travel statistics
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start space-x-4 p-4 bg-green-50 dark:bg-green-900/20 rounded-lg border border-green-100 dark:border-green-700">
|
||||
<div class="flex items-start space-x-4 p-4 bg-success/10 rounded-lg border border-success/20">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="h-10 w-10 rounded-full bg-green-600 dark:bg-green-500 flex items-center justify-center">
|
||||
<%= icon 'heart', class: "h-6 w-6 text-white" %>
|
||||
<div class="h-10 w-10 rounded-full bg-success flex items-center justify-center">
|
||||
<%= icon 'heart', class: "h-6 w-6 text-success-content" %>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-white mb-1">
|
||||
<h3 class="font-semibold text-base-content mb-1">
|
||||
Stay Connected
|
||||
</h3>
|
||||
<p class="text-sm text-gray-700 dark:text-gray-200">
|
||||
<p class="text-sm text-base-content opacity-70">
|
||||
Keep track of your loved ones' travels and adventures in real-time
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start space-x-4 p-4 bg-yellow-50 dark:bg-yellow-900/20 rounded-lg border border-yellow-100 dark:border-yellow-700">
|
||||
<div class="flex items-start space-x-4 p-4 bg-warning/10 rounded-lg border border-warning/20">
|
||||
<div class="flex-shrink-0">
|
||||
<div class="h-10 w-10 rounded-full bg-yellow-600 dark:bg-yellow-500 flex items-center justify-center">
|
||||
<%= icon 'shield-check', class: "h-6 w-6 text-white" %>
|
||||
<div class="h-10 w-10 rounded-full bg-warning flex items-center justify-center">
|
||||
<%= icon 'shield-check', class: "h-6 w-6 text-warning-content" %>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-semibold text-gray-900 dark:text-white mb-1">
|
||||
<h3 class="font-semibold text-base-content mb-1">
|
||||
Full Control & Privacy
|
||||
</h3>
|
||||
<p class="text-sm text-gray-700 dark:text-gray-200">
|
||||
<p class="text-sm text-base-content opacity-70">
|
||||
You control what and how long you share and can leave the family anytime
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -95,24 +95,24 @@
|
|||
</div>
|
||||
|
||||
<!-- Invitation Details -->
|
||||
<div class="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-6 mb-6 border border-gray-200 dark:border-gray-600">
|
||||
<h3 class="text-sm font-medium text-gray-600 dark:text-gray-300 mb-3">Invitation Details</h3>
|
||||
<div class="bg-base-300 rounded-lg p-6 mb-6">
|
||||
<h3 class="text-sm font-medium text-base-content opacity-70 mb-3">Invitation Details</h3>
|
||||
<div class="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<span class="text-gray-600 dark:text-gray-300">Family:</span>
|
||||
<span class="ml-2 font-semibold text-gray-900 dark:text-white"><%= @invitation.family.name %></span>
|
||||
<span class="text-base-content opacity-60">Family:</span>
|
||||
<span class="ml-2 font-semibold text-base-content"><%= @invitation.family.name %></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-gray-600 dark:text-gray-300">Invited by:</span>
|
||||
<span class="ml-2 font-semibold text-gray-900 dark:text-white"><%= @invitation.invited_by.email %></span>
|
||||
<span class="text-base-content opacity-60">Invited by:</span>
|
||||
<span class="ml-2 font-semibold text-base-content"><%= @invitation.invited_by.email %></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-gray-600 dark:text-gray-300">Your email:</span>
|
||||
<span class="ml-2 font-semibold text-gray-900 dark:text-white"><%= @invitation.email %></span>
|
||||
<span class="text-base-content opacity-60">Your email:</span>
|
||||
<span class="ml-2 font-semibold text-base-content"><%= @invitation.email %></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-gray-600 dark:text-gray-300">Expires:</span>
|
||||
<span class="ml-2 font-semibold text-gray-900 dark:text-white"><%= @invitation.expires_at.strftime('%b %d, %Y') %></span>
|
||||
<span class="text-base-content opacity-60">Expires:</span>
|
||||
<span class="ml-2 font-semibold text-base-content"><%= @invitation.expires_at.strftime('%b %d, %Y') %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -123,38 +123,38 @@
|
|||
<!-- User is logged in, show accept button -->
|
||||
<%= link_to accept_family_invitation_path(@invitation.family, @invitation),
|
||||
method: :post,
|
||||
class: "block w-full bg-green-600 hover:bg-green-700 text-white px-8 py-4 rounded-lg font-semibold text-lg transition-all duration-200 shadow-lg hover:shadow-xl text-center" do %>
|
||||
class: "btn btn-success btn-lg w-full text-lg shadow-lg" do %>
|
||||
✓ Accept Invitation & Join Family
|
||||
<% end %>
|
||||
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 text-center">
|
||||
<p class="text-sm text-base-content opacity-60 text-center">
|
||||
Logged in as <%= current_user.email %>
|
||||
·
|
||||
<%= link_to destroy_user_session_path, method: :delete, class: "text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300" do %>
|
||||
<%= link_to destroy_user_session_path, method: :delete, class: "link link-info" do %>
|
||||
Logout
|
||||
<% end %>
|
||||
</p>
|
||||
<% else %>
|
||||
<!-- User is not logged in, show register button prominently -->
|
||||
<%= link_to new_user_registration_path(invitation_token: @invitation.token),
|
||||
class: "block w-full bg-blue-600 hover:bg-blue-700 text-white px-8 py-4 rounded-lg font-semibold text-lg transition-all duration-200 shadow-lg hover:shadow-xl text-center" do %>
|
||||
class: "btn btn-primary btn-lg w-full text-lg shadow-lg" do %>
|
||||
Create Account & Join Family →
|
||||
<% end %>
|
||||
|
||||
<div class="text-center">
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 mb-2">
|
||||
<p class="text-sm text-base-content opacity-60 mb-2">
|
||||
Already have an account?
|
||||
</p>
|
||||
<%= link_to new_user_session_path(invitation_token: @invitation.token),
|
||||
class: "inline-block text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 font-medium" do %>
|
||||
class: "link link-info font-medium" do %>
|
||||
Sign in to accept invitation
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Decline Option -->
|
||||
<div class="pt-6 border-t border-gray-200 dark:border-gray-600 text-center">
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300">
|
||||
<div class="pt-6 border-t border-base-300 text-center">
|
||||
<p class="text-sm text-base-content opacity-60">
|
||||
Not interested? You can simply close this page.
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue