source: StockMaster/Views/PurchaseOrder/Create.cshtml

main
Last change on this file was dfe03b8, checked in by Ceyda <ceyda.huseini@…>, 3 days ago

Initialize StockMaster project

  • Property mode set to 100644
File size: 12.3 KB
Line 
1@model StockMaster.ViewModels.PurchaseOrderCreateViewModel
2@{
3 ViewData["Title"] = "New Purchase Order";
4}
5
6<div class="row mb-4">
7 <div class="col-12">
8 <h2><i class="fas fa-truck"></i> Create New Purchase Order</h2>
9 <nav aria-label="breadcrumb">
10 <ol class="breadcrumb">
11 <li class="breadcrumb-item"><a href="/">Home</a></li>
12 <li class="breadcrumb-item"><a href="/PurchaseOrder/Index">Purchase Orders</a></li>
13 <li class="breadcrumb-item active">New Order</li>
14 </ol>
15 </nav>
16 </div>
17</div>
18
19<form id="poForm" method="post" action="/PurchaseOrder/Create">
20 @Html.AntiForgeryToken()
21 <div class="row">
22 <div class="col-md-8">
23 <div class="card mb-3">
24 <div class="card-header">
25 <i class="fas fa-info-circle"></i> Order Information
26 </div>
27 <div class="card-body">
28 <div class="row">
29 <div class="col-md-4 mb-3">
30 <label class="form-label">Supplier</label>
31 <select name="SupplierId" class="form-select">
32 <option value="">Select supplier</option>
33 @foreach (var supplier in ViewBag.Suppliers)
34 {
35 <option value="@supplier.SupplierId">@supplier.Name</option>
36 }
37 </select>
38 </div>
39
40 <div class="col-md-4 mb-3">
41 <label class="form-label">Warehouse *</label>
42 <select name="WarehouseId" class="form-select" required>
43 <option value="">Select warehouse</option>
44 @foreach (var warehouse in ViewBag.Warehouses)
45 {
46 <option value="@warehouse.WarehouseId">@warehouse.Name</option>
47 }
48 </select>
49 </div>
50
51 <div class="col-md-4 mb-3">
52 <label class="form-label">Expected Delivery Date *</label>
53 <input type="date" name="ExpectedDeliveryDate" class="form-control"
54 min="@DateTime.Now.ToString("yyyy-MM-dd")"
55 value="@DateTime.Now.AddDays(7).ToString("yyyy-MM-dd")" required />
56 </div>
57 </div>
58 </div>
59 </div>
60
61 <div class="card">
62 <div class="card-header d-flex justify-content-between align-items-center">
63 <span><i class="fas fa-list"></i> Order Items</span>
64 <button type="button" class="btn btn-sm btn-success" onclick="addItem()">
65 <i class="fas fa-plus"></i> Add Product
66 </button>
67 </div>
68 <div class="card-body">
69 <div id="itemsContainer">
70
71 </div>
72
73
74 @if (ViewBag.Products == null || ViewBag.Products.Count == 0)
75 {
76 <div class="alert alert-warning">
77 <i class="fas fa-exclamation-triangle"></i>
78 No products available. Please add products first.
79 </div>
80 }
81 </div>
82 </div>
83 </div>
84
85 <div class="col-md-4">
86 <div class="card mb-3">
87 <div class="card-header">
88 <i class="fas fa-calculator"></i> Order Summary
89 </div>
90 <div class="card-body">
91 <div class="mb-3">
92 <div class="d-flex justify-content-between mb-2">
93 <span>Product Types:</span>
94 <strong id="itemCount">0</strong>
95 </div>
96 <div class="d-flex justify-content-between mb-2">
97 <span>Total Quantity:</span>
98 <strong id="totalQuantity">0</strong>
99 </div>
100 <hr>
101 <div class="d-flex justify-content-between">
102 <h5>Total Cost:</h5>
103 <h5 class="text-primary">
104 <strong id="totalCost">0.00 MKD</strong>
105 </h5>
106 </div>
107 </div>
108 </div>
109 </div>
110
111 <div class="card mb-3">
112 <div class="card-header">
113 <i class="fas fa-lightbulb"></i> Tips
114 </div>
115 <div class="card-body">
116 <ul class="list-unstyled mb-0">
117 <li class="mb-2">
118 <i class="fas fa-check text-success me-2"></i>
119 Check supplier information
120 </li>
121 <li class="mb-2">
122 <i class="fas fa-check text-success me-2"></i>
123 Set correct delivery date
124 </li>
125 <li class="mb-2">
126 <i class="fas fa-check text-success me-2"></i>
127 Review unit costs
128 </li>
129 <li>
130 <i class="fas fa-check text-success me-2"></i>
131 Verify stock levels
132 </li>
133 </ul>
134 </div>
135 </div>
136
137 <div class="card">
138 <div class="card-body">
139 <div class="d-grid gap-2">
140 <button type="submit" class="btn btn-primary btn-lg">
141 <i class="fas fa-check"></i> Create Order
142 </button>
143 <a href="/PurchaseOrder/Index" class="btn btn-secondary">
144 <i class="fas fa-times"></i> Cancel
145 </a>
146 </div>
147 </div>
148 </div>
149 </div>
150 </div>
151</form>
152
153
154<div id="itemTemplate" style="display: none;">
155 <div class="card mb-3 item-row">
156 <div class="card-body">
157 <div class="row">
158 <div class="col-md-5">
159 <label class="form-label">Product *</label>
160 <select class="form-select product-select" required>
161 <option value="">Select product</option>
162 @foreach (var product in ViewBag.Products)
163 {
164 <option value="@product.ProductId" data-sku="@product.Sku">
165 @product.Name (SKU: @product.Sku)
166 </option>
167 }
168 </select>
169 </div>
170 <div class="col-md-3">
171 <label class="form-label">Quantity *</label>
172 <input type="number" class="form-control quantity-input" min="1" value="1" required />
173 </div>
174 <div class="col-md-3">
175 <label class="form-label">Unit Cost (MKD) *</label>
176 <input type="number" class="form-control cost-input" step="0.01" min="0" required />
177 </div>
178 <div class="col-md-1">
179 <label class="form-label">&nbsp;</label>
180 <button type="button" class="btn btn-danger w-100" onclick="removeItem(this)">
181 <i class="fas fa-trash"></i>
182 </button>
183 </div>
184 </div>
185 <div class="row mt-2">
186 <div class="col-12">
187 <small class="text-muted">
188 Total: <span class="item-total">0.00</span> MKD
189 </small>
190 </div>
191 </div>
192 </div>
193 </div>
194</div>
195
196@section Scripts {
197 <script>
198 function addItem() {
199 const template = document.getElementById('itemTemplate').innerHTML;
200 const container = document.getElementById('itemsContainer');
201 const itemDiv = document.createElement('div');
202
203 itemDiv.innerHTML = template;
204
205 const row = itemDiv.firstElementChild;
206 container.appendChild(row);
207
208 const productSelect = row.querySelector('.product-select');
209 const quantityInput = row.querySelector('.quantity-input');
210 const costInput = row.querySelector('.cost-input');
211
212
213 productSelect.addEventListener('change', function() {
214 calculateItemTotal.call(this);
215 });
216 quantityInput.addEventListener('input', function() {
217 calculateItemTotal.call(this);
218 calculateSummary();
219 });
220 costInput.addEventListener('input', function() {
221 calculateItemTotal.call(this);
222 calculateSummary();
223 });
224
225
226 updateIndices();
227 calculateSummary();
228 }
229
230 function removeItem(button) {
231 button.closest('.item-row').remove();
232 updateIndices();
233 calculateSummary();
234 }
235
236
237 function updateIndices() {
238 document.querySelectorAll('#itemsContainer .item-row').forEach((row, index) => {
239 const productSelect = row.querySelector('.product-select');
240 const quantityInput = row.querySelector('.quantity-input');
241 const costInput = row.querySelector('.cost-input');
242
243 productSelect.name = `Items[${index}].ProductId`;
244 quantityInput.name = `Items[${index}].Quantity`;
245 costInput.name = `Items[${index}].UnitCost`;
246 });
247 }
248
249 function calculateItemTotal() {
250 const row = this.closest('.item-row');
251 const quantity = parseFloat(row.querySelector('.quantity-input').value) || 0;
252 const cost = parseFloat(row.querySelector('.cost-input').value) || 0;
253 const total = quantity * cost;
254 row.querySelector('.item-total').textContent = total.toFixed(2);
255 }
256
257 function calculateSummary() {
258 const items = document.querySelectorAll('#itemsContainer .item-row');
259 let totalCost = 0;
260 let totalQuantity = 0;
261
262 items.forEach(row => {
263 const quantity = parseFloat(row.querySelector('.quantity-input').value) || 0;
264 const cost = parseFloat(row.querySelector('.cost-input').value) || 0;
265 totalCost += quantity * cost;
266 totalQuantity += quantity;
267 });
268
269 document.getElementById('itemCount').textContent = items.length;
270 document.getElementById('totalQuantity').textContent = totalQuantity;
271 document.getElementById('totalCost').textContent = totalCost.toFixed(2) + ' MKD';
272 }
273
274 window.addEventListener('DOMContentLoaded', function() {
275 addItem();
276 });
277
278 document.getElementById('poForm').addEventListener('submit', function(e) {
279 const itemsCount = document.querySelectorAll('#itemsContainer .item-row').length;
280 if (itemsCount === 0) {
281 e.preventDefault();
282 alert('You must add at least one product!');
283 return false;
284 }
285
286 let allValid = true;
287 document.querySelectorAll('#itemsContainer .item-row').forEach(row => {
288 const productSelect = row.querySelector('.product-select');
289 if (!productSelect.value) {
290 allValid = false;
291 productSelect.classList.add('is-invalid');
292 } else {
293 productSelect.classList.remove('is-invalid');
294 }
295 });
296
297 if (!allValid) {
298 e.preventDefault();
299 alert('Please select products for all items!');
300 return false;
301 }
302
303 return true;
304 });
305 </script>
306}
Note: See TracBrowser for help on using the repository browser.