diff --git a/app/assets/images/dark-mode-preview.png b/app/assets/images/dark-mode-preview.png
new file mode 100644
index 00000000..f6b1a016
Binary files /dev/null and b/app/assets/images/dark-mode-preview.png differ
diff --git a/app/assets/images/light-mode-preview.png b/app/assets/images/light-mode-preview.png
new file mode 100644
index 00000000..7403f8f1
Binary files /dev/null and b/app/assets/images/light-mode-preview.png differ
diff --git a/app/assets/images/system-mode-preview.png b/app/assets/images/system-mode-preview.png
new file mode 100644
index 00000000..bc3d6fdf
Binary files /dev/null and b/app/assets/images/system-mode-preview.png differ
diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css
index b70d3244..54deb8e7 100644
--- a/app/assets/stylesheets/application.tailwind.css
+++ b/app/assets/stylesheets/application.tailwind.css
@@ -33,18 +33,19 @@
}
.form-field {
- @apply relative border bg-white rounded-xl shadow-sm;
+ @apply relative border border-alpha-black-100 bg-white rounded-md shadow-xs;
@apply focus-within:shadow-none focus-within:border-gray-900 focus-within:ring-4 focus-within:ring-gray-100;
}
.form-field__label {
- @apply p-3 pb-0 block text-sm font-medium opacity-50;
+ @apply px-3 pt-2 pb-0 block text-xs text-gray-500;
}
.form-field__input {
- @apply p-3 w-full bg-transparent border-none opacity-100;
+ @apply px-3 pb-2 pt-1 text-sm w-full bg-transparent border-none opacity-100;
@apply focus:outline-none focus:ring-0 focus:opacity-100;
@apply placeholder-shown:opacity-50;
+ @apply disabled:opacity-50;
}
.form-field__submit {
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index aecbce53..87138e67 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -3,5 +3,23 @@ class Settings::PreferencesController < ApplicationController
end
def update
+ preference_params_with_family = preference_params
+
+ if Current.family && preference_params[:family_attributes]
+ family_attributes = preference_params[:family_attributes].merge({ id: Current.family.id })
+ preference_params_with_family[:family_attributes] = family_attributes
+ end
+
+ if Current.user.update(preference_params_with_family)
+ redirect_to settings_preferences_path, notice: t(".success")
+ else
+ redirect_to settings_preferences_path, notice: t(".success")
+ render :edit, status: :unprocessable_entity
+ end
end
+
+ private
+ def preference_params
+ params.require(:user).permit(family_attributes: [ :id, :currency ])
+ end
end
diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb
index d510bf05..066aa912 100644
--- a/app/controllers/settings/profiles_controller.rb
+++ b/app/controllers/settings/profiles_controller.rb
@@ -5,13 +5,13 @@ class Settings::ProfilesController < ApplicationController
def update
user_params_with_family = user_params
- if Current.family
+ if Current.family && user_params_with_family[:family_attributes]
family_attributes = user_params_with_family[:family_attributes].merge({ id: Current.family.id })
user_params_with_family[:family_attributes] = family_attributes
end
if Current.user.update(user_params_with_family)
- redirect_to root_path, notice: "Profile updated successfully."
+ redirect_to settings_profile_path, notice: t(".success")
else
render :edit, status: :unprocessable_entity
end
@@ -20,7 +20,7 @@ class Settings::ProfilesController < ApplicationController
private
def user_params
- params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation,
- family_attributes: [ :name, :id, :currency ])
+ params.require(:user).permit(:first_name, :last_name,
+ family_attributes: [ :name, :id ])
end
end
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index f62f9af1..eca2075c 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -6,4 +6,9 @@ module SettingsHelper
def previous_setting(title, path)
render partial: "settings/nav_link_large", locals: { path: path, direction: "previous", title: title }
end
+
+ def settings_section(title:, subtitle: nil, &block)
+ content = capture(&block)
+ render partial: "settings/section", locals: { title: title, subtitle: subtitle, content: content }
+ end
end
diff --git a/app/javascript/controllers/auto_submit_form_controller.js b/app/javascript/controllers/auto_submit_form_controller.js
index c1dc5f0d..4d470f91 100644
--- a/app/javascript/controllers/auto_submit_form_controller.js
+++ b/app/javascript/controllers/auto_submit_form_controller.js
@@ -2,18 +2,21 @@ import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
// By default, auto-submit is "opt-in" to avoid unexpected behavior. Each `auto` target
- // will trigger a form submission when the input event is triggered.
+ // will trigger a form submission when the configured event is triggered.
static targets = ["auto"];
+ static values = {
+ triggerEvent: { type: String, default: "input" },
+ };
connect() {
this.autoTargets.forEach((element) => {
- element.addEventListener("input", this.handleInput);
+ element.addEventListener(this.triggerEventValue, this.handleInput);
});
}
disconnect() {
this.autoTargets.forEach((element) => {
- element.removeEventListener("input", this.handleInput);
+ element.removeEventListener(this.triggerEventValue, this.handleInput);
});
}
diff --git a/app/models/user.rb b/app/models/user.rb
index a0bd8ada..8cbd8fb1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -7,6 +7,8 @@ class User < ApplicationRecord
validates :email, presence: true, uniqueness: true
normalizes :email, with: ->(email) { email.strip.downcase }
+ enum :role, { member: "member", admin: "admin" }, validate: true
+
generates_token_for :password_reset, expires_in: 15.minutes do
password_salt&.last(10)
end
diff --git a/app/views/settings/_section.html.erb b/app/views/settings/_section.html.erb
new file mode 100644
index 00000000..cd0e3a3f
--- /dev/null
+++ b/app/views/settings/_section.html.erb
@@ -0,0 +1,12 @@
+<%# locals: (title:, subtitle: nil, content:) %>
+ <%= subtitle %><%= title %>
+ <% if subtitle.present? %>
+
Preferences coming soon...
+<%= t(".profile_image_type") %>
+ +<%= Current.family.name %> · <%= Current.family.users.size %>
+<%= Current.user.first_name.first %>
+<%= Current.user.first_name %> <%= Current.user.last_name %>
+<%= Current.user.role %>
+<%= t(".delete_account_warning") %>
+