chore: product variant modal rework#376
Conversation
WalkthroughThis update modifies how nutritional information is handled and displayed for product variants across several components. The input fields for nutrition in the update form now allow clearing values to Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UpdateForm
participant API
participant ChannelStore
participant Toast
User->>UpdateForm: Clicks Delete Button
UpdateForm->>Toast: Show "Deleting..." action toast
UpdateForm->>API: DELETE /api/product-variant/{id}
alt Success
API-->>UpdateForm: 200 OK
UpdateForm->>ChannelStore: Update after deletion
UpdateForm->>Toast: Show success message
UpdateForm->>User: Emit "success" event
else Failure
API-->>UpdateForm: Error
UpdateForm->>Toast: Show error message
end
Possibly related PRs
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/web-app/app/components/Form/UpdateProductVariant.vue (1)
254-270: Delete implementation looks good, consider refactoring common code.The
onDeletemethod follows the same pattern asonSubmitwith proper error handling and user feedback. Consider extracting the common toast and emit logic into a shared helper function to reduce duplication.+ function handleActionResult(success: boolean, message?: string) { + if (success) { + actionToast.success(message || '') + emit('success') + } else { + actionToast.error() + } + } async function onSubmit(event: FormSubmitEvent<ProductVariantUpdateSchema>) { actionToast.start() emit('submitted') try { await $fetch(`/api/product/variant/${productVariantId}`, { method: 'PATCH', body: event.data, }) await channel.update() - actionToast.success(t('toast.variant-updated')) - emit('success') + handleActionResult(true, t('toast.variant-updated')) } catch (error) { console.error(error) - actionToast.error() + handleActionResult(false) } } async function onDelete() { actionToast.start() emit('submitted') try { await $fetch(`/api/product/variant/${productVariantId}`, { method: 'DELETE', }) await channel.update() - actionToast.success(t('toast.variant-deleted')) - emit('success') + handleActionResult(true, t('toast.variant-deleted')) } catch (error) { console.error(error) - actionToast.error() + handleActionResult(false) } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/web-app/app/components/CommandCenter/ProductVariantCard.vue(1 hunks)apps/web-app/app/components/Form/DeleteProductVariant.vue(0 hunks)apps/web-app/app/components/Form/UpdateProductVariant.vue(2 hunks)apps/web-app/app/components/Modal/UpdateProductVariant.vue(1 hunks)apps/web-app/app/pages/catalog/[categorySlug]/[productSlug]/index.vue(1 hunks)packages/core/shared/services/product.ts(1 hunks)
💤 Files with no reviewable changes (1)
- apps/web-app/app/components/Form/DeleteProductVariant.vue
🔇 Additional comments (8)
packages/core/shared/services/product.ts (1)
46-49: Schema enhancement for nullable nutrition fieldsThe schema now explicitly allows
nullvalues for nutrition fields (calories,protein,fat, andcarbohydrate) by adding.nullable(). This is a good improvement that allows form inputs to properly clear these fields tonullrather than just omitting them.This change aligns well with the frontend updates in other files that now use explicit
!= nullchecks when rendering nutrition information.apps/web-app/app/components/Modal/UpdateProductVariant.vue (1)
4-8: UI simplification with consolidated functionalityThe modal component has been simplified by removing unnecessary wrappers and the separate delete form component. This indicates that the delete functionality has likely been integrated into the update form itself, creating a more streamlined user experience.
This consolidation is a good UX improvement that keeps all variant-related actions in one place.
apps/web-app/app/pages/catalog/[categorySlug]/[productSlug]/index.vue (1)
62-62: Simplified nutrition display logicThe condition for displaying the nutrition section has been improved to check only if
calories != nullinstead of using a more complex computed property. This aligns with the schema changes that now explicitly handle nullable nutrition fields.This simplification makes the code more maintainable while properly handling cases where nutrition values might be zero but still valid to display.
apps/web-app/app/components/CommandCenter/ProductVariantCard.vue (1)
16-29: Improved conditional rendering for nutrition valuesThe nutrition container is now always rendered, with each individual nutrition value conditionally displayed based on explicit
!= nullchecks. This is a great improvement that:
- Makes the layout more consistent by always rendering the container
- Properly handles zero values by using explicit null checks instead of truthiness
- Aligns with the schema changes that now support nullable nutrition fields
This approach ensures that valid zero values will be displayed correctly while still hiding undefined or null values.
apps/web-app/app/components/Form/UpdateProductVariant.vue (4)
83-94: Great UX enhancement with the clear button for nutrition fields.Adding a clear button for the calories field improves usability by allowing users to easily reset the value to null when needed. The conditional display ensures it only appears when there's an actual value to clear.
101-101: Good improvement to protein input precision and clearing.The change from "any" to 0.1 step provides more appropriate precision for protein values. The added clear button maintains consistency with the other nutrition fields.
Also applies to: 104-115
122-122: Appropriate step precision and clearing for fat values.Using 0.1 step for fat values matches nutritional standards, and the clear button implementation is consistent with other fields.
Also applies to: 125-136
143-143: Consistent implementation for carbohydrate field.The carbohydrate input follows the same pattern as protein and fat with appropriate step value and clear button functionality.
Also applies to: 146-157
| <div class="mt-3 flex flex-row gap-3"> | ||
| <UButton | ||
| type="submit" | ||
| variant="solid" | ||
| color="primary" | ||
| size="xl" | ||
| block | ||
| > | ||
| {{ $t('center.update.title') }} | ||
| </UButton> | ||
|
|
||
| <UButton | ||
| variant="soft" | ||
| color="error" | ||
| size="xl" | ||
| icon="i-lucide-trash-2" | ||
| class="aspect-square justify-center" | ||
| @click="onDelete" | ||
| /> | ||
| </div> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Consider adding a confirmation dialog for deletion.
While the UI layout with the delete button is clean, delete operations are destructive actions. Consider adding a confirmation dialog before proceeding with deletion to prevent accidental data loss.
<UButton
variant="soft"
color="error"
size="xl"
icon="i-lucide-trash-2"
class="aspect-square justify-center"
- @click="onDelete"
+ @click="showDeleteConfirmation = true"
/>
+ <UModal v-model="showDeleteConfirmation">
+ <UCard>
+ <template #header>
+ <div class="flex items-center gap-2">
+ <UIcon name="i-lucide-alert-triangle" class="text-error-500" />
+ <h3 class="text-lg font-semibold">{{ $t('common.delete-confirmation') }}</h3>
+ </div>
+ </template>
+ <p>{{ $t('center.product.variant-delete-confirmation') }}</p>
+ <template #footer>
+ <div class="flex justify-end gap-2">
+ <UButton color="neutral" @click="showDeleteConfirmation = false">
+ {{ $t('common.cancel') }}
+ </UButton>
+ <UButton color="error" @click="confirmDelete">
+ {{ $t('common.delete') }}
+ </UButton>
+ </div>
+ </template>
+ </UCard>
+ </UModal>You would also need to add these to your script:
const showDeleteConfirmation = ref(false)
async function confirmDelete() {
showDeleteConfirmation.value = false
await onDelete()
}


Summary by CodeRabbit
New Features
Improvements
Removals