Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"github@claude-plugins-official": true
}
}
4 changes: 4 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,7 @@ npm install && npm run dev
- Status: green/blue/yellow/red
- Charts: Custom SVG, CSS Grid for layouts
- No emojis in UI

## Code Standards

- **Comments**: Always document non-obvious logic changes with comments. Only add a comment when the WHY is non-obvious: a hidden constraint, a subtle invariant, a workaround for a specific bug, behavior that would surprise a reader.
3 changes: 3 additions & 0 deletions client/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<router-link to="/demand" :class="{ active: $route.path === '/demand' }">
{{ t('nav.demandForecast') }}
</router-link>
<router-link to="/restocking" :class="{ active: $route.path === '/restocking' }">
{{ t('nav.restocking') }}
</router-link>
<router-link to="/reports" :class="{ active: $route.path === '/reports' }">
Reports
</router-link>
Expand Down
5 changes: 5 additions & 0 deletions client/src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,10 @@ export const api = {
async getPurchaseOrderByBacklogItem(backlogItemId) {
const response = await axios.get(`${API_BASE_URL}/purchase-orders/${backlogItemId}`)
return response.data
},

async submitRestockingOrder(orderData) {
const response = await axios.post(`${API_BASE_URL}/orders`, orderData)
return response.data
}
}
30 changes: 30 additions & 0 deletions client/src/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default {
orders: 'Orders',
finance: 'Finance',
demandForecast: 'Demand Forecast',
restocking: 'Restocking',
companyName: 'Catalyst Components',
subtitle: 'Inventory Management System'
},
Expand Down Expand Up @@ -106,6 +107,9 @@ export default {
title: 'Orders',
description: 'View and manage customer orders',
allOrders: 'All Orders',
submittedOrders: 'Submitted Orders',
historicalOrders: 'Historical Orders',
statusSubmitted: 'Submitted',
totalOrders: 'Total Orders',
totalRevenue: 'Total Revenue',
avgOrderValue: 'Avg Order Value',
Expand All @@ -129,6 +133,32 @@ export default {
}
},

// Restocking
restocking: {
title: 'Restocking',
description: 'Plan and submit restocking orders based on demand forecasts',
warehouse: 'Select Warehouse',
budget: 'Available Budget',
recommendations: 'Recommended Items',
itemsRecommended: 'Items Recommended',
totalCost: 'Total Cost',
budgetRemaining: 'Budget Remaining',
sku: 'SKU',
productName: 'Product Name',
category: 'Category',
currentStock: 'Current Stock',
forecastedDemand: 'Forecasted Demand',
recommendedQty: 'Rec. Qty',
unitCost: 'Unit Cost',
placeOrder: 'Place Order',
submitting: 'Submitting...',
reset: 'Reset Selections',
noRecommendations: 'No recommendations available for this warehouse',
overBudget: 'Order exceeds budget',
selectAll: 'Select all items',
selectAtLeastOne: 'Please select at least one item'
},

// Finance/Spending
finance: {
title: 'Finance Dashboard',
Expand Down
30 changes: 30 additions & 0 deletions client/src/locales/ja.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default {
orders: '注文',
finance: '財務',
demandForecast: '需要予測',
restocking: '補充注文',
companyName: '触媒コンポーネンツ',
subtitle: '在庫管理システム'
},
Expand Down Expand Up @@ -106,6 +107,9 @@ export default {
title: '注文',
description: '顧客注文の表示と管理',
allOrders: 'すべての注文',
submittedOrders: '提出済み注文',
historicalOrders: '過去の注文',
statusSubmitted: '提出済み',
totalOrders: '総注文数',
totalRevenue: '総収益',
avgOrderValue: '平均注文額',
Expand All @@ -129,6 +133,32 @@ export default {
}
},

// Restocking
restocking: {
title: '補充注文',
description: '需要予測に基づいて補充注文を計画・提出します',
warehouse: '倉庫を選択',
budget: '利用可能予算',
recommendations: '推奨品目',
itemsRecommended: '推奨品目数',
totalCost: '合計コスト',
budgetRemaining: '残る予算',
sku: 'SKU',
productName: '製品名',
category: 'カテゴリ',
currentStock: '現在の在庫',
forecastedDemand: '予測需要',
recommendedQty: '推奨数量',
unitCost: '単価',
placeOrder: '注文を提出',
submitting: '提出中...',
reset: 'リセット',
noRecommendations: 'この倉庫には推奨品目がありません',
overBudget: '注文が予算を超えています',
selectAll: 'すべてを選択',
selectAtLeastOne: '少なくとも1つの品目を選択してください'
},

// Finance/Spending
finance: {
title: '財務ダッシュボード',
Expand Down
4 changes: 3 additions & 1 deletion client/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Orders from './views/Orders.vue'
import Demand from './views/Demand.vue'
import Spending from './views/Spending.vue'
import Reports from './views/Reports.vue'
import Restocking from './views/Restocking.vue'

const router = createRouter({
history: createWebHistory(),
Expand All @@ -16,7 +17,8 @@ const router = createRouter({
{ path: '/orders', component: Orders },
{ path: '/demand', component: Demand },
{ path: '/spending', component: Spending },
{ path: '/reports', component: Reports }
{ path: '/reports', component: Reports },
{ path: '/restocking', component: Restocking }
]
})

Expand Down
98 changes: 93 additions & 5 deletions client/src/views/Orders.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,59 @@
</div>
</div>

<div class="card">
<!-- Submitted Orders Section -->
<div v-if="submittedOrders.length > 0" class="card submitted-section">
<div class="card-header">
<h3 class="card-title">{{ t('orders.allOrders') }} ({{ orders.length }})</h3>
<h3 class="card-title">{{ t('orders.submittedOrders') }} ({{ submittedOrders.length }})</h3>
</div>
<div class="table-container">
<table class="orders-table">
<thead>
<tr>
<th class="col-order-number">{{ t('orders.table.orderNumber') }}</th>
<th class="col-warehouse">Warehouse</th>
<th class="col-items">{{ t('orders.table.items') }}</th>
<th class="col-status">{{ t('orders.table.status') }}</th>
<th class="col-date">{{ t('orders.table.orderDate') }}</th>
<th class="col-leadtime">Lead Time (days)</th>
<th class="col-value">{{ t('orders.table.totalValue') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="order in submittedOrders" :key="order.id">
<td class="col-order-number"><strong>{{ order.order_number }}</strong></td>
<td class="col-warehouse">{{ order.warehouse }}</td>
<td class="col-items">
<details class="items-details">
<summary class="items-summary">
{{ t('orders.itemsCount', { count: order.items.length }) }}
</summary>
<div class="items-dropdown">
<div v-for="(item, idx) in order.items" :key="idx" class="item-entry">
<span class="item-name">{{ translateProductName(item.name) }}</span>
<span class="item-meta">{{ t('orders.quantity') }}: {{ item.quantity }} @ {{ currencySymbol }}{{ item.unit_price }}</span>
</div>
</div>
</details>
</td>
<td class="col-status">
<span :class="['badge', getOrderStatusClass(order.status)]">
{{ t('orders.statusSubmitted') }}
</span>
</td>
<td class="col-date">{{ formatDate(order.order_date) }}</td>
<td class="col-leadtime">{{ calculateLeadTime(order.expected_delivery) }}</td>
<td class="col-value"><strong>{{ currencySymbol }}{{ order.total_value.toLocaleString() }}</strong></td>
</tr>
</tbody>
</table>
</div>
</div>

<!-- Mock/Historical Orders Section -->
<div class="card mock-section">
<div class="card-header">
<h3 class="card-title">{{ t('orders.historicalOrders') }} ({{ regularOrders.length }})</h3>
</div>
<div class="table-container">
<table class="orders-table">
Expand All @@ -45,7 +95,7 @@
</tr>
</thead>
<tbody>
<tr v-for="order in orders" :key="order.id">
<tr v-for="order in regularOrders" :key="order.id">
<td class="col-order-number"><strong>{{ order.order_number }}</strong></td>
<td class="col-customer">{{ translateCustomerName(order.customer) }}</td>
<td class="col-items">
Expand Down Expand Up @@ -138,11 +188,28 @@ export default {
'Delivered': 'success',
'Shipped': 'info',
'Processing': 'warning',
'Backordered': 'danger'
'Backordered': 'danger',
'Submitted Orders': 'info'
}
return statusMap[status] || 'info'
}

const submittedOrders = computed(() =>
orders.value.filter(order => order.status === 'Submitted Orders')
)

const regularOrders = computed(() =>
orders.value.filter(order => order.status !== 'Submitted Orders')
)

const calculateLeadTime = (expectedDeliveryDate) => {
const today = new Date()
const delivery = new Date(expectedDeliveryDate)
const diffTime = Math.abs(delivery - today)
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
return diffDays
}

const formatDate = (dateString) => {
const { currentLocale } = useI18n()
const locale = currentLocale.value === 'ja' ? 'ja-JP' : 'en-US'
Expand All @@ -160,12 +227,15 @@ export default {
loading,
error,
orders,
submittedOrders,
regularOrders,
getOrdersByStatus,
getOrderStatusClass,
formatDate,
currencySymbol,
translateProductName,
translateCustomerName
translateCustomerName,
calculateLeadTime
}
}
}
Expand Down Expand Up @@ -203,6 +273,24 @@ export default {
width: 120px;
}

.col-warehouse {
width: 140px;
}

.col-leadtime {
width: 140px;
text-align: center;
}

.submitted-section {
margin-bottom: 2rem;
border-top: 3px solid #3b82f6;
}

.mock-section {
border-top: 3px solid #9ca3af;
}

/* Items details styling */
.items-details {
position: relative;
Expand Down
Loading