Skip to content
Open
Changes from 1 commit
Commits
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
116 changes: 116 additions & 0 deletions src/routes/dashboard/projects/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,123 @@

<Head title={data.project.name} />



<h1 class="mt-5 mb-2 font-hero text-3xl font-medium">{data.project.name}</h1>
<div class="mb-2">
<p class="text-sm">
Created
<abbr title={`${data.project.createdAt.toUTCString()}`}>
{relativeDate(data.project.createdAt)}
</abbr>
∙ Updated
<abbr title={`${new Date(data.project.updatedAt).toUTCString()}`}>
{relativeDate(data.project.updatedAt)}
</abbr>
∙ {Math.floor(data.project.timeSpent / 60)}h {data.project.timeSpent % 60}min
</p>
</div>

<div class="mb-8 w-full px-0 sm:px-2 md:px-4 lg:px-8 xl:px-16 py-6">
{#key data.project.status}
{#if data.project.status === 'rejected' || data.project.status === 'rejected_locked'}
<div class="flex items-center gap-3 w-full">
<div class="flex-1 h-4 rounded-full bg-gradient-to-r from-red-200 to-red-100 relative overflow-hidden w-full">
<div class="absolute left-0 top-0 h-4 rounded-full bg-gradient-to-r from-red-500 to-red-400 animate-pulse" style="width: 22%"></div>
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The rejected status progress bar shows a hardcoded width of 22% which appears to be an arbitrary magic number. This value should either be documented with a comment explaining its significance or extracted as a named constant to improve code clarity.

Copilot uses AI. Check for mistakes.
</div>
<span class="ml-2 text-red-700 font-bold text-base tracking-wide flex items-center gap-1 whitespace-nowrap">
<svg width="18" height="18" fill="none" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="#f87171"/><path d="M12 7v5m0 4h.01" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The rejected status icon SVG is missing accessible text for screen readers. Consider adding an aria-label or title element to describe the icon's meaning for users who rely on assistive technologies.

Suggested change
<svg width="18" height="18" fill="none" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="#f87171"/><path d="M12 7v5m0 4h.01" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>
<svg width="18" height="18" fill="none" viewBox="0 0 24 24" role="img" aria-label="Rejected status"><circle cx="12" cy="12" r="10" fill="#f87171"/><path d="M12 7v5m0 4h.01" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>

Copilot uses AI. Check for mistakes.
Rejected
</span>
</div>
{:else}
<div class="w-full flex flex-col items-stretch">
<div class="relative w-full flex items-center" style="height: 44px;">
<div class="absolute z-0 top-1/2 -translate-y-1/2 left-[5%] right-[5%] h-2 bg-gray-200 rounded-full overflow-hidden">
<div class="h-2 bg-gradient-to-r from-primary-400 to-primary-600 transition-all duration-300" style="width: calc((({[
'submitted',
't1_approved',
'printing',
'printed',
'finalized'
].indexOf(data.project.status)}) / 4) * 100%)"></div>
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The progress bar width calculation uses a hardcoded divisor of 4, which assumes there are always 5 steps (0-indexed). If the status list changes in the future, this calculation will break. Consider using a dynamic calculation based on the actual array length minus 1, such as (index / (steps.length - 1)) * 100%.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The progress calculation using indexOf() will return -1 if the project status is not in the expected list, resulting in a negative width value. While this may not crash the UI, it could lead to unexpected visual behavior. Consider adding validation to handle unexpected status values gracefully.

Copilot uses AI. Check for mistakes.
</div>
{#each [
{ key: 'submitted', label: 'Submitted', color: 'bg-indigo-400' },
{ key: 't1_approved', label: 'On print queue', color: 'bg-yellow-400' },
{ key: 'printing', label: 'Being printed', color: 'bg-emerald-400' },
{ key: 'printed', label: 'Printed', color: 'bg-blue-400' },
{ key: 'finalized', label: 'Payout', color: 'bg-green-200' }
] as step, i (step.key)}
<div class="flex-1 flex flex-col items-center min-w-0 relative z-10" style="position: absolute; left: calc(5% + (90% * {i} / 4)); top: 50%; transform: translate(-50%, -50%);">
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The hardcoded divisor of 4 in the positioning calculation assumes there are always 5 steps. This creates the same maintainability issue as the progress bar width calculation. If steps are added or removed, the positioning will be incorrect.

Copilot uses AI. Check for mistakes.
<div
class="w-7 h-7 rounded-full border-4 shadow-md transition-all duration-300"
class:bg-primary-500={[
'submitted',
't1_approved',
'printing',
'printed',
'finalized'
].indexOf(data.project.status) >= i}
class:bg-gray-200={[
'submitted',
't1_approved',
'printing',
'printed',
'finalized'
].indexOf(data.project.status) < i}
class:border-primary-500={[
'submitted',
't1_approved',
'printing',
'printed',
'finalized'
].indexOf(data.project.status) >= i}
class:border-gray-300={[
'submitted',
't1_approved',
'printing',
'printed',
'finalized'
].indexOf(data.project.status) < i}
class:{step.color}={true}
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The step color property defined in the loop (line 86-90) is not being used effectively. Line 123 sets the color with class:{step.color}={true}, but since the circles are already conditionally styled with bg-primary-500 or bg-gray-200 based on the status progression, the step.color classes (bg-indigo-400, bg-yellow-400, etc.) will be overridden and have no visible effect. This creates confusion about the intended styling.

Copilot uses AI. Check for mistakes.
style="box-shadow: 0 2px 8px 0 rgba(0,0,0,0.07);"
></div>
</div>
{/each}
</div>
<div class="relative w-full mt-3" style="height: 22px;">
{#each [
{ key: 'submitted', label: 'Submitted' },
{ key: 't1_approved', label: 'On print queue' },
{ key: 'printing', label: 'Being printed' },
{ key: 'printed', label: 'Printed' },
{ key: 'finalized', label: 'Payout' }
] as step, i (step.key)}
<div class="absolute w-max max-w-[20%] text-center left-0" style="left: calc(5% + (90% * {i} / 4)); transform: translate(-50%, 0);">
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The same hardcoded divisor of 4 is used here for label positioning, which will break if the number of steps changes. This should be calculated dynamically based on the array length.

Copilot uses AI. Check for mistakes.
<span class="text-xs font-semibold whitespace-nowrap"
class:text-primary-700={[
'submitted',
't1_approved',
'printing',
'printed',
'finalized'
].indexOf(data.project.status) >= i}
class:text-gray-400={[
'submitted',
't1_approved',
'printing',
'printed',
'finalized'
].indexOf(data.project.status) < i}
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The same array ['submitted', 't1_approved', 'printing', 'printed', 'finalized'] is repeated multiple times throughout the code. This creates significant code duplication and makes maintenance difficult. Consider extracting this array into a constant at the component level to improve maintainability and reduce the risk of inconsistencies.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

>{step.label}</span>
</div>
{/each}
</div>
</div>
{/if}
{/key}
</div>
Comment on lines +77 to +122
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

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

The progress indicator circles lack proper ARIA attributes for screen reader users. Consider adding role="progressbar", aria-valuenow, aria-valuemin, aria-valuemax, and aria-label attributes to make the progress bar accessible to users with disabilities.

Copilot uses AI. Check for mistakes.

<div class="flex flex-col xl:flex-row gap-3">
<div class="mb-6 grow">
Expand Down