Files
railsgoat/app/views/benefit_forms/index.html.erb
T
Ken Johnson f21da3f075 Improve file upload UX with validation and uploaded files display
Enhanced the benefit forms file upload functionality to provide better
user feedback and visibility of uploaded files.

Changes:
1. Added file type validation in controller:
   - Only accepts PDF, DOC, DOCX, JPG, PNG formats
   - Shows clear error message with the rejected file extension

2. Added file size validation:
   - Maximum 10MB file size limit
   - Shows file size in error message if exceeded

3. Improved success/error messages:
   - Shows specific filename on successful upload
   - Shows detailed error messages for validation failures

4. Added uploaded files display section:
   - Lists all uploaded files with icons based on file type
   - Shows file size and upload timestamp
   - Provides download button for each file
   - Only displays when files exist

Before: Users received generic "Something went wrong" message with no
indication of why uploads failed. No way to see uploaded files.

After: Clear validation feedback tells users exactly what went wrong
(wrong format, too large, etc.) and uploaded files are visible with
download links.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 13:13:21 +00:00

283 lines
9.9 KiB
Plaintext

<div class="container-fluid">
<div class="row mb-4">
<div class="col-12">
<h2 class="mb-3">
<i class="bi bi-file-earmark-medical text-primary"></i> Benefit Forms
</h2>
<p class="text-muted">Download benefit documents and upload completed forms</p>
</div>
</div>
<!-- Download Forms Section -->
<div class="row g-3 mb-4">
<!-- Health Insurance Card -->
<div class="col-lg-6">
<div class="card shadow-sm h-100 hover-card">
<div class="card-body text-center p-4">
<div class="mb-3">
<i class="bi bi-heart-pulse-fill" style="font-size: 3rem; color: var(--rg-primary);"></i>
</div>
<h4 class="card-title mb-3">Health Insurance</h4>
<p class="text-muted mb-4">Download your health insurance benefit forms and information</p>
<%= link_to download_path(type: "File", name: "public/docs/Health_n_Stuff.pdf"), class: "btn btn-primary btn-lg" do %>
<i class="bi bi-file-earmark-pdf"></i> Download PDF
<% end %>
</div>
</div>
</div>
<!-- Dental Insurance Card -->
<div class="col-lg-6">
<div class="card shadow-sm h-100 hover-card">
<div class="card-body text-center p-4">
<div class="mb-3">
<i class="bi bi-emoji-smile-fill" style="font-size: 3rem; color: var(--rg-success);"></i>
</div>
<h4 class="card-title mb-3">Dental Insurance</h4>
<p class="text-muted mb-4">Download your dental insurance benefit forms and information</p>
<%= link_to download_path(type: "File", name: "public/docs/Dental_n_Stuff.pdf"), class: "btn btn-success btn-lg" do %>
<i class="bi bi-file-earmark-pdf"></i> Download PDF
<% end %>
</div>
</div>
</div>
</div>
<!-- Upload Section -->
<div class="row">
<div class="col-12">
<div class="card shadow-sm">
<div class="card-header bg-white py-3">
<h4 class="mb-0">
<i class="bi bi-cloud-upload text-primary"></i> Upload Completed Forms
</h4>
</div>
<div class="card-body p-4">
<%= form_for @benefits, url: upload_path, html: { multipart: true, id: "fi", class: "needs-validation" } do |f| %>
<%= hidden_field "benefits", "backup", value: false %>
<div class="row g-3">
<div class="col-12">
<div class="upload-area p-4 text-center border rounded" style="border: 2px dashed #dee2e6; background: var(--rg-light); transition: all 0.3s;">
<i class="bi bi-cloud-arrow-up" style="font-size: 3rem; color: var(--rg-secondary);"></i>
<h5 class="mt-3 mb-2">Select File to Upload</h5>
<p class="text-muted mb-3">Choose a file from your computer</p>
<div class="file-input-wrapper">
<label for="benefits_upload" class="btn btn-primary mb-3" style="cursor: pointer;">
<i class="bi bi-folder2-open"></i> Choose File
</label>
<%= f.file_field :upload, class: "d-none", id: "benefits_upload" %>
</div>
<div class="selected-file mt-3">
<span class="filename text-muted">
<i class="bi bi-file-earmark"></i> No file selected
</span>
</div>
</div>
</div>
<div class="col-12">
<div class="d-flex gap-2">
<button id="start_upload" type="submit" class="btn btn-primary btn-lg">
<i class="bi bi-upload"></i> Upload File
</button>
<button type="button" class="btn btn-outline-secondary btn-lg" onclick="document.getElementById('fi').reset(); $('.filename').html('<i class=\'bi bi-file-earmark\'></i> No file selected');">
<i class="bi bi-x-circle"></i> Cancel
</button>
</div>
</div>
<div class="col-12">
<!-- Progress Bar -->
<div class="progress" style="height: 25px; display: none;" id="upload-progress">
<div class="progress-bar progress-bar-striped progress-bar-animated bg-primary" role="progressbar" style="width: 0%;" id="progress-bar">
<span id="progress-text">0%</span>
</div>
</div>
</div>
<div class="col-12">
<!-- Files Table -->
<table class="table table-hover d-none" id="files-table">
<thead class="table-light">
<tr>
<th>File Name</th>
<th>Size</th>
<th>Status</th>
</tr>
</thead>
<tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody>
</table>
</div>
</div>
<% end %>
</div>
</div>
</div>
</div>
<!-- Uploaded Files Section -->
<% if @uploaded_files.any? %>
<div class="row mt-4">
<div class="col-12">
<div class="card shadow-sm">
<div class="card-header bg-white py-3">
<h4 class="mb-0">
<i class="bi bi-folder2-open text-success"></i> Uploaded Files
</h4>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th><i class="bi bi-file-earmark"></i> File Name</th>
<th><i class="bi bi-hdd"></i> Size</th>
<th><i class="bi bi-clock"></i> Uploaded</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% @uploaded_files.each do |file| %>
<tr>
<td>
<% icon_class = case File.extname(file[:name]).downcase
when '.pdf' then 'bi-file-earmark-pdf text-danger'
when '.doc', '.docx' then 'bi-file-earmark-word text-primary'
when '.jpg', '.jpeg', '.png' then 'bi-file-earmark-image text-success'
else 'bi-file-earmark'
end %>
<i class="bi <%= icon_class %> me-2"></i>
<strong><%= file[:name] %></strong>
</td>
<td><%= number_to_human_size(file[:size]) %></td>
<td><%= file[:modified].strftime("%b %d, %Y at %I:%M %p") %></td>
<td>
<%= link_to download_path(type: "File", name: "public/data/#{file[:name]}"), class: "btn btn-sm btn-outline-primary" do %>
<i class="bi bi-download"></i> Download
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<% end %>
<!-- Info Box -->
<div class="row mt-4">
<div class="col-12">
<div class="alert alert-info" role="alert">
<div class="d-flex align-items-start">
<i class="bi bi-info-circle-fill me-2" style="font-size: 1.5rem;"></i>
<div>
<h5 class="alert-heading mb-2">Important Information</h5>
<ul class="mb-0 ps-3">
<li>Download benefit forms, fill them out completely, and upload them back</li>
<li>Accepted file formats: PDF, DOC, DOCX, JPG, PNG</li>
<li>Maximum file size: 10MB</li>
<li>All uploaded documents are securely stored</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function makeActive() {
$('li[id="benefit_forms"]').addClass('active');
}
$(document).ready(function() {
makeActive();
// File input change handler
$("#benefits_upload").change(function() {
var fileName = $(this).val();
if (fileName) {
// Extract just the filename from the full path
fileName = fileName.split('\\').pop().split('/').pop();
$(".filename").html('<i class="bi bi-file-earmark-check-fill text-success"></i> ' + fileName);
// Highlight the upload area
$(".upload-area").css({
'border-color': 'var(--rg-success)',
'background': 'rgba(6, 214, 160, 0.05)'
});
} else {
$(".filename").html('<i class="bi bi-file-earmark"></i> No file selected');
$(".upload-area").css({
'border-color': '#dee2e6',
'background': 'var(--rg-light)'
});
}
});
// Form submission handler (for demonstration)
$("#fi").submit(function(e) {
var fileName = $("#benefits_upload").val();
if (!fileName) {
e.preventDefault();
alert('Please select a file to upload');
return false;
}
// Show progress bar
$("#upload-progress").show();
// Simulate upload progress (in real implementation, this would be handled by the server)
var progress = 0;
var interval = setInterval(function() {
progress += 10;
$("#progress-bar").css('width', progress + '%');
$("#progress-text").text(progress + '%');
if (progress >= 100) {
clearInterval(interval);
}
}, 200);
});
});
// Handle Turbolinks page loads
$(document).on('turbolinks:load', function() {
makeActive();
});
</script>
<style>
.hover-card {
transition: all 0.3s ease;
}
.hover-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 24px rgba(0,0,0,0.15) !important;
}
.upload-area:hover {
border-color: var(--rg-primary) !important;
background: rgba(230, 57, 70, 0.03) !important;
}
.file-input-wrapper input[type="file"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
#progress-bar {
font-weight: 600;
line-height: 25px;
}
</style>