Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5fbc859
Add receipt bin select to ach transfer input
polypixeldev Sep 9, 2025
dd42fd2
Move controller
polypixeldev Sep 9, 2025
fadb5ae
Merge branch 'main' into polypixeldev/link-receipt-input
polypixeldev Sep 9, 2025
84e6703
Improve frontend for new receipt input
polypixeldev Sep 11, 2025
6cdc257
Add padding
polypixeldev Sep 11, 2025
4c6cc3b
Add extraction from receipt bin
polypixeldev Sep 12, 2025
acf9e13
Fix extraction bug
polypixeldev Sep 12, 2025
bd26d4b
Rename inline-receipt to receipt-input
polypixeldev Sep 12, 2025
3428204
Disable add button when no receipts
polypixeldev Sep 12, 2025
50d8cde
Add newlines
polypixeldev Sep 12, 2025
29608b7
Add required option
polypixeldev Sep 12, 2025
f8cdeb2
Add extraction option
polypixeldev Sep 12, 2025
f24cb7a
Add receipt input to disbursements
polypixeldev Sep 12, 2025
285d4e2
Add new receipt input to checks
polypixeldev Sep 12, 2025
f4b53df
Add new receipt input to paypal transfers
polypixeldev Sep 12, 2025
a692490
Add new receipt input to wires
polypixeldev Sep 12, 2025
fb6b14a
Add new receipt input to wise transfers
polypixeldev Sep 12, 2025
badadf0
Don't add extraction action if not enabled
polypixeldev Sep 12, 2025
558a347
Merge branch 'main' into polypixeldev/link-receipt-input
polypixeldev Sep 12, 2025
b0020db
Fix disabling of add button
polypixeldev Sep 12, 2025
666f1c0
Fix ERB formatting
polypixeldev Sep 12, 2025
51b70ca
Send receipts link list as array instead of string
polypixeldev Sep 15, 2025
2a21f26
Use current_user.receipts
polypixeldev Sep 15, 2025
bc39304
Fix JS formatting
polypixeldev Sep 15, 2025
c85e442
Remove extra class
polypixeldev Sep 15, 2025
715c9e2
Add new receipt list with previews
polypixeldev Sep 15, 2025
8900545
Fix light mode
polypixeldev Sep 15, 2025
d5a8f8a
Fix CSS and JS formatting
polypixeldev Sep 15, 2025
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
75 changes: 52 additions & 23 deletions app/assets/stylesheets/components/_forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,35 +70,35 @@ input[type='number'] {
-moz-appearance: textfield;
}

.field--fileupload {
display: flex;
gap: 0.5rem;
align-items: center;
.field--fileupload__label {
white-space: nowrap;
display: block;
padding: 5px 0;

.field--fileupload__label {
white-space: nowrap;
display: block;
padding: 5px 0;
display: block;
padding: 0.25rem 1rem;
cursor: pointer;
border-radius: 6px;

display: block;
padding: 0.25rem 1rem;
cursor: pointer;
border-radius: 6px;
color: map-get($palette, info) !important;
border: 1px dashed map-get($palette, info);

color: map-get($palette, info);
border: 1px dashed map-get($palette, info);
transition: transform 0.125s ease-in-out;
font-size: 0.875rem;
font-weight: 600;

transition: transform 0.125s ease-in-out;
font-size: 0.875rem;
font-weight: 600;

letter-spacing: 0;
line-height: 1.5;
letter-spacing: 0;
line-height: 1.5;

&:hover {
transform: scale(1.0625);
}
&:hover {
transform: scale(1.0625);
}
}

.field--fileupload {
display: flex;
gap: 0.5rem;
align-items: center;

.field--fileupload__field {
&::file-selector-button {
Expand Down Expand Up @@ -545,3 +545,32 @@ input:where([data-behavior='otp_input']) {
transform: scale(1.0625);
}
}

.receipt-input__list {
list-style-type: none;
padding: 0.25rem 0rem;

div {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;

border-bottom-width: 1px;
border-bottom-color: $smoke;
border-bottom-style: solid;

html[data-dark='true'] & {
border-bottom-color: $slate;
}

img {
width: 2rem;
height: 3rem;
}
}

div:last-child {
border-bottom-width: 0px;
}
}
9 changes: 9 additions & 0 deletions app/controllers/ach_transfers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ def create
end

if @ach_transfer.save
if params[:receipts].present?
params[:receipts].each do |receipt_id|
receipt = Receipt.find(receipt_id)
authorize receipt, :link?

receipt.update!(receiptable: @ach_transfer.local_hcb_code)
end
end

if ach_transfer_params[:file]
::ReceiptService::Create.new(
uploader: current_user,
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/disbursements_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ def create
fronted: @source_event.plan.front_disbursements_enabled?
).run

if params[:receipts].present?
params[:receipts].each do |receipt_id|
receipt = Receipt.find(receipt_id)
authorize receipt, :link?

receipt.update!(receiptable: disbursement.local_hcb_code)
end
end

if disbursement_params[:file]
::ReceiptService::Create.new(
uploader: current_user,
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/increase_checks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ def create
end

if @check.save
if params[:receipts].present?
params[:receipts].each do |receipt_id|
receipt = Receipt.find(receipt_id)
authorize receipt, :link?

receipt.update!(receiptable: @check.local_hcb_code)
end
end

if check_params[:file]
::ReceiptService::Create.new(
uploader: current_user,
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/paypal_transfers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ def create
authorize @paypal_transfer

if @paypal_transfer.save
if params[:receipts].present?
params[:receipts].each do |receipt_id|
receipt = Receipt.find(receipt_id)
authorize receipt, :link?

receipt.update!(receiptable: @paypal_transfer.local_hcb_code)
end
end

if paypal_transfer_params[:file]
::ReceiptService::Create.new(
uploader: current_user,
Expand Down
14 changes: 13 additions & 1 deletion app/controllers/receipts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class ReceiptsController < ApplicationController
before_action :find_receiptable, only: [:create, :link, :link_modal]
before_action :set_event, only: [:create, :link]
before_action :set_transaction_display_data
before_action :set_receipt, only: [:destroy, :reverse]
before_action :set_receipt, only: [:destroy, :reverse, :metadata]

def destroy
@receiptable = @receipt.receiptable
Expand Down Expand Up @@ -92,6 +92,12 @@ def link_modal

end

def inline_link
skip_authorization

@receipts = current_user.receipts.in_receipt_bin.with_attached_file.order(created_at: :desc)
end

def create
streams = []

Expand Down Expand Up @@ -235,6 +241,12 @@ def reverse
end
end

def metadata
authorize @receipt

render json: { name: @receipt.file.blob.filename, preview: @receipt.preview, total: (@receipt.extracted_total_amount_cents.present? ? @receipt.extracted_total_amount_cents / 100.0 : nil), seller_name: @receipt.extracted_merchant_name, seller_address_zip: @receipt.extracted_merchant_zip_code }
end

private

RECEIPTABLE_TYPE_MAP = [HcbCode, CanonicalTransaction, Transaction, StripeAuthorization,
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/wires_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ def create
end

if @wire.save
if params[:receipts].present?
params[:receipts].each do |receipt_id|
receipt = Receipt.find(receipt_id)
authorize receipt, :link?

receipt.update!(receiptable: @wire.local_hcb_code)
end
end

if wire_params[:file]
::ReceiptService::Create.new(
uploader: current_user,
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/wise_transfers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ def create
end

if @wise_transfer.save
if params[:receipts].present?
params[:receipts].each do |receipt_id|
receipt = Receipt.find(receipt_id)
authorize receipt, :link?

receipt.update!(receiptable: @wise_transfer.local_hcb_code)
end
end

if wise_transfer_params[:file]
::ReceiptService::Create.new(
uploader: current_user,
Expand Down
57 changes: 35 additions & 22 deletions app/javascript/controllers/extraction_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,20 @@ export default class extends Controller {
Turbo.navigator.delegate.adapter.progressBar.hide()
document.querySelector('html').setAttribute('data-ai-loading', false)

this.pasteData(response)
}

pasteData(response) {
Comment on lines +29 to +32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by "pasting" do you mean filling the form?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

let empty = true

const extractedKeys = Object.keys(response).filter(
key => response[key] !== null
)

Array.from(this.formTarget.elements).map(element => {
if (
element.dataset.extractionField &&
Object.keys(response).includes(element.dataset.extractionField)
extractedKeys.includes(element.dataset.extractionField)
) {
if (element.value != '') {
empty = false
Expand All @@ -40,42 +48,47 @@ export default class extends Controller {
})

if (empty) {
let success = false

Array.from(this.formTarget.elements).map(element => {
if (
element.dataset.extractionField &&
Object.keys(response).includes(element.dataset.extractionField)
extractedKeys.includes(element.dataset.extractionField)
) {
element.value = response[element.dataset.extractionField]
element.dispatchEvent(new Event('paste'))
success = true
}
})

let dropzone = document.createElement('div')
dropzone.classList.add('file-dropzone')
dropzone.classList.add('data-extracted')
if (success) {
let dropzone = document.createElement('div')
dropzone.classList.add('file-dropzone')
dropzone.classList.add('data-extracted')

const title = document.createElement('h1')
title.innerText = '🧾 Successfully extracted!'
dropzone.appendChild(title)
const title = document.createElement('h1')
title.innerText = '🧾 Successfully extracted!'
dropzone.appendChild(title)

document.body.appendChild(dropzone)
document.body.style.overflow = 'hidden'
document.body.appendChild(dropzone)
document.body.style.overflow = 'hidden'

// Explanation: https://stackoverflow.com/a/24195487/10987085
window.getComputedStyle(dropzone).opacity
// Explanation: https://stackoverflow.com/a/24195487/10987085
window.getComputedStyle(dropzone).opacity

dropzone.classList.add('visible')
dropzone.classList.add('visible')

const jsConfetti = new JSConfetti()
const jsConfetti = new JSConfetti()

jsConfetti
.addConfetti({
emojis: '✨',
})
.then(() => {
dropzone.remove()
document.body.style.overflow = 'auto'
})
jsConfetti
.addConfetti({
emojis: '✨',
})
.then(() => {
dropzone.remove()
document.body.style.overflow = 'auto'
})
}
}
}
}
Loading