diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index e36d0ad..642c257 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -1,7 +1,7 @@
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';
-
+import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
@@ -9,6 +9,7 @@ export const appConfig: ApplicationConfig = {
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideAnimations(),
+ provideHttpClient(),
]
};
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
new file mode 100644
index 0000000..180b92c
--- /dev/null
+++ b/src/app/app.module.ts
@@ -0,0 +1,9 @@
+import { bootstrapApplication } from '@angular/platform-browser';
+import { AppComponent } from './app.component';
+import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
+
+bootstrapApplication(AppComponent, {
+ providers: [
+ provideHttpClient(withInterceptorsFromDi())
+ ]
+});
\ No newline at end of file
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index 7308758..f1d42b7 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -15,6 +15,15 @@ import { authGuard } from './gaurds/auth.guard'
import { roleGuard } from './gaurds/role.guard';
import { VendorSignupComponent } from './components/auth-page/vendor-signup/vendor-signup.component';
import { SupplierSignupComponent } from './components/auth-page/supplier-signup/supplier-signup.component';
+import { VendorComponent } from './components/vendor-page/vender/vendor.component';
+import { ProductSectionComponent } from './components/vendor-page/product-section/product-section.component';
+import { CartComponent } from './components/vendor-page/cart/cart.component';
+import { OrderSummaryComponent } from './components/vendor-page/order-summary/order-summary.component';
+import { CartSummaryComponent } from './components/vendor-page/cart-summary/cart-summary.component';
+import { OrdersComponent } from './components/vendor-page/orders/orders.component';
+
+import { WarehouseComponent } from './components/admin-page/warehouse/warehouse.component';
+
export const routes: Routes = [
{
@@ -35,7 +44,7 @@ export const routes: Routes = [
{
path: 'dashboard',
component: DashboardLayoutComponent,
- canActivate: [authGuard],
+ // canActivate: [authGuard],
children: [
{ path: '', component: ProfileComponent, pathMatch: 'full' }, // /dashboard
{ path: 'profile', component: ProfileComponent, pathMatch: 'full' },
@@ -44,6 +53,7 @@ export const routes: Routes = [
component: ForecastComponent,
pathMatch: 'full',
},
+ { path: 'warehouse', component: WarehouseComponent, pathMatch: 'full' },
{ path: 'order-history', component: OrderHistoryComponent }, // /dashboard/orders
{ path: 'inventory', component: InventoryComponent }, // /dashboard/inventory
{ path: 'product-management', component: ProductManagementComponent}, // /dashboard/product-management
@@ -51,6 +61,12 @@ export const routes: Routes = [
// { path: 'deliveries', component: DeliveriesComponent }, // /dashboard/deliveries
// { path: 'vendors', component: VendorsComponent },
{ path: 'supplier', component: SupplierDashboard, pathMatch: 'full' },
+ { path: 'vendor', component: VendorComponent, pathMatch: 'full' },
+ { path: 'vendor/products', component: ProductSectionComponent, pathMatch: 'full' },
+ { path: 'vendor/cart', component: CartComponent, pathMatch: 'full' },
+ { path: 'vendor/orders/order-details/:id', component: OrderSummaryComponent, pathMatch: 'full' },
+ { path: 'vendor/cart-summery', component: CartSummaryComponent, pathMatch: 'full' },
+ { path: 'vendor/orders', component: OrdersComponent, pathMatch: 'full' },
]
},
{ path: '**', redirectTo: 'home' }, // Handle 404/unknown routes
diff --git a/src/app/components/admin-page/warehouse/warehouse.component.css b/src/app/components/admin-page/warehouse/warehouse.component.css
new file mode 100644
index 0000000..1daef03
--- /dev/null
+++ b/src/app/components/admin-page/warehouse/warehouse.component.css
@@ -0,0 +1,189 @@
+/* Warehouse Card Styles */
+.warehouse-card {
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+ }
+
+ .warehouse-card:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
+ }
+
+ /* Gradient Backgrounds */
+ .warehouse-header-gradient {
+ background-image: linear-gradient(135deg, #4f46e5 0%, #3b82f6 100%);
+ }
+
+ .inventory-header-gradient {
+ background-image: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
+ }
+
+ /* Custom Badge Styles */
+ .custom-badge {
+ border-radius: 9999px;
+ padding: 0.25rem 0.75rem;
+ font-size: 0.75rem;
+ font-weight: 500;
+ display: inline-flex;
+ align-items: center;
+ }
+
+ .badge-blue {
+ background-color: rgba(59, 130, 246, 0.1);
+ color: #1e40af;
+ }
+
+ .badge-green {
+ background-color: rgba(16, 185, 129, 0.1);
+ color: #065f46;
+ }
+
+ .badge-amber {
+ background-color: rgba(245, 158, 11, 0.1);
+ color: #92400e;
+ }
+
+ /* Status Indicators */
+ .status-indicator {
+ display: inline-block;
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ margin-right: 6px;
+ }
+
+ .status-active {
+ background-color: #10b981;
+ }
+
+ .status-inactive {
+ background-color: #ef4444;
+ }
+
+ /* Button Animations */
+ .btn-primary {
+ transition: all 0.2s ease;
+ position: relative;
+ overflow: hidden;
+ }
+
+ .btn-primary:after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 5px;
+ height: 5px;
+ background: rgba(255, 255, 255, 0.5);
+ opacity: 0;
+ border-radius: 100%;
+ transform: scale(1, 1) translate(-50%);
+ transform-origin: 50% 50%;
+ }
+
+ .btn-primary:focus:not(:active)::after {
+ animation: ripple 1s ease-out;
+ }
+
+ @keyframes ripple {
+ 0% {
+ transform: scale(0, 0);
+ opacity: 0.5;
+ }
+ 20% {
+ transform: scale(25, 25);
+ opacity: 0.3;
+ }
+ 100% {
+ opacity: 0;
+ transform: scale(40, 40);
+ }
+ }
+
+ /* Search Input Focus Effect */
+ .search-input:focus {
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
+ }
+
+ /* Table Row Hover Effect */
+ .inventory-row {
+ transition: background-color 0.2s ease;
+ }
+
+ .inventory-row:hover {
+ background-color: rgba(243, 244, 246, 0.8);
+ }
+
+ /* Loading Animation */
+ .loading-spinner {
+ animation: spin 1s linear infinite;
+ }
+
+ @keyframes spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+ }
+
+ /* Back Button Hover Effect */
+ .back-button {
+ transition: transform 0.2s ease;
+ }
+
+ .back-button:hover {
+ transform: translateX(-3px);
+ }
+
+ /* Responsive Adjustments */
+ @media (max-width: 768px) {
+ .warehouse-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .stats-container {
+ flex-direction: column;
+ }
+
+ .stats-item {
+ margin-bottom: 1rem;
+ }
+ }
+
+ /* Inventory Quantity Tags */
+ .quantity-high {
+ background-color: #d1fae5;
+ color: #065f46;
+ }
+
+ .quantity-medium {
+ background-color: #fef3c7;
+ color: #92400e;
+ }
+
+ .quantity-low {
+ background-color: #fee2e2;
+ color: #b91c1c;
+ }
+
+ /* Page Transitions */
+ .page-enter {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+
+ .page-enter-active {
+ opacity: 1;
+ transform: translateY(0);
+ transition: opacity 300ms, transform 300ms;
+ }
+
+ .page-exit {
+ opacity: 1;
+ }
+
+ .page-exit-active {
+ opacity: 0;
+ transition: opacity 300ms;
+ }
\ No newline at end of file
diff --git a/src/app/components/admin-page/warehouse/warehouse.component.html b/src/app/components/admin-page/warehouse/warehouse.component.html
new file mode 100644
index 0000000..d906565
--- /dev/null
+++ b/src/app/components/admin-page/warehouse/warehouse.component.html
@@ -0,0 +1,280 @@
+
+
+
+
+
+
+
+
+
+ Warehouse Management
+
+
+ {{ selectedWarehouse ? 'Inventory for' : 'All Warehouses' }}
+
+
+ {{ selectedWarehouse ? selectedWarehouse.warehouse_name : 'Warehouse Directory' }}
+
+
+ {{ selectedWarehouse ? 'View and manage inventory' : 'Manage your storage facilities' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Warehouses
+
+ {{ warehouses.length }} locations
+
+
+
+
+
+
+
+
+
0; else noWarehousesTemplate" class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
+
+
+
{{ warehouse.warehouse_name }}
+ ID: {{ warehouse.id }}
+
+
+
+
+
{{ warehouse.location_x }}, {{ warehouse.location_y }}
+
+
+
+
Capacity: {{ parseFloat(warehouse.capacity).toLocaleString() }} units
+
+
+
+
Created: {{ formatDate(warehouse.created_at) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ selectedWarehouse.warehouse_name }}
+
ID: {{ selectedWarehouse.id }}
+
+
{{ selectedWarehouse.location_x }}, {{ selectedWarehouse.location_y }}
+
+
+
+
Warehouse Capacity
+
{{ parseFloat(selectedWarehouse.capacity).toLocaleString() }} units
+
+
+
+
+
+
+
+
0; else noInventoryTemplate">
+
+
+
+
Category
+
Product Name
+
Quantity
+
Supplied Date
+
+
+
+
+
+
+
+
+
+
{{ item.product_name }}
+
Category: {{ item.category }}
+
+
+ {{ item.product_count.toLocaleString() }} units
+
+
+
Supplied: {{ formatDate(item.supplied_date) }} by {{ item.supplied_by }}
+
+
+
+
+
{{ item.category }}
+
{{ item.product_name }}
+
+
+ {{ item.product_count.toLocaleString() }} units
+
+
+
{{ formatDate(item.supplied_date) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
No warehouses found
+
+ {{ warehouses.length > 0 ? 'No warehouses match your search.' : 'There are no warehouses in the system yet.' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
No inventory items found
+
+ {{ inventoryProducts.length > 0 ? 'No inventory items match your search.' : 'This warehouse is currently empty.' }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/admin-page/warehouse/warehouse.component.spec.ts b/src/app/components/admin-page/warehouse/warehouse.component.spec.ts
new file mode 100644
index 0000000..65e7fda
--- /dev/null
+++ b/src/app/components/admin-page/warehouse/warehouse.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+
+import { WarehouseComponent } from './warehouse.component';
+
+describe('WarehouseComponent', () => {
+ let component: WarehouseComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [WarehouseComponent, HttpClientTestingModule]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(WarehouseComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
\ No newline at end of file
diff --git a/src/app/components/admin-page/warehouse/warehouse.component.ts b/src/app/components/admin-page/warehouse/warehouse.component.ts
new file mode 100644
index 0000000..844d000
--- /dev/null
+++ b/src/app/components/admin-page/warehouse/warehouse.component.ts
@@ -0,0 +1,120 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
+import { WarehouseService, Warehouse, WarehouseInventory, InventoryProductDetail } from '../../../services/warehouse.service';
+
+@Component({
+ selector: 'app-warehouse',
+ standalone: true,
+ imports: [CommonModule, FormsModule, RouterModule],
+ templateUrl: './warehouse.component.html',
+ styleUrls: ['./warehouse.component.css']
+})
+export class WarehouseComponent implements OnInit {
+ warehouses: Warehouse[] = [];
+ inventoryData: WarehouseInventory | null = null;
+ inventoryProducts: InventoryProductDetail[] = [];
+ selectedWarehouse: Warehouse | null = null;
+ loading = false;
+ searchQuery = '';
+ filteredWarehouses: Warehouse[] = [];
+
+ // For inventory view
+ inventoryLoading = false;
+ inventorySearchQuery = '';
+ filteredInventoryProducts: InventoryProductDetail[] = [];
+
+ constructor(private warehouseService: WarehouseService) { }
+
+ ngOnInit(): void {
+ this.loadWarehouses();
+ }
+
+ // Add this method to make parseFloat available in the template
+ parseFloat(value: string): number {
+ return parseFloat(value);
+ }
+
+ loadWarehouses(): void {
+ this.loading = true;
+ this.warehouseService.getWarehouses().subscribe({
+ next: (data) => {
+ this.warehouses = data;
+ this.filteredWarehouses = [...this.warehouses];
+ this.loading = false;
+ },
+ error: (error) => {
+ console.error('Error loading warehouses', error);
+ this.loading = false;
+ }
+ });
+ }
+
+ selectWarehouse(warehouse: Warehouse): void {
+ this.selectedWarehouse = warehouse;
+ this.loadInventory(warehouse.id);
+ }
+
+ loadInventory(warehouseId: number): void {
+ this.inventoryLoading = true;
+ this.warehouseService.getWarehouseInventory(warehouseId).subscribe({
+ next: (data) => {
+ this.inventoryData = data;
+ this.inventoryProducts = data.inventory_product_details;
+ this.filteredInventoryProducts = [...this.inventoryProducts];
+ this.inventoryLoading = false;
+ },
+ error: (error) => {
+ console.error('Error loading inventory', error);
+ this.inventoryLoading = false;
+ }
+ });
+ }
+
+ backToWarehouses(): void {
+ this.selectedWarehouse = null;
+ this.inventoryData = null;
+ this.inventoryProducts = [];
+ }
+
+ filterWarehouses(): void {
+ if (!this.searchQuery.trim()) {
+ this.filteredWarehouses = [...this.warehouses];
+ return;
+ }
+
+ const query = this.searchQuery.toLowerCase();
+ this.filteredWarehouses = this.warehouses.filter(warehouse =>
+ warehouse.warehouse_name.toLowerCase().includes(query) ||
+ warehouse.location_x.toLowerCase().includes(query) ||
+ warehouse.location_y.toLowerCase().includes(query)
+ );
+ }
+
+ filterInventory(): void {
+ if (!this.inventorySearchQuery.trim()) {
+ this.filteredInventoryProducts = [...this.inventoryProducts];
+ return;
+ }
+
+ const query = this.inventorySearchQuery.toLowerCase();
+ this.filteredInventoryProducts = this.inventoryProducts.filter(item =>
+ item.product_name.toLowerCase().includes(query) ||
+ item.category.toLowerCase().includes(query) ||
+ item.supplied_by.toLowerCase().includes(query)
+ );
+ }
+
+ formatDate(dateString: string): string {
+ return new Date(dateString).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric'
+ });
+ }
+
+ formatNumber(value: number): string {
+ return value.toLocaleString();
+ }
+}
\ No newline at end of file
diff --git a/src/app/components/home-page/product-section/product-section.component.html b/src/app/components/home-page/product-section/product-section.component.html
index b68850d..59291f6 100644
--- a/src/app/components/home-page/product-section/product-section.component.html
+++ b/src/app/components/home-page/product-section/product-section.component.html
@@ -102,6 +102,7 @@
@@ -110,7 +111,7 @@