Skip to content

Conversation

@bbarni2020
Copy link
Collaborator

No description provided.

Introduces database schema and migration for printers and printer orders, including new enums and relations. Adds admin and public UI for managing printers and upgrades in the dashboard, with create, update, and delete functionality. Updates Svelte components and database schema to support the new printer market feature.
Copilot AI review requested due to automatic review settings January 17, 2026 23:42

This comment was marked as outdated.

This comment was marked as outdated.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 11 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +66 to +74
for (const item of selectedItems) {
if (item.startsWith('marketItem-')) {
const id = parseInt(item.slice('marketItem-'.length));
if (!id) throw error(400, { message: 'malformed market item filter' });
marketItemFilter.push(id);
} else if (item.startsWith('printer-')) {
const id = parseInt(item.slice('printer-'.length));
if (!id) throw error(400, { message: 'malformed printer filter' });
printerFilter.push(id);
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The validation check 'parseInt(id) || null' at line 68 and 72 will incorrectly treat a valid ID of 0 as invalid because 0 is falsy in JavaScript. While printer IDs likely start at 1, this is still a potential bug. The validation should use 'isNaN(id)' or 'id === 0' explicitly if 0 is an invalid ID, rather than relying on truthiness checks.

Copilot uses AI. Check for mistakes.
const name = formData.get('name')?.toString();
const description = formData.get('description')?.toString();
const image = formData.get('image')?.toString();
const isBase = formData.get('isBase') === 'on';
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The 'isBase' field is being checked via 'formData.get('isBase') === 'on'', but 'isBase' is not a form field name that's actually submitted from the admin form. The form uses a checkbox with id 'isBase' that changes the local 'formType' state, but there's no hidden input or form field named 'isBase' being submitted. This will cause the server to always treat submissions as upgrades (isBase will always be false), leading to incorrect data being saved.

Suggested change
const isBase = formData.get('isBase') === 'on';
const formType = formData.get('formType')?.toString() || 'base';
const isBase = formType === 'base';

Copilot uses AI. Check for mistakes.
class="h-4 w-4"
/>
<label for="isBase" class="font-semibold cursor-pointer">Base Printer</label>
</div>
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The admin form is missing a hidden input or proper form field to submit whether the printer is a base printer or upgrade. The checkbox at line 157-167 changes local state (formType) but doesn't have a 'name' attribute, so the server won't receive this information. This causes the server-side logic at line 29 and 70 of +page.server.ts to always evaluate 'isBase' as false. Add a hidden input field that tracks the formType value, or add a 'name' attribute to the checkbox.

Suggested change
</div>
</div>
<input type="hidden" name="isBase" value={formType === 'base' ? 'true' : 'false'} />

Copilot uses AI. Check for mistakes.
Comment on lines +184 to +204
<label class="block">
<span class="mb-1 block font-semibold">Min Shop Score</span>
<input
type="number"
name="minShopScore"
bind:value={form.minShopScore}
min="0"
class="w-full rounded-lg border border-primary-700 bg-primary-900 p-2 text-primary-100"
/>
</label>
<label class="block">
<span class="mb-1 block font-semibold">Max Shop Score</span>
<input
type="number"
name="maxShopScore"
bind:value={form.maxShopScore}
min="0"
class="w-full rounded-lg border border-primary-700 bg-primary-900 p-2 text-primary-100"
/>
</label>
<label class="block">
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

There's inconsistent indentation with mixed tabs and spaces. Line 184 and 204 use spaces for indentation while the rest of the file uses tabs. This should be corrected to maintain consistent code formatting throughout the file.

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +104
if (locals.user.idvToken) {
let userData = null;

try {
const token = decrypt(locals.user.idvToken);
userData = await getUserData(token);
} catch {
userDataError = true;
}

addresses = userData?.addresses;
} else {
userDataError = true;
}

return {
printerData: {
...basePrinter,
clayPrice: basePrinter.clayPrice || 40
},
isBase: true,
addresses,
userDataError
};
} else {
const [upgrade] = await db
.select()
.from(printer)
.where(
and(
eq(printer.deleted, false),
eq(printer.isPublic, true),
eq(printer.id, id),
isNotNull(printer.requiresId)
)
)
.limit(1);

if (!upgrade) {
throw error(404, { message: 'printer upgrade not found' });
}

const computedPrice = calculateMarketPrice(
upgrade.minPrice,
upgrade.maxPrice,
upgrade.minShopScore,
upgrade.maxShopScore,
locals.user.shopScore
);

const discountAmount = (upgrade.maxPrice - computedPrice) / upgrade.maxPrice;

let userDataError = false;
let addresses = null;

if (locals.user.idvToken) {
let userData = null;

try {
const token = decrypt(locals.user.idvToken);
userData = await getUserData(token);
} catch {
userDataError = true;
}

addresses = userData?.addresses;
} else {
userDataError = true;
}
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

There's duplicated code for fetching user address data. Lines 36-49 and lines 91-104 contain identical logic for fetching addresses via idvToken. This code should be extracted into a helper function to improve maintainability and reduce duplication.

Copilot uses AI. Check for mistakes.

export async function load({ locals, params, url }) {
if (!locals.user) {
throw error(500);
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The function throws a 500 error when the user is not authenticated (line 12). A 500 status code indicates an internal server error, but an unauthenticated user is not a server error - it's a client error. This should return a 401 (Unauthorized) or 403 (Forbidden) status code instead, or redirect to a login page.

Suggested change
throw error(500);
throw error(401, { message: 'unauthenticated' });

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

@ArcaEge ArcaEge left a comment

Choose a reason for hiding this comment

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

Sending more detailed info in the slack channel

@ArcaEge
Copy link
Collaborator

ArcaEge commented Jan 18, 2026

Merge the stuff I pushed to the printer-shop branch on this repo into your own fork (I can't commit to your fork sorry), then have a look at what I sent in Slack

Fix some of the issues with the pr
@bbarni2020
Copy link
Collaborator Author

Merged

@bbarni2020 bbarni2020 closed this Jan 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants