mirror of
https://github.com/we-promise/sure.git
synced 2026-05-07 21:04:12 +00:00
* feat: improve QIF import date format selection - Added a reusable date format auto-detection method. - Show a live preview of the first parsed date that updates client-side as the user changes the dropdown selection, via a new qif-date-format Stimulus controller. - Show an error alert and disable the submit button when no supported date format can parse the file's dates. * A few polishing fixes: - Missing return on redirects Stale REASONABLE_DATE_RANGE constant. - Replaced the frozen constant with a class method Bare inline rescue — Replaced Date.strptime(s, fmt) rescue nil with an explicit begin/rescue catching. - save!(validate: false) in controller — Changed to update_column(:column_mappings, ...) in qif_category_selections_controller.rb:22, matching the pattern used in detect_and_set_qif_date_format!. - Unescaped JSON in HTML attribute — Replaced the raw <div> with tag.div ... do block in show.html.erb:16, letting Rails properly escape the data attribute value. * fix: address review feedback for QIF date format feature - Add missing `return` after redirect for non-QIF imports - Pass date_format to parse_opening_balance in will_adjust_opening_anchor? - Return empty array when no usable date sample exists for format preview - Add sr-only label to date format select for accessibility - Consolidate duplicate try_parse_date/parse_qif_date into single method - Remove misleading ambiguity scoring comment from detect_date_format - Skip redundant sync_mappings when date format already triggered a sync Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Use %{product_name} interpolation in locale strings --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
80 lines
4.6 KiB
Plaintext
80 lines
4.6 KiB
Plaintext
<%# locals: (import:) %>
|
|
|
|
<% steps = if import.is_a?(SureImport)
|
|
[
|
|
{ name: t("imports.steps.upload", default: "Upload"), path: import_upload_path(import), is_complete: import.uploaded?, step_number: 1 },
|
|
{ name: t("imports.steps.confirm", default: "Confirm"), path: import_path(import), is_complete: import.complete?, step_number: 2 }
|
|
]
|
|
elsif import.is_a?(PdfImport)
|
|
# PDF imports have a simplified flow: Upload -> Confirm
|
|
# Upload/Configure/Clean are always complete for processed PDF imports
|
|
[
|
|
{ name: t("imports.steps.upload", default: "Upload"), path: nil, is_complete: import.pdf_uploaded?, step_number: 1 },
|
|
{ name: t("imports.steps.configure", default: "Configure"), path: nil, is_complete: import.configured?, step_number: 2 },
|
|
{ name: t("imports.steps.clean", default: "Clean"), path: import.configured? ? import_clean_path(import) : nil, is_complete: import.cleaned?, step_number: 3 },
|
|
{ name: t("imports.steps.confirm", default: "Confirm"), path: import_path(import), is_complete: import.complete?, step_number: 4 }
|
|
]
|
|
elsif import.is_a?(QifImport)
|
|
# QIF imports combine date-format configuration with category/tag selection.
|
|
[
|
|
{ name: t("imports.steps.upload", default: "Upload"), path: import_upload_path(import), is_complete: import.uploaded?, step_number: 1 },
|
|
{ name: t("imports.steps.select", default: "Select"), path: import.uploaded? ? import_qif_category_selection_path(import) : nil, is_complete: import.categories_selected?, step_number: 2 },
|
|
{ name: t("imports.steps.clean", default: "Clean"), path: import.uploaded? ? import_clean_path(import) : nil, is_complete: import.cleaned?, step_number: 3 },
|
|
{ name: t("imports.steps.map", default: "Map"), key: "Map", path: import_confirm_path(import), is_complete: import.publishable?, step_number: 4 },
|
|
{ name: t("imports.steps.confirm", default: "Confirm"), path: import_path(import), is_complete: import.complete?, step_number: 5 }
|
|
].reject { |step| step[:key] == "Map" && import.mapping_steps.empty? }
|
|
else
|
|
[
|
|
{ name: t("imports.steps.upload", default: "Upload"), path: import_upload_path(import), is_complete: import.uploaded?, step_number: 1 },
|
|
{ name: t("imports.steps.configure", default: "Configure"), path: import_configuration_path(import), is_complete: import.configured?, step_number: 2 },
|
|
{ name: t("imports.steps.clean", default: "Clean"), path: import_clean_path(import), is_complete: import.cleaned?, step_number: 3 },
|
|
{ name: t("imports.steps.map", default: "Map"), key: "Map", path: import_confirm_path(import), is_complete: import.publishable?, step_number: 4 },
|
|
{ name: t("imports.steps.confirm", default: "Confirm"), path: import_path(import), is_complete: import.complete?, step_number: 5 }
|
|
].reject { |step| step[:key] == "Map" && import.mapping_steps.empty? }
|
|
end %>
|
|
|
|
<% content_for :mobile_import_progress do %>
|
|
<% active_step_index = steps.index { |s| request.path.eql?(s[:match_path] || s[:path]) } %>
|
|
<% if active_step_index %>
|
|
<div class="md:hidden text-center text-secondary text-md my-2">
|
|
<span class="text-secondary"><%= t("imports.steps.progress", step: active_step_index + 1, total: steps.size, default: "Step %{step} of %{total}") %></span>
|
|
</div>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<ul class="hidden md:flex items-center gap-2">
|
|
<% steps.each_with_index do |step, idx| %>
|
|
<li class="flex items-center gap-2 group">
|
|
<% is_current = request.path == (step[:match_path] || step[:path]) %>
|
|
|
|
<% text_class = if is_current
|
|
"text-primary"
|
|
else
|
|
step[:is_complete] ? "text-green-600" : "text-secondary"
|
|
end %>
|
|
<% step_class = if is_current
|
|
"bg-surface-inset text-primary"
|
|
else
|
|
step[:is_complete] ? "bg-green-600/10 border-alpha-black-25" : "bg-container-inset"
|
|
end %>
|
|
|
|
<% step_content = capture do %>
|
|
<div class="flex items-center gap-2 text-sm font-medium <%= text_class %>">
|
|
<span class="<%= step_class %> w-7 h-7 rounded-full shrink-0 inline-flex items-center justify-center border border-transparent">
|
|
<%= step[:is_complete] && !is_current ? icon("check", size: "sm", color: "current") : idx + 1 %>
|
|
</span>
|
|
|
|
<span><%= step[:name] %></span>
|
|
</div>
|
|
<% end %>
|
|
<% if step[:path].present? %>
|
|
<%= link_to step[:path], class: "flex items-center gap-3" do %><%= step_content %><% end %>
|
|
<% else %>
|
|
<div class="flex items-center gap-3"><%= step_content %></div>
|
|
<% end %>
|
|
|
|
<hr class="border border-secondary w-12 group-last:hidden">
|
|
</li>
|
|
<% end %>
|
|
</ul>
|