Files
sure/app/views/transactions/_attachments.html.erb
soky srm 560c9fbff3 Family sharing (#1272)
* Initial account sharing changes

* Update schema.rb

* Update schema.rb

* Change sharing UI to modal

* UX fixes and sharing controls

* Scope include in finances better

* Update totals.rb

* Update totals.rb

* Scope reports to finance account scope

* Update impersonation_sessions_controller_test.rb

* Review fixes

* Update schema.rb

* Update show.html.erb

* FIX db validation

* Refine edit permissions

* Review items

* Review

* Review

* Add application level helper

* Critical review

* Address remaining review items

* Fix modals

* more scoping

* linter

* small UI fix

* Fix: Sync broadcasts push unscoped balance sheet to all users

* Update sync_complete_event.rb

 The fix removes the sidebar broadcasts (which rendered unscoped account groups using family.balance_sheet without user context)
  along with the now-unused sidebar_targets, account_group, and family_balance_sheet private methods.

  The sidebar will still update correctly — when the sync completes, Family::SyncCompleteEvent#broadcast fires family.broadcast_refresh, which triggers a
  morph-based page refresh for each user with their own authenticated session, rendering properly scoped sidebar content.
2026-03-25 10:50:23 +01:00

127 lines
5.4 KiB
Plaintext

<%# locals: (transaction:, can_upload: false, can_delete: false) %>
<div id="transaction_attachments_<%= transaction.id %>" class="pb-4">
<!-- Upload Form -->
<% if can_upload && transaction.attachments.count < Transaction::MAX_ATTACHMENTS_PER_TRANSACTION %>
<%= styled_form_with url: transaction_attachments_path(transaction),
method: :post,
multipart: true,
local: true,
class: "mb-4",
data: {
controller: "attachment-upload",
attachment_upload_max_files_value: Transaction::MAX_ATTACHMENTS_PER_TRANSACTION - transaction.attachments.count,
attachment_upload_max_size_value: Transaction::MAX_ATTACHMENT_SIZE
} do |form| %>
<div class="space-y-3">
<div>
<div class="flex flex-col items-center justify-center w-full py-8 border border-secondary border-dashed rounded-xl cursor-pointer bg-surface-inset hover:bg-surface-inset-hover transition-colors text-center px-4"
data-action="click->attachment-upload#triggerFileInput">
<div data-attachment-upload-target="uploadText" class="flex flex-col items-center">
<%= icon "plus", size: "lg", class: "mb-2 text-secondary" %>
<p class="text-sm font-medium text-primary"><%= t(".browse_to_add") %></p>
</div>
<div data-attachment-upload-target="fileName" class="flex flex-col items-center hidden w-full px-2">
<%= icon "file-text", size: "lg", class: "mb-2 text-secondary" %>
<p class="text-sm font-medium text-primary truncate w-full"></p>
</div>
<%= form.file_field :attachments,
multiple: true,
accept: Transaction::ALLOWED_CONTENT_TYPES.join(","),
class: "hidden",
data: {
attachment_upload_target: "fileInput",
action: "change->attachment-upload#updateSubmitButton"
} %>
</div>
<p class="text-[10px] text-secondary mt-1 text-center">
<%= t(".select_up_to",
count: Transaction::MAX_ATTACHMENTS_PER_TRANSACTION,
size: Transaction::MAX_ATTACHMENT_SIZE / 1.megabyte,
used: transaction.attachments.count) %>
</p>
</div>
<div class="flex justify-end">
<%= render DS::Button.new(
text: t(".upload"),
variant: :primary,
size: :sm,
data: { attachment_upload_target: "submitButton" }
) %>
</div>
</div>
<% end %>
<% elsif can_upload %>
<div class="p-3 mb-4 rounded-lg border border-warning bg-warning/5 flex items-start gap-3">
<%= icon "alert-circle", size: "sm", color: "warning", class: "mt-0.5" %>
<div class="text-xs text-warning leading-relaxed font-medium">
<%= t(".max_reached", count: transaction.attachments.count, max: Transaction::MAX_ATTACHMENTS_PER_TRANSACTION) %>
</div>
</div>
<% end %>
<!-- Attachments List -->
<% if transaction.attachments.any? %>
<div class="space-y-2">
<h4 class="text-sm font-medium text-primary"><%= t(".files", count: transaction.attachments.count) %></h4>
<div class="space-y-2">
<% transaction.attachments.each do |attachment| %>
<div class="flex items-center justify-between p-3 border border-primary rounded-lg bg-container">
<div class="flex items-center gap-3">
<div class="flex-shrink-0">
<% if attachment.image? %>
<%= icon "image", size: "sm", color: "secondary" %>
<% else %>
<%= icon "file", size: "sm", color: "secondary" %>
<% end %>
</div>
<div class="min-w-0 flex-1">
<p class="text-sm font-medium text-primary truncate"><%= attachment.filename %></p>
<p class="text-xs text-secondary"><%= number_to_human_size(attachment.byte_size) %></p>
</div>
</div>
<div class="flex items-center gap-2">
<%= render DS::Link.new(
href: transaction_attachment_path(transaction, attachment, disposition: :inline),
variant: :outline,
size: :sm,
icon: "eye",
text: "",
target: "_blank"
) %>
<%= render DS::Link.new(
href: transaction_attachment_path(transaction, attachment, disposition: :attachment),
variant: :outline,
size: :sm,
icon: "download",
text: "",
data: { turbo: false }
) %>
<% if can_delete %>
<%= render DS::Button.new(
href: transaction_attachment_path(transaction, attachment),
method: :delete,
variant: :outline_destructive,
size: :sm,
icon: "trash-2",
confirm: CustomConfirm.for_resource_deletion("attachment")
) %>
<% end %>
</div>
</div>
<% end %>
</div>
</div>
<% else %>
<p class="text-sm text-secondary"><%= t(".no_attachments") %></p>
<% end %>
</div>