feat: add formatted price and type label attributes to ProductPrice model and display in product table

This commit is contained in:
Yoga Pangestu 2026-04-18 16:24:52 +07:00
parent d06d32f3f8
commit cae6bc929a
3 changed files with 45 additions and 0 deletions

View File

@ -3,11 +3,14 @@
namespace App\Models;
use App\Enums\PriceType;
use Illuminate\Database\Eloquent\Attributes\Appends;
use Illuminate\Database\Eloquent\Attributes\Guarded;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
#[Guarded(['id'])]
#[Appends(['price_formatted', 'price_type_label'])]
class ProductPrice extends Model
{
protected function casts(): array
@ -18,6 +21,20 @@ protected function casts(): array
];
}
protected function priceTypeLabel(): Attribute
{
return Attribute::make(
get: fn () => $this->price_type->label(),
);
}
protected function priceFormatted(): Attribute
{
return Attribute::make(
get: fn () => 'Rp '.number_format($this->price, 0, ',', '.'),
);
}
public function product(): BelongsTo
{
return $this->belongsTo(Product::class);

View File

@ -79,6 +79,32 @@ export const getColumns = ({ onDelete, onToggleStatus, onPreviewImage }: ColumnP
);
}
},
{
accessorKey: "prices",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Harga" />
),
cell: ({ row }) => {
const product = row.original;
const prices = product.prices;
if (!prices || !Array.isArray(prices) || prices.length === 0) {
return <span className="text-muted-foreground text-xs italic">-</span>;
}
return (
<div className="flex flex-col gap-1">
{prices.map((p, i) => (
<div key={i} className="text-xs whitespace-nowrap">
<span className="text-muted-foreground">{p.price_type_label}:</span>{' '}
<span className="font-medium text-primary">{p.price_formatted}</span>
</div>
))}
</div>
);
},
meta: { title: "Harga" },
},
{
accessorKey: "is_active",
header: "Status",

View File

@ -5,6 +5,8 @@ export interface ProductPrice {
product_id: number;
price_type: 'purchase' | 'distributor' | 'agent' | 'reseller' | 'retail';
price: number;
price_formatted: string;
price_type_label: string;
created_at: string;
updated_at: string;
}