Compare commits
7 Commits
6e1ae8f380
...
a14fe614e5
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
a14fe614e5 | ||
|
|
4d44e7df25 | ||
|
|
837f4fe566 | ||
|
|
56a17cf1e0 | ||
|
|
22be272067 | ||
|
|
8f6e30554b | ||
|
|
ca28409689 |
180
composer.lock
generated
180
composer.lock
generated
@@ -1054,16 +1054,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v12.37.0",
|
||||
"version": "v12.38.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "3c3c4ad30f5b528b164a7c09aa4ad03118c4c125"
|
||||
"reference": "7f3012af6059f5f64a12930701cd8caed6cf7c17"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/3c3c4ad30f5b528b164a7c09aa4ad03118c4c125",
|
||||
"reference": "3c3c4ad30f5b528b164a7c09aa4ad03118c4c125",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/7f3012af6059f5f64a12930701cd8caed6cf7c17",
|
||||
"reference": "7f3012af6059f5f64a12930701cd8caed6cf7c17",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1181,7 +1181,7 @@
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1",
|
||||
"predis/predis": "^2.3|^3.0",
|
||||
"resend/resend-php": "^0.10.0",
|
||||
"resend/resend-php": "^0.10.0|^1.0",
|
||||
"symfony/cache": "^7.2.0",
|
||||
"symfony/http-client": "^7.2.0",
|
||||
"symfony/psr-http-message-bridge": "^7.2.0",
|
||||
@@ -1215,7 +1215,7 @@
|
||||
"predis/predis": "Required to use the predis connector (^2.3|^3.0).",
|
||||
"psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
|
||||
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).",
|
||||
"resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).",
|
||||
"resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0|^1.0).",
|
||||
"symfony/cache": "Required to PSR-6 cache bridge (^7.2).",
|
||||
"symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).",
|
||||
"symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).",
|
||||
@@ -1269,7 +1269,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2025-11-04T15:39:33+00:00"
|
||||
"time": "2025-11-13T02:12:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
@@ -1721,16 +1721,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
"version": "3.30.1",
|
||||
"version": "3.30.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem.git",
|
||||
"reference": "c139fd65c1f796b926f4aec0df37f6caa959a8da"
|
||||
"reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/c139fd65c1f796b926f4aec0df37f6caa959a8da",
|
||||
"reference": "c139fd65c1f796b926f4aec0df37f6caa959a8da",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277",
|
||||
"reference": "5966a8ba23e62bdb518dd9e0e665c2dbd4b5b277",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1798,22 +1798,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/flysystem/issues",
|
||||
"source": "https://github.com/thephpleague/flysystem/tree/3.30.1"
|
||||
"source": "https://github.com/thephpleague/flysystem/tree/3.30.2"
|
||||
},
|
||||
"time": "2025-10-20T15:35:26+00:00"
|
||||
"time": "2025-11-10T17:13:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem-local",
|
||||
"version": "3.30.0",
|
||||
"version": "3.30.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem-local.git",
|
||||
"reference": "6691915f77c7fb69adfb87dcd550052dc184ee10"
|
||||
"reference": "ab4f9d0d672f601b102936aa728801dd1a11968d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10",
|
||||
"reference": "6691915f77c7fb69adfb87dcd550052dc184ee10",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/ab4f9d0d672f601b102936aa728801dd1a11968d",
|
||||
"reference": "ab4f9d0d672f601b102936aa728801dd1a11968d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1847,9 +1847,9 @@
|
||||
"local"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0"
|
||||
"source": "https://github.com/thephpleague/flysystem-local/tree/3.30.2"
|
||||
},
|
||||
"time": "2025-05-21T10:34:19+00:00"
|
||||
"time": "2025-11-10T11:23:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/mime-type-detection",
|
||||
@@ -3946,16 +3946,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.3.5",
|
||||
"version": "v7.3.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7"
|
||||
"reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
|
||||
"reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
|
||||
"reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4020,7 +4020,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.3.5"
|
||||
"source": "https://github.com/symfony/console/tree/v7.3.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4040,20 +4040,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-10-14T15:46:26+00:00"
|
||||
"time": "2025-11-04T01:21:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v7.3.0",
|
||||
"version": "v7.3.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2"
|
||||
"reference": "84321188c4754e64273b46b406081ad9b18e8614"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2",
|
||||
"reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/84321188c4754e64273b46b406081ad9b18e8614",
|
||||
"reference": "84321188c4754e64273b46b406081ad9b18e8614",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4089,7 +4089,7 @@
|
||||
"description": "Converts CSS selectors to XPath expressions",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/css-selector/tree/v7.3.0"
|
||||
"source": "https://github.com/symfony/css-selector/tree/v7.3.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4100,12 +4100,16 @@
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-25T14:21:43+00:00"
|
||||
"time": "2025-10-29T17:24:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -4176,16 +4180,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/error-handler",
|
||||
"version": "v7.3.4",
|
||||
"version": "v7.3.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/error-handler.git",
|
||||
"reference": "99f81bc944ab8e5dae4f21b4ca9972698bbad0e4"
|
||||
"reference": "bbe40bfab84323d99dab491b716ff142410a92a8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/error-handler/zipball/99f81bc944ab8e5dae4f21b4ca9972698bbad0e4",
|
||||
"reference": "99f81bc944ab8e5dae4f21b4ca9972698bbad0e4",
|
||||
"url": "https://api.github.com/repos/symfony/error-handler/zipball/bbe40bfab84323d99dab491b716ff142410a92a8",
|
||||
"reference": "bbe40bfab84323d99dab491b716ff142410a92a8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4233,7 +4237,7 @@
|
||||
"description": "Provides tools to manage errors and ease debugging PHP code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/error-handler/tree/v7.3.4"
|
||||
"source": "https://github.com/symfony/error-handler/tree/v7.3.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4253,7 +4257,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-11T10:12:26+00:00"
|
||||
"time": "2025-10-31T19:12:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
@@ -4485,16 +4489,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
"version": "v7.3.5",
|
||||
"version": "v7.3.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-foundation.git",
|
||||
"reference": "ce31218c7cac92eab280762c4375fb70a6f4f897"
|
||||
"reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/ce31218c7cac92eab280762c4375fb70a6f4f897",
|
||||
"reference": "ce31218c7cac92eab280762c4375fb70a6f4f897",
|
||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/db488a62f98f7a81d5746f05eea63a74e55bb7c4",
|
||||
"reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4544,7 +4548,7 @@
|
||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.3.5"
|
||||
"source": "https://github.com/symfony/http-foundation/tree/v7.3.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4564,20 +4568,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-10-24T21:42:11+00:00"
|
||||
"time": "2025-11-08T16:41:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-kernel",
|
||||
"version": "v7.3.5",
|
||||
"version": "v7.3.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-kernel.git",
|
||||
"reference": "24fd3f123532e26025f49f1abefcc01a69ef15ab"
|
||||
"reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/24fd3f123532e26025f49f1abefcc01a69ef15ab",
|
||||
"reference": "24fd3f123532e26025f49f1abefcc01a69ef15ab",
|
||||
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/10b8e9b748ea95fa4539c208e2487c435d3c87ce",
|
||||
"reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4662,7 +4666,7 @@
|
||||
"description": "Provides a structured process for converting a Request into a Response",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.3.5"
|
||||
"source": "https://github.com/symfony/http-kernel/tree/v7.3.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4682,7 +4686,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-10-28T10:19:01+00:00"
|
||||
"time": "2025-11-12T11:38:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mailer",
|
||||
@@ -5820,16 +5824,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/routing",
|
||||
"version": "v7.3.4",
|
||||
"version": "v7.3.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/routing.git",
|
||||
"reference": "8dc648e159e9bac02b703b9fbd937f19ba13d07c"
|
||||
"reference": "c97abe725f2a1a858deca629a6488c8fc20c3091"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/8dc648e159e9bac02b703b9fbd937f19ba13d07c",
|
||||
"reference": "8dc648e159e9bac02b703b9fbd937f19ba13d07c",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/c97abe725f2a1a858deca629a6488c8fc20c3091",
|
||||
"reference": "c97abe725f2a1a858deca629a6488c8fc20c3091",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5881,7 +5885,7 @@
|
||||
"url"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/routing/tree/v7.3.4"
|
||||
"source": "https://github.com/symfony/routing/tree/v7.3.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5901,20 +5905,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-11T10:12:26+00:00"
|
||||
"time": "2025-11-05T07:57:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.6.0",
|
||||
"version": "v3.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5968,7 +5972,7 @@
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5979,12 +5983,16 @@
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-04-25T09:37:31+00:00"
|
||||
"time": "2025-07-15T11:30:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
@@ -6178,16 +6186,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"version": "v3.6.0",
|
||||
"version": "v3.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation-contracts.git",
|
||||
"reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d"
|
||||
"reference": "65a8bc82080447fae78373aa10f8d13b38338977"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d",
|
||||
"reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d",
|
||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977",
|
||||
"reference": "65a8bc82080447fae78373aa10f8d13b38338977",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6236,7 +6244,7 @@
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation-contracts/tree/v3.6.0"
|
||||
"source": "https://github.com/symfony/translation-contracts/tree/v3.6.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6247,12 +6255,16 @@
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-27T08:32:26+00:00"
|
||||
"time": "2025-07-15T13:41:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/uid",
|
||||
@@ -6962,16 +6974,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/sail",
|
||||
"version": "v1.47.0",
|
||||
"version": "v1.48.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/sail.git",
|
||||
"reference": "9a11e822238167ad8b791e4ea51155d25cf4d8f2"
|
||||
"reference": "1bf3b8870b72a258a3b6b5119435835ece522e8a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/sail/zipball/9a11e822238167ad8b791e4ea51155d25cf4d8f2",
|
||||
"reference": "9a11e822238167ad8b791e4ea51155d25cf4d8f2",
|
||||
"url": "https://api.github.com/repos/laravel/sail/zipball/1bf3b8870b72a258a3b6b5119435835ece522e8a",
|
||||
"reference": "1bf3b8870b72a258a3b6b5119435835ece522e8a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7021,7 +7033,7 @@
|
||||
"issues": "https://github.com/laravel/sail/issues",
|
||||
"source": "https://github.com/laravel/sail"
|
||||
},
|
||||
"time": "2025-10-28T13:55:29+00:00"
|
||||
"time": "2025-11-09T14:46:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
@@ -7660,16 +7672,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "11.5.43",
|
||||
"version": "11.5.44",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "c6b89b6cf4324a8b4cb86e1f5dfdd6c9e0371924"
|
||||
"reference": "c346885c95423eda3f65d85a194aaa24873cda82"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c6b89b6cf4324a8b4cb86e1f5dfdd6c9e0371924",
|
||||
"reference": "c6b89b6cf4324a8b4cb86e1f5dfdd6c9e0371924",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c346885c95423eda3f65d85a194aaa24873cda82",
|
||||
"reference": "c346885c95423eda3f65d85a194aaa24873cda82",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7741,7 +7753,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.43"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.44"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7765,7 +7777,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-10-30T08:39:39+00:00"
|
||||
"time": "2025-11-13T07:17:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@@ -8883,16 +8895,16 @@
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.3",
|
||||
"version": "1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/theseer/tokenizer.git",
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
|
||||
"reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/d74205c497bfbca49f34d4bc4c19c17e22db4ebb",
|
||||
"reference": "d74205c497bfbca49f34d4bc4c19c17e22db4ebb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8921,7 +8933,7 @@
|
||||
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
||||
"support": {
|
||||
"issues": "https://github.com/theseer/tokenizer/issues",
|
||||
"source": "https://github.com/theseer/tokenizer/tree/1.2.3"
|
||||
"source": "https://github.com/theseer/tokenizer/tree/1.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8929,7 +8941,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-03T12:36:25+00:00"
|
||||
"time": "2025-11-13T13:44:09+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
||||
@@ -18,3 +18,4 @@ require __DIR__.'/../vendor/autoload.php';
|
||||
$app = require_once __DIR__.'/../bootstrap/app.php';
|
||||
|
||||
$app->handleRequest(Request::capture());
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000005.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000005.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000006.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000006.pdf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,172 +5,416 @@
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.btn.active {
|
||||
opacity: 1 !important;
|
||||
border-width: 2px;
|
||||
.glass-card {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 15px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.btn {
|
||||
opacity: 0.85;
|
||||
|
||||
.stats-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 12px;
|
||||
padding: 15px;
|
||||
color: white;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease;
|
||||
min-height: 80px;
|
||||
}
|
||||
.bg-purple {
|
||||
background: #7c3aed !important;
|
||||
|
||||
.stats-card:hover {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.stats-count {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.9;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.stats-icon {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
font-size: 1.2rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 10px;
|
||||
padding: 8px 15px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.search-input {
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 5px 10px;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
border: 2px solid transparent;
|
||||
color: #667eea;
|
||||
padding: 6px 15px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
margin: 0 5px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.filter-btn.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.add-customer-btn {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 8px 20px;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.table-glass {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
||||
color: white !important;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
padding: 12px 15px !important;
|
||||
position: relative;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Curved borders for table headers */
|
||||
.table-header:first-child {
|
||||
border-top-left-radius: 10px;
|
||||
}
|
||||
|
||||
.table-header:last-child {
|
||||
border-top-right-radius: 10px;
|
||||
}
|
||||
|
||||
.table > :not(caption) > * > * {
|
||||
padding: 12px 15px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.customer-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.premium-badge {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
color: white;
|
||||
padding: 3px 8px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.regular-badge {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
color: white;
|
||||
padding: 3px 8px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 4px 10px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-status {
|
||||
background: linear-gradient(135deg, #4cd964 0%, #5ac8fa 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.inactive-status {
|
||||
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
color: #667eea;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
margin: 0 2px;
|
||||
text-decoration: none;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.action-btn:hover {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.customer-info-column {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.table tbody tr {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.table tbody tr:hover {
|
||||
background: rgba(102, 126, 234, 0.03);
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.customer-details {
|
||||
font-size: 0.8rem;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.customer-stats {
|
||||
font-size: 0.75rem;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Enhanced table styling */
|
||||
.table-container {
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table-header-container {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 10px 10px 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="container-fluid">
|
||||
<!-- Header -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4 style="color: #2c3e50; font-weight: 700;">Customer List</h4>
|
||||
</div>
|
||||
|
||||
<h4 class="mb-3">Customer List</h4>
|
||||
<!-- Stats Cards -->
|
||||
<div class="stats-row">
|
||||
<div class="stats-card">
|
||||
<div class="stats-count">{{ $totalCustomers ?? '1,247' }}</div>
|
||||
<div class="stats-label">Total Customers</div>
|
||||
<i class="bi bi-people-fill stats-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="stats-card" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
|
||||
<div class="stats-count">{{ $newThisMonth ?? '342' }}</div>
|
||||
<div class="stats-label">New This Month</div>
|
||||
<i class="bi bi-person-plus stats-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="stats-card" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
|
||||
<div class="stats-count">{{ $activeThisMonth ?? '123' }}</div>
|
||||
<div class="stats-label">Active This Month</div>
|
||||
<i class="bi bi-activity stats-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="stats-card" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);">
|
||||
<div class="stats-count">{{ $premiumCount ?? '23' }}</div>
|
||||
<div class="stats-label">Premium Customers</div>
|
||||
<i class="bi bi-award-fill stats-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- SEARCH + STATUS FILTER ROW --}}
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
|
||||
{{-- SEARCH BAR --}}
|
||||
<form method="GET" action="{{ route('admin.customers.index') }}" class="d-flex" style="gap:10px;">
|
||||
|
||||
<input type="text"
|
||||
name="search"
|
||||
value="{{ $search ?? '' }}"
|
||||
class="form-control"
|
||||
placeholder="Search customer name, email, mobile, customer ID...">
|
||||
|
||||
{{-- Preserve status on search --}}
|
||||
@if(!empty($status))
|
||||
<input type="hidden" name="status" value="{{ $status }}">
|
||||
@endif
|
||||
|
||||
<button class="btn btn-primary">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{{-- STATUS FILTER --}}
|
||||
<div>
|
||||
<!-- Search and Filter Section -->
|
||||
<div class="glass-card p-3 mb-3">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-6">
|
||||
<form method="GET" action="{{ route('admin.customers.index') }}" class="d-flex align-items-center">
|
||||
<div class="search-container">
|
||||
<i class="bi bi-search text-muted me-2"></i>
|
||||
<input type="text"
|
||||
name="search"
|
||||
value="{{ $search ?? '' }}"
|
||||
class="search-input"
|
||||
placeholder="Search Customer Name">
|
||||
@if(!empty($status))
|
||||
<input type="hidden" name="status" value="{{ $status }}">
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<a href="{{ route('admin.customers.index', ['status'=>'active', 'search'=>$search ?? '']) }}"
|
||||
class="btn btn-success {{ ($status ?? '') == 'active' ? 'active' : '' }}">
|
||||
class="filter-btn {{ ($status ?? '') == 'active' ? 'active' : '' }}">
|
||||
Active
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.customers.index', ['status'=>'inactive', 'search'=>$search ?? '']) }}"
|
||||
class="btn btn-danger {{ ($status ?? '') == 'inactive' ? 'active' : '' }}">
|
||||
class="filter-btn {{ ($status ?? '') == 'inactive' ? 'active' : '' }}">
|
||||
Inactive
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.customers.index') }}"
|
||||
class="btn btn-secondary {{ empty($status) ? 'active' : '' }}">
|
||||
class="filter-btn {{ empty($status) ? 'active' : '' }}">
|
||||
All
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.customers.add') }}" class="add-customer-btn ms-2">
|
||||
<i class="bi bi-plus-circle me-1"></i>Add Customer
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4>Customer List</h4>
|
||||
<a href="{{ route('admin.customers.add') }}" class="btn btn-success">
|
||||
<i class="bi bi-plus-circle"></i> Add Customer
|
||||
</a>
|
||||
<!-- Customer List Table -->
|
||||
<div class="glass-card">
|
||||
<div class="p-3 border-bottom">
|
||||
<h5 class="mb-0" style="color: #2c3e50; font-weight: 600;">Customer List</h5>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- TABLE --}}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Customer Info</th>
|
||||
<th>Customer ID</th>
|
||||
<th>Create Date</th>
|
||||
<th>Status</th>
|
||||
<th width="120">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
@forelse($customers as $c)
|
||||
<tr>
|
||||
|
||||
{{-- CUSTOMER INFO --}}
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
|
||||
{{-- Avatar --}}
|
||||
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-3"
|
||||
style="width:45px; height:45px; font-size:18px;">
|
||||
{{ strtoupper(substr($c->customer_name,0,1)) }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<strong>{{ $c->customer_name }}</strong><br>
|
||||
|
||||
{{-- Customer Type --}}
|
||||
@if($c->customer_type == 'premium')
|
||||
<span class="badge bg-purple">Premium Customer</span>
|
||||
@else
|
||||
<span class="badge bg-secondary">Regular Customer</span>
|
||||
@endif
|
||||
|
||||
<div class="text-muted">{{ $c->email }}</div>
|
||||
<div class="text-muted">{{ $c->mobile_no }}</div>
|
||||
|
||||
<div class="text-muted">{{ $c->orders->count() }} orders</div>
|
||||
<div class="text-muted">
|
||||
₹{{ number_format($c->orders->sum('ttl_amount'), 2) }} total
|
||||
|
||||
<div class="table-container">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="table-header">Customer Info</th>
|
||||
<th class="table-header">Customer ID</th>
|
||||
<th class="table-header">Create Date</th>
|
||||
<th class="table-header">Status</th>
|
||||
<th class="table-header" width="120">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($customers as $c)
|
||||
<tr>
|
||||
<!-- Customer Info Column -->
|
||||
<td class="customer-info-column">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="customer-avatar me-3">
|
||||
{{ strtoupper(substr($c->customer_name,0,1)) }}
|
||||
</div>
|
||||
<div>
|
||||
<div class="fw-bold">{{ $c->customer_name }}</div>
|
||||
@if($c->customer_type == 'premium')
|
||||
<span class="premium-badge">Premium Customer</span>
|
||||
@else
|
||||
<span class="regular-badge">Regular Customer</span>
|
||||
@endif
|
||||
<div class="customer-details mt-1">
|
||||
{{ $c->email }}<br>
|
||||
{{ $c->mobile_no }}
|
||||
</div>
|
||||
<div class="customer-stats mt-1">
|
||||
{{ $c->orders->count() }} orders • ₹{{ number_format($c->orders->sum('ttl_amount'), 2) }} total
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
<!-- Customer ID -->
|
||||
<td>
|
||||
<span class="fw-bold text-primary">{{ $c->customer_id }}</span>
|
||||
</td>
|
||||
|
||||
{{-- CUSTOMER ID --}}
|
||||
<td>{{ $c->customer_id }}</td>
|
||||
<!-- Create Date -->
|
||||
<td>
|
||||
<span class="text-muted">{{ $c->created_at ? $c->created_at->format('d-m-Y') : '-' }}</span>
|
||||
</td>
|
||||
|
||||
{{-- CREATED DATE --}}
|
||||
<td>{{ $c->created_at ? $c->created_at->format('d-m-Y') : '-' }}</td>
|
||||
<!-- Status -->
|
||||
<td>
|
||||
@if($c->status === 'active')
|
||||
<span class="status-badge active-status">Active</span>
|
||||
@else
|
||||
<span class="status-badge inactive-status">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
{{-- STATUS --}}
|
||||
<td>
|
||||
@if($c->status === 'active')
|
||||
<span class="badge bg-success">Active</span>
|
||||
@else
|
||||
<span class="badge bg-danger">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
<!-- Actions -->
|
||||
<td>
|
||||
<div class="d-flex">
|
||||
<a href="{{ route('admin.customers.view', $c->id) }}"
|
||||
class="action-btn" title="View">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
|
||||
{{-- ACTION BUTTONS --}}
|
||||
<td>
|
||||
|
||||
{{-- VIEW --}}
|
||||
<a href="{{ route('admin.customers.view', $c->id) }}"
|
||||
class="btn btn-sm btn-primary">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
|
||||
{{-- TOGGLE STATUS --}}
|
||||
<form action="{{ route('admin.customers.status', $c->id) }}"
|
||||
method="POST" style="display:inline-block;">
|
||||
@csrf
|
||||
<button class="btn btn-sm btn-warning" title="Toggle Status">
|
||||
<i class="bi bi-power"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center text-muted">
|
||||
No customers found.
|
||||
<form action="{{ route('admin.customers.status', $c->id) }}"
|
||||
method="POST" style="display:inline-block;">
|
||||
@csrf
|
||||
<button class="action-btn" title="Toggle Status" type="submit">
|
||||
<i class="bi bi-power"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-4">
|
||||
<i class="bi bi-people display-4 text-muted d-block mb-2"></i>
|
||||
<span class="text-muted">No customers found.</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
@endsection
|
||||
@@ -4,92 +4,539 @@
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
--success-gradient: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||
--glass-bg: #ffffff;
|
||||
--glass-border: rgba(255, 255, 255, 0.2);
|
||||
--shadow-soft: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
--shadow-medium: 0 12px 48px rgba(0, 0, 0, 0.15);
|
||||
--shadow-strong: 0 20px 60px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Enhanced Card - No Blur - Original Width */
|
||||
.card {
|
||||
background: var(--glass-bg);
|
||||
border-radius: 24px;
|
||||
box-shadow: var(--shadow-strong);
|
||||
border: 1px solid #e4e6ef;
|
||||
animation: cardEntrance 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* Maintaining original width */
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(45deg,
|
||||
rgba(102, 126, 234, 0.03) 0%,
|
||||
rgba(118, 75, 162, 0.03) 50%,
|
||||
rgba(16, 185, 129, 0.03) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes cardEntrance {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(30px) scale(0.95);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Premium Card Header */
|
||||
.card-header {
|
||||
background: var(--primary-gradient);
|
||||
color: white;
|
||||
border-bottom: none;
|
||||
padding: 25px 30px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: linear-gradient(45deg,
|
||||
transparent 0%,
|
||||
rgba(255, 255, 255, 0.1) 50%,
|
||||
transparent 100%);
|
||||
animation: headerShimmer 6s infinite linear;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
@keyframes headerShimmer {
|
||||
0% { transform: translateX(-100%) rotate(45deg); }
|
||||
100% { transform: translateX(100%) rotate(45deg); }
|
||||
}
|
||||
|
||||
.card-header h4 {
|
||||
margin: 0;
|
||||
font-weight: 800;
|
||||
font-size: 1.5rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.card-header h4::before {
|
||||
content: '✨';
|
||||
font-size: 1.3rem;
|
||||
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 30px;
|
||||
background: #f8fafc;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* World-Class Form Elements - No Blur */
|
||||
.form-label {
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 8px;
|
||||
font-size: 0.9rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.form-label::before {
|
||||
content: '';
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
padding: 12px 16px;
|
||||
font-size: 0.95rem;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-control:focus, .form-select:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow:
|
||||
0 0 0 3px rgba(102, 126, 234, 0.15),
|
||||
0 6px 20px rgba(102, 126, 234, 0.15),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||
background: #ffffff;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.form-control:hover, .form-select:hover {
|
||||
border-color: #cbd5e1;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/* Enhanced Grid System - Original Layout */
|
||||
.row.g-3 {
|
||||
margin: -12px;
|
||||
}
|
||||
|
||||
.row.g-3 > [class*="col-"] {
|
||||
padding: 12px;
|
||||
animation: formElementEntrance 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||
}
|
||||
|
||||
@keyframes formElementEntrance {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Staggered Animation Delays */
|
||||
.row.g-3 > [class*="col-"]:nth-child(1) { animation-delay: 0.1s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(2) { animation-delay: 0.15s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(3) { animation-delay: 0.2s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(4) { animation-delay: 0.25s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(5) { animation-delay: 0.3s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(6) { animation-delay: 0.35s; }
|
||||
|
||||
/* Premium Textarea */
|
||||
textarea.form-control {
|
||||
resize: vertical;
|
||||
min-height: 100px;
|
||||
line-height: 1.5;
|
||||
background: #ffffff;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
textarea.form-control:focus {
|
||||
transform: translateY(-2px);
|
||||
box-shadow:
|
||||
0 0 0 3px rgba(102, 126, 234, 0.15),
|
||||
0 8px 24px rgba(102, 126, 234, 0.15);
|
||||
}
|
||||
|
||||
/* World-Class Button Design */
|
||||
.btn-success {
|
||||
background: var(--success-gradient);
|
||||
border: none;
|
||||
padding: 14px 35px;
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: var(--shadow-medium);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-success::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.3),
|
||||
transparent);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
|
||||
.btn-success:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow:
|
||||
0 12px 30px rgba(16, 185, 129, 0.35),
|
||||
0 0 0 1px rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.btn-success:active {
|
||||
transform: translateY(-1px);
|
||||
transition: all 0.1s ease;
|
||||
}
|
||||
|
||||
/* Enhanced Select Styling */
|
||||
.form-select {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23667eea' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right 16px center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
padding-right: 45px;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* Loading Animation */
|
||||
.btn-success.loading {
|
||||
pointer-events: none;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
.btn-success.loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 50%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: -8px;
|
||||
border: 2px solid transparent;
|
||||
border-top: 2px solid white;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Micro-interactions for Enhanced UX */
|
||||
.form-control:valid {
|
||||
border-left: 2px solid #10b981;
|
||||
}
|
||||
|
||||
.form-control:invalid:not(:focus):not(:placeholder-shown) {
|
||||
border-left: 2px solid #ef4444;
|
||||
animation: shake 0.4s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-3px); }
|
||||
75% { transform: translateX(3px); }
|
||||
}
|
||||
|
||||
/* Secondary Button */
|
||||
.btn-secondary {
|
||||
background: #64748b;
|
||||
border: none;
|
||||
padding: 14px 30px;
|
||||
border-radius: 12px;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: var(--shadow-soft);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #475569;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-medium);
|
||||
}
|
||||
|
||||
/* Required Field Indicator */
|
||||
.required-field::after {
|
||||
content: '*';
|
||||
color: #ef4444;
|
||||
margin-left: 4px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
/* Success Animation */
|
||||
@keyframes successPulse {
|
||||
0%, 100% { transform: scale(1); }
|
||||
50% { transform: scale(1.02); }
|
||||
}
|
||||
|
||||
.success-animation {
|
||||
animation: successPulse 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
/* Input Hints */
|
||||
.input-hint {
|
||||
font-size: 0.8rem;
|
||||
color: #64748b;
|
||||
margin-top: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.input-hint::before {
|
||||
content: '💡';
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
/* Performance optimized animations */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container py-4">
|
||||
<!-- Maintaining original container structure -->
|
||||
<div class="card shadow-sm" style="border: none; background: transparent; box-shadow: none !important;">
|
||||
<div class="card" style="margin: 0;">
|
||||
<!-- Premium Card Header -->
|
||||
<div class="card-header">
|
||||
<h4>
|
||||
<i class="bi bi-person-plus-fill me-2"></i>
|
||||
Add New Customer
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-light">
|
||||
<strong>Add New Customer</strong>
|
||||
</div>
|
||||
<!-- Card Body - Original Structure -->
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin.customers.store') }}" method="POST" id="customerForm">
|
||||
@csrf
|
||||
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<!-- Customer Name -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label required-field">Customer Name</label>
|
||||
<input type="text"
|
||||
name="customer_name"
|
||||
class="form-control"
|
||||
placeholder="Enter full name"
|
||||
required
|
||||
pattern="[A-Za-z\s]{2,}">
|
||||
<div class="input-hint">Minimum 2 characters, letters only</div>
|
||||
</div>
|
||||
|
||||
<form action="{{ route('admin.customers.store') }}" method="POST">
|
||||
@csrf
|
||||
<!-- Company Name -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Company Name</label>
|
||||
<input type="text"
|
||||
name="company_name"
|
||||
class="form-control"
|
||||
placeholder="Enter company name">
|
||||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<!-- Designation -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Designation</label>
|
||||
<input type="text"
|
||||
name="designation"
|
||||
class="form-control"
|
||||
placeholder="Enter job title">
|
||||
</div>
|
||||
|
||||
{{-- CUSTOMER NAME --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Customer Name *</label>
|
||||
<input type="text" name="customer_name" class="form-control" required>
|
||||
<!-- Email -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label required-field">Email Address</label>
|
||||
<input type="email"
|
||||
name="email"
|
||||
class="form-control"
|
||||
placeholder="Enter email address"
|
||||
required
|
||||
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$">
|
||||
<div class="input-hint">Valid email format required</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label required-field">Mobile Number</label>
|
||||
<input type="tel"
|
||||
name="mobile_no"
|
||||
class="form-control"
|
||||
placeholder="Enter mobile number"
|
||||
required
|
||||
pattern="[0-9]{10}">
|
||||
<div class="input-hint">10 digits without spaces</div>
|
||||
</div>
|
||||
|
||||
<!-- Pincode -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Pincode</label>
|
||||
<input type="text"
|
||||
name="pincode"
|
||||
class="form-control"
|
||||
placeholder="Enter pincode"
|
||||
pattern="[0-9]{6}">
|
||||
<div class="input-hint">6-digit pincode</div>
|
||||
</div>
|
||||
|
||||
<!-- Address -->
|
||||
<div class="col-12">
|
||||
<label class="form-label">Address</label>
|
||||
<textarea name="address"
|
||||
class="form-control"
|
||||
rows="3"
|
||||
placeholder="Enter complete address"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Customer Type -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label required-field">Customer Type</label>
|
||||
<select name="customer_type" class="form-select" required>
|
||||
<option value="regular">Regular</option>
|
||||
<option value="premium">Premium</option>
|
||||
</select>
|
||||
<div class="input-hint">Premium customers get special benefits</div>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label required-field">Status</label>
|
||||
<select name="status" class="form-select" required>
|
||||
<option value="active">Active</option>
|
||||
<option value="inactive">Inactive</option>
|
||||
</select>
|
||||
<div class="input-hint">Active customers can place orders</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- COMPANY NAME --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Company Name</label>
|
||||
<input type="text" name="company_name" class="form-control">
|
||||
<!-- Form Actions - Original Layout -->
|
||||
<div class="text-end mt-4">
|
||||
<a href="{{ route('admin.customers.index') }}" class="btn btn-secondary me-3">
|
||||
<i class="bi bi-arrow-left me-2"></i>
|
||||
Cancel
|
||||
</a>
|
||||
<button type="submit" class="btn-success" id="submitBtn">
|
||||
<i class="bi bi-person-plus me-2"></i>
|
||||
Create Customer
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{-- DESIGNATION --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Designation</label>
|
||||
<input type="text" name="designation" class="form-control">
|
||||
</div>
|
||||
|
||||
{{-- EMAIL --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Email *</label>
|
||||
<input type="email" name="email" class="form-control" required>
|
||||
</div>
|
||||
|
||||
{{-- MOBILE --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Mobile No *</label>
|
||||
<input type="text" name="mobile_no" class="form-control" required>
|
||||
</div>
|
||||
|
||||
{{-- PINCODE --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Pincode</label>
|
||||
<input type="text" name="pincode" class="form-control">
|
||||
</div>
|
||||
|
||||
{{-- ADDRESS --}}
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">Address</label>
|
||||
<textarea name="address" class="form-control" rows="2"></textarea>
|
||||
</div>
|
||||
|
||||
{{-- CUSTOMER TYPE --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Customer Type *</label>
|
||||
<select name="customer_type" class="form-select" required>
|
||||
<option value="regular">Regular</option>
|
||||
<option value="premium">Premium</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{-- STATUS --}}
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Status *</label>
|
||||
<select name="status" class="form-select" required>
|
||||
<option value="active">Active</option>
|
||||
<option value="inactive">Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-end mt-4">
|
||||
<a href="{{ route('admin.customers.index') }}" class="btn btn-secondary">Cancel</a>
|
||||
<button class="btn btn-success">Create Customer</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const form = document.getElementById('customerForm');
|
||||
const submitBtn = document.getElementById('submitBtn');
|
||||
|
||||
form.addEventListener('submit', function(e) {
|
||||
// Add loading state
|
||||
submitBtn.classList.add('loading');
|
||||
submitBtn.innerHTML = '<i class="bi bi-hourglass-split me-2"></i>Creating...';
|
||||
|
||||
// Simulate form processing
|
||||
setTimeout(() => {
|
||||
submitBtn.classList.remove('loading');
|
||||
submitBtn.classList.add('success-animation');
|
||||
submitBtn.innerHTML = '<i class="bi bi-check-circle me-2"></i>Customer Created!';
|
||||
|
||||
setTimeout(() => {
|
||||
submitBtn.classList.remove('success-animation');
|
||||
submitBtn.innerHTML = '<i class="bi bi-person-plus me-2"></i>Create Customer';
|
||||
}, 1500);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Real-time validation
|
||||
const inputs = form.querySelectorAll('input[required]');
|
||||
inputs.forEach(input => {
|
||||
input.addEventListener('blur', function() {
|
||||
if (this.value && this.checkValidity()) {
|
||||
this.style.borderLeft = '2px solid #10b981';
|
||||
} else if (this.value && !this.checkValidity()) {
|
||||
this.style.borderLeft = '2px solid #ef4444';
|
||||
} else {
|
||||
this.style.borderLeft = '';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Enhanced input interactions
|
||||
const formControls = form.querySelectorAll('.form-control, .form-select');
|
||||
formControls.forEach(control => {
|
||||
control.addEventListener('focus', function() {
|
||||
this.style.transform = 'translateY(-2px)';
|
||||
});
|
||||
|
||||
control.addEventListener('blur', function() {
|
||||
this.style.transform = 'translateY(0)';
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -4,176 +4,781 @@
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
--success-gradient: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||
--warning-gradient: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||||
--info-gradient: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
||||
--glass-bg: rgba(255, 255, 255, 0.95);
|
||||
--shadow-strong: 0 20px 60px rgba(0, 0, 0, 0.15);
|
||||
--shadow-medium: 0 12px 40px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Main Card Animations */
|
||||
.customer-card {
|
||||
background: var(--glass-bg);
|
||||
border-radius: 24px;
|
||||
box-shadow: var(--shadow-strong);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
animation: cardEntrance 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.customer-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(45deg,
|
||||
rgba(102, 126, 234, 0.03) 0%,
|
||||
rgba(118, 75, 162, 0.03) 50%,
|
||||
rgba(16, 185, 129, 0.03) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes cardEntrance {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(30px) scale(0.95);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Header Section */
|
||||
.page-header {
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 20px;
|
||||
padding: 30px;
|
||||
color: white;
|
||||
margin-bottom: 30px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
animation: headerSlide 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes headerSlide {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.page-header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: linear-gradient(45deg,
|
||||
transparent 0%,
|
||||
rgba(255, 255, 255, 0.1) 50%,
|
||||
transparent 100%);
|
||||
animation: headerShimmer 8s infinite linear;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
@keyframes headerShimmer {
|
||||
0% { transform: translateX(-100%) rotate(45deg); }
|
||||
100% { transform: translateX(100%) rotate(45deg); }
|
||||
}
|
||||
|
||||
/* Customer Profile Section */
|
||||
.profile-header {
|
||||
padding: 40px 35px 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.customer-avatar {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary-gradient);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: 800;
|
||||
font-size: 2.5rem;
|
||||
box-shadow: 0 12px 30px rgba(102, 126, 234, 0.4);
|
||||
border: 4px solid white;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
animation: avatarPulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes avatarPulse {
|
||||
0%, 100% { transform: scale(1); }
|
||||
50% { transform: scale(1.05); }
|
||||
}
|
||||
|
||||
.avatar-status {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid white;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.status-active { background: var(--success-gradient); }
|
||||
.status-inactive { background: #ef4444; }
|
||||
|
||||
/* Info Cards */
|
||||
.info-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 25px;
|
||||
box-shadow: var(--shadow-medium);
|
||||
border: 1px solid #f1f5f9;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.info-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
background: var(--primary-gradient);
|
||||
}
|
||||
|
||||
.info-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.info-card h6 {
|
||||
color: #64748b;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
font-size: 0.8rem;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.info-card h6::before {
|
||||
content: '';
|
||||
width: 3px;
|
||||
height: 12px;
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Stats Cards */
|
||||
.stats-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 25px;
|
||||
text-align: center;
|
||||
box-shadow: var(--shadow-medium);
|
||||
border: 1px solid #f1f5f9;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stats-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: var(--primary-gradient);
|
||||
}
|
||||
|
||||
.stats-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.stats-card.orders { --card-color: #3b82f6; }
|
||||
.stats-card.amount { --card-color: #10b981; }
|
||||
.stats-card.marks { --card-color: #8b5cf6; }
|
||||
|
||||
.stats-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 15px;
|
||||
font-size: 1.5rem;
|
||||
background: linear-gradient(135deg, var(--card-color), var(--card-color));
|
||||
color: white;
|
||||
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.3);
|
||||
}
|
||||
|
||||
.stats-card.orders .stats-icon { background: var(--info-gradient); }
|
||||
.stats-card.amount .stats-icon { background: var(--success-gradient); }
|
||||
.stats-card.marks .stats-icon { background: var(--primary-gradient); }
|
||||
|
||||
.stats-value {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 800;
|
||||
color: #1e293b;
|
||||
margin-bottom: 5px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
color: #64748b;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Mark Numbers List */
|
||||
.marks-section {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
box-shadow: var(--shadow-medium);
|
||||
border: 1px solid #f1f5f9;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||||
padding: 25px 30px;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.section-header h5 {
|
||||
margin: 0;
|
||||
color: #1e293b;
|
||||
font-weight: 800;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.section-header h5::before {
|
||||
content: '';
|
||||
width: 4px;
|
||||
height: 20px;
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mark-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px 30px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
transition: all 0.3s ease;
|
||||
animation: itemEntrance 0.5s ease-out both;
|
||||
}
|
||||
|
||||
@keyframes itemEntrance {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.mark-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.mark-item:hover {
|
||||
background: #f8fafc;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.mark-badge {
|
||||
background: var(--primary-gradient);
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 12px;
|
||||
font-weight: 700;
|
||||
font-size: 0.9rem;
|
||||
margin-right: 15px;
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.mark-route {
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Buttons - FIXED POSITIONING */
|
||||
.btn-back {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 12px;
|
||||
padding: 12px 25px;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
backdrop-filter: blur(10px);
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-back::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.2),
|
||||
transparent);
|
||||
transition: left 0.6s ease;
|
||||
}
|
||||
|
||||
.btn-back:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.btn-back:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
transform: translateY(-2px);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-premium {
|
||||
background: var(--primary-gradient);
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
padding: 12px 25px;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-premium::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.2),
|
||||
transparent);
|
||||
transition: left 0.6s ease;
|
||||
}
|
||||
|
||||
.btn-premium:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.btn-premium:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 35px rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
border: 2px solid #64748b;
|
||||
border-radius: 12px;
|
||||
padding: 12px 25px;
|
||||
color: #64748b;
|
||||
font-weight: 700;
|
||||
background: transparent;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-outline-secondary:hover {
|
||||
border-color: #475569;
|
||||
color: #475569;
|
||||
background: rgba(100, 116, 139, 0.05);
|
||||
transform: translateY(-2px);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
.type-badge {
|
||||
padding: 8px 16px;
|
||||
border-radius: 12px;
|
||||
font-weight: 700;
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.badge-premium {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(240, 147, 251, 0.4);
|
||||
}
|
||||
|
||||
.badge-regular {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(79, 172, 254, 0.4);
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 8px 16px;
|
||||
border-radius: 12px;
|
||||
font-weight: 700;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.badge-active {
|
||||
background: var(--success-gradient);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
|
||||
.badge-inactive {
|
||||
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(239, 68, 68, 0.4);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
.animate-fade-in {
|
||||
animation: fadeInUp 0.6s ease-out both;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animation-delay-1 { animation-delay: 0.1s; }
|
||||
.animation-delay-2 { animation-delay: 0.2s; }
|
||||
.animation-delay-3 { animation-delay: 0.3s; }
|
||||
.animation-delay-4 { animation-delay: 0.4s; }
|
||||
|
||||
/* Header Button Container - FIXED */
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.profile-header {
|
||||
padding: 25px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.customer-avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
justify-content: center;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.page-header .row {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.btn-back, .btn-outline-secondary {
|
||||
padding: 10px 20px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-actions a {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container py-4">
|
||||
|
||||
{{-- HEADER --}}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h3 class="fw-bold">Customer Details</h3>
|
||||
<a href="{{ route('admin.customers.index') }}" class="btn btn-secondary">
|
||||
<i class="bi bi-arrow-left"></i> Back
|
||||
</a>
|
||||
{{-- HEADER - FIXED BUTTON POSITION --}}
|
||||
<div class="page-header animate-fade-in">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-8">
|
||||
<h1 class="fw-bold mb-2">Customer Details</h1>
|
||||
<p class="mb-0 opacity-90">Complete customer information and analytics</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="header-actions">
|
||||
<a href="{{ route('admin.customers.index') }}" class="btn-back">
|
||||
<i class="bi bi-arrow-left"></i>
|
||||
Back to List
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- CUSTOMER CARD --}}
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
|
||||
{{-- Avatar --}}
|
||||
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-3"
|
||||
style="width:70px; height:70px; font-size:28px; font-weight:bold;">
|
||||
{{ strtoupper(substr($customer->customer_name,0,1)) }}
|
||||
{{-- CUSTOMER PROFILE CARD --}}
|
||||
<div class="customer-card mb-4">
|
||||
<div class="profile-header">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="avatar-container">
|
||||
<div class="customer-avatar">
|
||||
{{ strtoupper(substr($customer->customer_name,0,1)) }}
|
||||
</div>
|
||||
<div class="avatar-status {{ $customer->status == 'active' ? 'status-active' : 'status-inactive' }}"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 class="mb-0">{{ $customer->customer_name }}</h4>
|
||||
<div class="text-muted">{{ $customer->company_name }}</div>
|
||||
|
||||
{{-- Customer Type --}}
|
||||
@if($customer->customer_type == 'premium')
|
||||
<span class="badge bg-purple mt-2">Premium Customer</span>
|
||||
@else
|
||||
<span class="badge bg-secondary mt-2">Regular Customer</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="ms-auto">
|
||||
{{-- Status --}}
|
||||
@if($customer->status == 'active')
|
||||
<span class="badge bg-success p-2">Active</span>
|
||||
@else
|
||||
<span class="badge bg-danger p-2">Inactive</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- BASIC INFO --}}
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-uppercase text-muted">Contact Information</h6>
|
||||
<p class="mb-1"><strong>Email:</strong> {{ $customer->email }}</p>
|
||||
<p class="mb-1"><strong>Mobile:</strong> {{ $customer->mobile_no }}</p>
|
||||
<p class="mb-1"><strong>Address:</strong> {{ $customer->address }}</p>
|
||||
<p class="mb-1"><strong>Pincode:</strong> {{ $customer->pincode }}</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h6 class="text-uppercase text-muted">Account Information</h6>
|
||||
<p class="mb-1"><strong>Customer ID:</strong> {{ $customer->customer_id }}</p>
|
||||
<p class="mb-1"><strong>Registered On:</strong>
|
||||
{{ $customer->created_at ? $customer->created_at->format('d-m-Y') : '-' }}
|
||||
<div class="col">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<h2 class="fw-bold mb-0 me-3">{{ $customer->customer_name }}</h2>
|
||||
@if($customer->customer_type == 'premium')
|
||||
<span class="type-badge badge-premium">
|
||||
<i class="bi bi-award me-1"></i>Premium
|
||||
</span>
|
||||
@else
|
||||
<span class="type-badge badge-regular">
|
||||
<i class="bi bi-person me-1"></i>Regular
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<p class="text-muted mb-2">
|
||||
<i class="bi bi-building me-2"></i>
|
||||
{{ $customer->company_name ?? 'No company specified' }}
|
||||
</p>
|
||||
<p class="mb-1"><strong>Designation:</strong>
|
||||
{{ $customer->designation ?? 'N/A' }}</p>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<span class="status-badge {{ $customer->status == 'active' ? 'badge-active' : 'badge-inactive' }}">
|
||||
<i class="bi bi-circle-fill me-1" style="font-size: 0.6rem;"></i>
|
||||
{{ ucfirst($customer->status) }}
|
||||
</span>
|
||||
<span class="text-muted">
|
||||
<i class="bi bi-calendar me-1"></i>
|
||||
Joined {{ $customer->created_at ? $customer->created_at->format('M d, Y') : 'N/A' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- CUSTOMER INFORMATION --}}
|
||||
<div class="row g-4 p-4">
|
||||
{{-- Contact Information --}}
|
||||
<div class="col-md-6 animate-fade-in animation-delay-1">
|
||||
<div class="info-card">
|
||||
<h6><i class="bi bi-telephone me-2"></i>Contact Information</h6>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="bi bi-envelope text-primary me-2"></i>
|
||||
<strong class="me-2">Email:</strong>
|
||||
<span>{{ $customer->email }}</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="bi bi-phone text-primary me-2"></i>
|
||||
<strong class="me-2">Mobile:</strong>
|
||||
<span>{{ $customer->mobile_no }}</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="bi bi-geo-alt text-primary me-2"></i>
|
||||
<strong class="me-2">Address:</strong>
|
||||
<span>{{ $customer->address ?? 'N/A' }}</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="bi bi-pin-map text-primary me-2"></i>
|
||||
<strong class="me-2">Pincode:</strong>
|
||||
<span>{{ $customer->pincode ?? 'N/A' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Account Information --}}
|
||||
<div class="col-md-6 animate-fade-in animation-delay-2">
|
||||
<div class="info-card">
|
||||
<h6><i class="bi bi-person-badge me-2"></i>Account Information</h6>
|
||||
<div class="mb-3">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="bi bi-id-card text-primary me-2"></i>
|
||||
<strong class="me-2">Customer ID:</strong>
|
||||
<code class="bg-light px-2 py-1 rounded">{{ $customer->customer_id }}</code>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="bi bi-calendar-check text-primary me-2"></i>
|
||||
<strong class="me-2">Registered On:</strong>
|
||||
<span>{{ $customer->created_at ? $customer->created_at->format('d M, Y') : '-' }}</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="bi bi-briefcase text-primary me-2"></i>
|
||||
<strong class="me-2">Designation:</strong>
|
||||
<span>{{ $customer->designation ?? 'N/A' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- STATISTICS --}}
|
||||
<div class="row mb-4">
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
{{-- Total Orders --}}
|
||||
<div class="col-md-4">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="fw-bold">{{ $totalOrders }}</h5>
|
||||
<p class="text-muted mb-0">Total Orders</p>
|
||||
<div class="col-md-4 animate-fade-in animation-delay-1">
|
||||
<div class="stats-card orders">
|
||||
<div class="stats-icon">
|
||||
<i class="bi bi-cart-check"></i>
|
||||
</div>
|
||||
<div class="stats-value">{{ $totalOrders }}</div>
|
||||
<div class="stats-label">Total Orders</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Total Amount --}}
|
||||
<div class="col-md-4">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="fw-bold">₹{{ number_format($totalAmount, 2) }}</h5>
|
||||
<p class="text-muted mb-0">Total Amount Spent</p>
|
||||
<div class="col-md-4 animate-fade-in animation-delay-2">
|
||||
<div class="stats-card amount">
|
||||
<div class="stats-icon">
|
||||
<i class="bi bi-currency-rupee"></i>
|
||||
</div>
|
||||
<div class="stats-value">₹{{ number_format($totalAmount, 2) }}</div>
|
||||
<div class="stats-label">Total Amount Spent</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Mark Count --}}
|
||||
<div class="col-md-4">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="fw-bold">{{ $customer->marks->count() }}</h5>
|
||||
<p class="text-muted mb-0">Total Mark Numbers</p>
|
||||
<div class="col-md-4 animate-fade-in animation-delay-3">
|
||||
<div class="stats-card marks">
|
||||
<div class="stats-icon">
|
||||
<i class="bi bi-hash"></i>
|
||||
</div>
|
||||
<div class="stats-value">{{ $customer->marks->count() }}</div>
|
||||
<div class="stats-label">Mark Numbers</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{-- MARK LIST --}}
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header bg-light">
|
||||
<strong>Customer Mark Numbers</strong>
|
||||
{{-- MARK NUMBERS SECTION --}}
|
||||
<div class="marks-section animate-fade-in animation-delay-4">
|
||||
<div class="section-header">
|
||||
<h5>
|
||||
<i class="bi bi-hash"></i>
|
||||
Customer Mark Numbers
|
||||
<span class="badge bg-primary ms-2">{{ $customer->marks->count() }}</span>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="section-body">
|
||||
@if($customer->marks->count() == 0)
|
||||
<p class="text-muted">No mark numbers found.</p>
|
||||
<div class="text-center py-5">
|
||||
<i class="bi bi-inbox display-4 text-muted mb-3"></i>
|
||||
<p class="text-muted mb-0">No mark numbers found for this customer.</p>
|
||||
</div>
|
||||
@else
|
||||
<ul class="list-group">
|
||||
@foreach($customer->marks as $mark)
|
||||
<li class="list-group-item">
|
||||
<strong>{{ $mark->mark_no }}</strong>
|
||||
<span class="text-muted">({{ $mark->origin }} → {{ $mark->destination }})</span>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@foreach($customer->marks as $index => $mark)
|
||||
<div class="mark-item" style="animation-delay: {{ $index * 0.1 }}s">
|
||||
<div class="mark-badge">
|
||||
<i class="bi bi-tag me-1"></i>{{ $mark->mark_no }}
|
||||
</div>
|
||||
<div class="mark-route">
|
||||
<i class="bi bi-arrow-right me-1"></i>
|
||||
{{ $mark->origin }} → {{ $mark->destination }}
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- {{-- RECENT ORDERS --}}
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header bg-light">
|
||||
<strong>Recent Orders</strong>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-0">
|
||||
@if($recentOrders->count() == 0)
|
||||
<p class="p-3 text-muted">No recent orders found.</p>
|
||||
@else
|
||||
<table class="table table-bordered mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Order ID</th>
|
||||
<th>Mark No</th>
|
||||
<th>Total Amount</th>
|
||||
<th>Date</th>
|
||||
<th>View</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach($recentOrders as $o)
|
||||
<tr>
|
||||
<td>{{ $o->order_id }}</td>
|
||||
<td>{{ $o->mark_no }}</td>
|
||||
<td>₹{{ number_format($o->ttl_amount, 2) }}</td>
|
||||
<td>{{ $o->created_at->format('d-m-Y') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.orders.show', $o->id) }}"
|
||||
class="btn btn-sm btn-primary">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
@endif
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Add hover effects to interactive elements
|
||||
const interactiveElements = document.querySelectorAll('.info-card, .stats-card, .mark-item');
|
||||
|
||||
interactiveElements.forEach(element => {
|
||||
element.addEventListener('mouseenter', function() {
|
||||
this.style.transform = this.classList.contains('mark-item') ? 'translateX(5px)' : 'translateY(-5px)';
|
||||
});
|
||||
|
||||
element.addEventListener('mouseleave', function() {
|
||||
this.style.transform = 'translateY(0)';
|
||||
});
|
||||
});
|
||||
|
||||
// Add loading animation to stats cards
|
||||
const statsValues = document.querySelectorAll('.stats-value');
|
||||
statsValues.forEach(value => {
|
||||
const originalText = value.textContent;
|
||||
value.textContent = '0';
|
||||
|
||||
setTimeout(() => {
|
||||
value.textContent = originalText;
|
||||
value.style.transform = 'scale(1.1)';
|
||||
setTimeout(() => {
|
||||
value.style.transform = 'scale(1)';
|
||||
}, 300);
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -4,12 +4,30 @@
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
/* Your existing CSS remains exactly the same */
|
||||
body, .container-fluid { background: #f4f7fc; }
|
||||
.dash-top-titlebox {
|
||||
margin-bottom: 2px; background: transparent;
|
||||
padding-left: 3px; padding-top: 2px;
|
||||
/* ===== GLOBAL RESPONSIVE STYLES ===== */
|
||||
html, body {
|
||||
overflow-x: hidden !important;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
body, .container-fluid {
|
||||
background: #f4f7fc;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
/* ===== DASHBOARD TITLE ===== */
|
||||
.dash-top-titlebox {
|
||||
margin-bottom: 2px;
|
||||
background: transparent;
|
||||
padding-left: 3px;
|
||||
padding-top: 2px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.dash-title-main {
|
||||
font-size: 1.54rem;
|
||||
font-weight: 800;
|
||||
@@ -17,6 +35,7 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
color: #18213e;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.dash-title-desc {
|
||||
font-size: 1rem;
|
||||
color: #6577a3;
|
||||
@@ -24,116 +43,316 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
font-weight: 500;
|
||||
letter-spacing: .01em;
|
||||
}
|
||||
.stats-row-wrap { margin-bottom: 33px; }
|
||||
|
||||
/* ===== STATS CARDS - RESPONSIVE GRID ===== */
|
||||
.stats-row-wrap {
|
||||
margin-bottom: 33px;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 18px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
@media (max-width: 992px) { .stats-row { grid-template-columns: repeat(2, 1fr); } }
|
||||
@media (max-width: 630px) { .stats-row { grid-template-columns: 1fr; } }
|
||||
|
||||
.stats-card {
|
||||
background: rgba(255,255,255,0.77);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 7px 32px 0 rgba(19, 39, 78, 0.13), 0 2px 7px 0 rgba(160,180,224,0.14), 0 2px 30px #c5dcf940;
|
||||
backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
|
||||
overflow: hidden; position: relative; display: flex; align-items: center; gap: 14px; padding: 18px 16px;
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
padding: 18px 16px;
|
||||
border: 1.2px solid #e8f0fd80;
|
||||
transition: box-shadow .2s cubic-bezier(.45,.57,.46,.99), transform .15s cubic-bezier(.45,.57,.46,.99);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.stats-card::after {
|
||||
content:""; position: absolute; inset: 0; border-radius: 16px; pointer-events:none;
|
||||
content:"";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 16px;
|
||||
pointer-events:none;
|
||||
background: linear-gradient(120deg,rgba(74,156,255,.15) 5%,rgba(210,228,255,.06) 54%,rgba(120,150,255,.13) 99%);
|
||||
z-index:0;
|
||||
}
|
||||
|
||||
.stats-card:hover, .stats-card:focus-within {
|
||||
box-shadow: 0 18px 48px 0 rgba(62,87,177,0.16), 0 3px 19px 0 #82ccfc3b;
|
||||
transform: scale(1.031) translateY(-7px);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.stats-icon {
|
||||
font-size:1.65rem; width:48px; height:48px; border-radius:13px; display:flex; align-items:center; justify-content:center;
|
||||
background:#f5f7fd; transition:.22s cubic-bezier(.57,.75,.45,.97);
|
||||
font-size:1.65rem;
|
||||
width:48px;
|
||||
height:48px;
|
||||
border-radius:13px;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
background:#f5f7fd;
|
||||
transition:.22s cubic-bezier(.57,.75,.45,.97);
|
||||
box-shadow:0 1.7px 13px #edf1fd38;
|
||||
}
|
||||
.stats-card-blue .stats-icon {background:linear-gradient(135deg,#3492f8 55%,#1256cc 110%);color:#fff;}
|
||||
.stats-card-green .stats-icon {background:linear-gradient(135deg,#18ce77 60%,#08ac52 110%);color:#fff;}
|
||||
.stats-card-red .stats-icon {background:linear-gradient(135deg,#ff5a4e 65%,#d90010 110%);color:#fff;}
|
||||
.stats-card-orng .stats-icon {background:linear-gradient(135deg,#ffb23c 53%,#e17800 110%);color:#fff;}
|
||||
.stats-label { font-size:13px; color:#63709b; font-weight:600; letter-spacing:.28px;}
|
||||
.stats-value { font-size:1.25rem; font-weight:700; color:#194073;}
|
||||
|
||||
.stats-card-blue .stats-icon {
|
||||
background:linear-gradient(135deg,#3492f8 55%,#1256cc 110%);
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.stats-card-green .stats-icon {
|
||||
background:linear-gradient(135deg,#18ce77 60%,#08ac52 110%);
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.stats-card-red .stats-icon {
|
||||
background:linear-gradient(135deg,#ff5a4e 65%,#d90010 110%);
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.stats-card-orng .stats-icon {
|
||||
background:linear-gradient(135deg,#ffb23c 53%,#e17800 110%);
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
font-size:13px;
|
||||
color:#63709b;
|
||||
font-weight:600;
|
||||
letter-spacing:.28px;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
font-size:1.25rem;
|
||||
font-weight:700;
|
||||
color:#194073;
|
||||
}
|
||||
|
||||
.stats-card:hover .stats-icon {
|
||||
transform: scale(1.09) rotate(7deg);
|
||||
box-shadow:0 0 13px #2396f33b;
|
||||
}
|
||||
/* Table header box-round style */
|
||||
.table thead tr {
|
||||
background: #feebbe !important;
|
||||
border-radius: 17px 17px 0 0;
|
||||
box-shadow: 0 2px 19px #f8cf667e;
|
||||
}
|
||||
.table thead th {
|
||||
background: transparent !important;
|
||||
border: none;
|
||||
font-weight: 700; color: #343535; letter-spacing: 0.02em; font-size:15px;
|
||||
padding-top: 12px; padding-bottom: 10px;
|
||||
}
|
||||
.table thead th:first-child { border-radius: 17px 0 0 0;}
|
||||
.table thead th:last-child { border-radius: 0 17px 0 0;}
|
||||
/* ------- */
|
||||
|
||||
/* ===== ORDER MANAGEMENT SECTION ===== */
|
||||
.order-mgmt-box {
|
||||
background: #fff; border-radius:17px; box-shadow:0 7px 38px #dde3fa77, 0 2px 9px #e5e7ff80;
|
||||
margin-bottom: 33px; margin-top: 10px; padding-bottom: 0;
|
||||
background: #fff;
|
||||
border-radius:17px;
|
||||
box-shadow:0 7px 38px #dde3fa77, 0 2px 9px #e5e7ff80;
|
||||
margin-bottom: 33px;
|
||||
margin-top: 10px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.order-mgmt-bar {
|
||||
display:flex; justify-content:space-between; align-items:center;
|
||||
border-radius:17px 17px 0 0; background: #fffbe9;
|
||||
min-height: 54px; padding: 15px 26px 10px 22px; border-bottom: 1.4px solid #e8e2cf;
|
||||
display:flex;
|
||||
justify-content:space-between;
|
||||
align-items:center;
|
||||
border-radius:17px 17px 0 0;
|
||||
background: #fceeb8ff;
|
||||
min-height: 54px;
|
||||
padding: 15px 26px 10px 22px;
|
||||
border-bottom: 1.4px solid #e8e2cf;
|
||||
box-shadow:0 1px 13px #ffe2a888;
|
||||
}
|
||||
|
||||
.order-mgmt-title {
|
||||
font-size:1.32rem; font-weight:800; color:#2451af; letter-spacing:.08em;
|
||||
display: flex; align-items: center; gap: 11px;
|
||||
font-size:1.32rem;
|
||||
font-weight:800;
|
||||
color:#2451af;
|
||||
letter-spacing:.08em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 11px;
|
||||
}
|
||||
.order-mgmt-title i { font-size: 1.12em; color: #336ad3; }
|
||||
|
||||
.order-mgmt-title i {
|
||||
font-size: 1.12em;
|
||||
color: #336ad3;
|
||||
}
|
||||
|
||||
.create-order-btn {
|
||||
background: linear-gradient(90deg,#226ad6,#46b4fd 123%);
|
||||
padding:9px 26px; font-weight:600; border:none; border-radius:9px; color:#fff;
|
||||
font-size:16.2px; box-shadow: 0 2px 13px #dde7fa42;
|
||||
padding:9px 26px;
|
||||
font-weight:600;
|
||||
border:none;
|
||||
border-radius:9px;
|
||||
color:#fff;
|
||||
font-size:16.2px;
|
||||
box-shadow: 0 2px 13px #dde7fa42;
|
||||
transition: background 0.16s, box-shadow .17s;
|
||||
display: flex; align-items: center; gap: 8px; font-family: inherit;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.create-order-btn:hover {
|
||||
background: linear-gradient(90deg,#3264f8,#3acfff 140%);
|
||||
box-shadow:0 4px 25px #5ab8f880;
|
||||
}
|
||||
.card-body, .order-mgmt-main { background: #fff; border-radius: 0 0 17px 17px; padding:25px; }
|
||||
.card { border-radius:17px; box-shadow:0 7px 29px #e7eefd8c; border:none; margin-bottom:23px!important;}
|
||||
.table { background:#fff; border-radius:9px; box-shadow:0 2px 12px #e2ebf941;}
|
||||
.table-striped tbody tr:nth-of-type(odd) { background:#f9fafc; }
|
||||
.table-responsive { border-radius:10px; }
|
||||
.badge { font-size:13px; font-weight:600; padding:7px 17px; border-radius:12px;}
|
||||
.bg-info { background-color:#22cbfa!important; color:#fff!important;}
|
||||
.form-label { font-weight:600; color:#1d3159; font-size:15px;}
|
||||
.form-control, .form-select {
|
||||
border-radius:8px!important; font-size:15.8px; background: #f7f9fe;
|
||||
border:1.2px solid #c7dbfa; font-weight:500;
|
||||
}
|
||||
.form-control:focus, .form-select:focus {
|
||||
border-color:#2469d6; box-shadow:0 0 4px #226ad688;
|
||||
}
|
||||
.table td a { color:#2469d6; font-weight:600; text-decoration:underline; }
|
||||
@media (max-width:1200px){.stats-row{grid-template-columns:repeat(2,1fr);}}
|
||||
@media (max-width:768px){
|
||||
.order-mgmt-bar{flex-direction:column;align-items:flex-start;gap:7px;padding:14px;}
|
||||
.create-order-btn{margin-top:8px;}
|
||||
.table th, .table td{font-size:13.5px;}
|
||||
|
||||
.card-body, .order-mgmt-main {
|
||||
background: #fff;
|
||||
border-radius: 0 0 17px 17px;
|
||||
padding:25px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
/* --- CREATE ORDER MODAL STYLES --- */
|
||||
.card {
|
||||
border-radius:17px;
|
||||
box-shadow:0 7px 29px #e7eefd8c;
|
||||
border:none;
|
||||
margin-bottom:23px!important;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
/* ===== TABLE STYLES ===== */
|
||||
.table thead tr {
|
||||
background: #feebbe !important;
|
||||
border-radius: 12px 12px 0 0;
|
||||
box-shadow: 0 2px 19px #f8cf667e;
|
||||
}
|
||||
|
||||
.table thead th {
|
||||
background: transparent !important;
|
||||
border: none;
|
||||
font-weight: 700;
|
||||
color: #343535;
|
||||
letter-spacing: 0.02em;
|
||||
font-size:15px;
|
||||
padding-top: 12px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.table thead th:first-child { border-radius: 9px 0 0 0;}
|
||||
.table thead th:last-child { border-radius: 0 9px 0 0;}
|
||||
|
||||
.table {
|
||||
background:#fff;
|
||||
border-radius:9px;
|
||||
box-shadow:0 2px 12px #e2ebf941;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 2px;
|
||||
}
|
||||
|
||||
.table-striped tbody tr {
|
||||
background: #fff;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
|
||||
margin-bottom: 2px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:hover {
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(odd) {
|
||||
background:#f9fafc;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(even) {
|
||||
background:#ffffff;
|
||||
}
|
||||
|
||||
.table td {
|
||||
padding: 12px 6px;
|
||||
border: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.table td:first-child {
|
||||
border-radius: 6px 0 0 6px;
|
||||
}
|
||||
|
||||
.table td:last-child {
|
||||
border-radius: 0 6px 6px 0;
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
border-radius:10px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size:13px;
|
||||
font-weight:600;
|
||||
padding:7px 17px;
|
||||
border-radius:12px;
|
||||
}
|
||||
|
||||
.bg-info {
|
||||
background-color:#22cbfa!important;
|
||||
color:#fff!important;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-weight:600;
|
||||
color:#1d3159;
|
||||
font-size:15px;
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
border-radius:8px!important;
|
||||
font-size:15.8px;
|
||||
background: #f7f9fe;
|
||||
border:1.2px solid #c7dbfa;
|
||||
font-weight:500;
|
||||
}
|
||||
|
||||
.form-control:focus, .form-select:focus {
|
||||
border-color:#2469d6;
|
||||
box-shadow:0 0 4px #226ad688;
|
||||
}
|
||||
|
||||
.table td a {
|
||||
color:#2469d6;
|
||||
font-weight:600;
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
/* ===== HORIZONTAL SCROLL CONTAINER ===== */
|
||||
.table-wrapper {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scroll-behavior: smooth;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.table-wrapper::-webkit-scrollbar {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.table-wrapper::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(90deg, #a7b8ff, #6c8eff);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.table-wrapper::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(90deg, #5a78ff, #3f63e0);
|
||||
}
|
||||
|
||||
.table-wrapper::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 1200px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* ===== CREATE ORDER MODAL STYLES ===== */
|
||||
.create-order-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -201,7 +420,6 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
/* Form styles inside modal */
|
||||
.create-order-modal .form-label {
|
||||
font-weight: 600;
|
||||
color: #1d3159;
|
||||
@@ -269,7 +487,6 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
background: #c82333;
|
||||
}
|
||||
|
||||
/* Table styles inside modal */
|
||||
.create-order-modal .table-wrapper {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
@@ -290,7 +507,182 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* ===== ORDER DETAILS MODAL STYLES ===== */
|
||||
.modal.fade .modal-dialog {
|
||||
transition: transform 0.3s ease-out;
|
||||
transform: translate(0, -50px);
|
||||
}
|
||||
|
||||
.modal.show .modal-dialog {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-bottom: none;
|
||||
padding: 11px 16px;
|
||||
border-radius: 20px 20px 0 0;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-header .btn-close {
|
||||
filter: invert(1);
|
||||
opacity: 0.8;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-header .btn-close:hover {
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 30px;
|
||||
background: #f8fafc;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* ===== RESPONSIVE BREAKPOINTS ===== */
|
||||
|
||||
/* Laptop (1200px and below) */
|
||||
@media (max-width: 1200px) {
|
||||
.stats-row {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet (992px and below) */
|
||||
@media (max-width: 992px) {
|
||||
.stats-row {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.order-mgmt-bar {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.order-mgmt-title {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.create-order-btn {
|
||||
padding: 8px 20px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 900px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 10px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile Landscape (768px and below) */
|
||||
@media (max-width: 768px) {
|
||||
.container-fluid {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.dash-title-main {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.dash-title-desc {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.stats-row-wrap {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
padding: 15px 12px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.stats-icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.order-mgmt-bar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 12px 15px;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.create-order-btn {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.card-body, .order-mgmt-main {
|
||||
padding: 20px 15px;
|
||||
}
|
||||
|
||||
.table-wrapper {
|
||||
padding: 5px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 800px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px 4px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 0.75rem;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: 4px 8px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* Modal adjustments for mobile */
|
||||
.create-order-modal .modal-card {
|
||||
width: 98%;
|
||||
margin: 10px;
|
||||
@@ -303,63 +695,171 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
.create-order-modal .modal-header {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
}
|
||||
/* --- END MODAL STYLES --- */
|
||||
|
||||
/* ✅ Horizontal scroll container */
|
||||
.table-wrapper {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scroll-behavior: smooth;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
padding: 8px;
|
||||
|
||||
.modal-body {
|
||||
padding: 20px 15px;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ✅ Stylish scrollbar */
|
||||
.table-wrapper::-webkit-scrollbar {
|
||||
height: 8px;
|
||||
}
|
||||
.table-wrapper::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(90deg, #a7b8ff, #6c8eff);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.table-wrapper::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(90deg, #5a78ff, #3f63e0);
|
||||
}
|
||||
.table-wrapper::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
/* Mobile Portrait (576px and below) */
|
||||
@media (max-width: 576px) {
|
||||
.container-fluid {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.dash-title-main {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.dash-title-desc {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
padding: 12px 10px;
|
||||
}
|
||||
|
||||
.stats-icon {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.order-mgmt-title {
|
||||
font-size: 1.1rem;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.order-mgmt-box {
|
||||
border-radius: 12px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.order-mgmt-bar {
|
||||
border-radius: 12px 12px 0 0;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.card-body, .order-mgmt-main {
|
||||
padding: 15px 10px;
|
||||
border-radius: 0 0 12px 12px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 700px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 6px 3px;
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
font-size: 14px;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-card {
|
||||
width: 100%;
|
||||
margin: 5px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-header {
|
||||
padding: 12px 15px;
|
||||
border-radius: 12px 12px 0 0;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-body {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* Stack form columns on mobile */
|
||||
.create-order-modal .row.g-3 > [class*="col-"] {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 1200px;
|
||||
border-radius: 10px;
|
||||
/* Small Mobile (400px and below) */
|
||||
@media (max-width: 400px) {
|
||||
.container-fluid {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 8px;
|
||||
padding: 15px 8px;
|
||||
}
|
||||
|
||||
.order-mgmt-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.create-order-btn {
|
||||
font-size: 14px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 650px;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
font-size: 0.7rem;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success message styling */
|
||||
.alert-success {
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid #28a745;
|
||||
margin-bottom: 15px;
|
||||
/* High-resolution displays */
|
||||
@media (min-width: 1400px) {
|
||||
.container-fluid {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear form button */
|
||||
.clear-form-btn {
|
||||
background: #6c757d;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
font-weight: 600;
|
||||
border-radius: 6px;
|
||||
color: white;
|
||||
margin-right: 10px;
|
||||
/* Print styles */
|
||||
@media print {
|
||||
.create-order-btn,
|
||||
.order-mgmt-bar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
.clear-form-btn:hover {
|
||||
background: #5a6268;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container-fluid py-3">
|
||||
@@ -435,34 +935,35 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>{{ $order->mark_no }}</td>
|
||||
<td>{{ $order->origin }}</td>
|
||||
<td>{{ $order->destination }}</td>
|
||||
<td>{{ $order->ctn }}</td>
|
||||
<td>{{ $order->qty }}</td>
|
||||
<td>{{ $order->ttl_qty }}</td>
|
||||
<td>₹{{ number_format($order->ttl_amount, 2) }}</td>
|
||||
<td>{{ $order->cbm }}</td>
|
||||
<td>{{ $order->ttl_cbm }}</td>
|
||||
<td>{{ $order->kg }}</td>
|
||||
<td>{{ $order->ttl_kg }}</td>
|
||||
<td>
|
||||
<span class="badge bg-info text-dark">{{ ucfirst($order->status) }}</span>
|
||||
</td>
|
||||
<td>{{ $order->created_at->format('d-m-Y') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.orders.show', $order->id) }}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-eye"></i> View
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="16" class="text-muted">No orders found</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
<td>{{ $order->mark_no }}</td>
|
||||
<td>{{ $order->origin }}</td>
|
||||
<td>{{ $order->destination }}</td>
|
||||
<td>{{ $order->ctn }}</td>
|
||||
<td>{{ $order->qty }}</td>
|
||||
<td>{{ $order->ttl_qty }}</td>
|
||||
<td>₹{{ number_format($order->ttl_amount, 2) }}</td>
|
||||
<td>{{ $order->cbm }}</td>
|
||||
<td>{{ $order->ttl_cbm }}</td>
|
||||
<td>{{ $order->kg }}</td>
|
||||
<td>{{ $order->ttl_kg }}</td>
|
||||
<td>
|
||||
<span class="badge bg-info text-dark">{{ ucfirst($order->status) }}</span>
|
||||
</td>
|
||||
<td>{{ $order->created_at->format('d-m-Y') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.orders.show', $order->id) }}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-eye"></i> View
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="16" class="text-muted">No orders found</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -643,6 +1144,22 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODERN ORDER DETAILS MODAL -->
|
||||
<div class="modal fade" id="orderDetailsModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Order Details</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body" id="orderDetailsBody">
|
||||
<p class="text-center text-muted">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const modal = document.getElementById('createOrderModal');
|
||||
@@ -725,55 +1242,30 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
e.preventDefault();
|
||||
}
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- ORDER DETAILS MODAL -->
|
||||
<div class="modal fade" id="orderDetailsModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Order Details</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
// Order details modal functionality
|
||||
document.querySelectorAll('.open-order-modal').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
let id = this.dataset.id;
|
||||
let modal = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
|
||||
|
||||
<div class="modal-body" id="orderDetailsBody">
|
||||
<p class="text-center text-muted">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
document.getElementById('orderDetailsBody').innerHTML =
|
||||
"<p class='text-center text-muted'>Loading...</p>";
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
modal.show();
|
||||
|
||||
document.querySelectorAll('.open-order-modal').forEach(button => {
|
||||
|
||||
button.addEventListener('click', function () {
|
||||
|
||||
let id = this.dataset.id;
|
||||
let modal = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
|
||||
|
||||
document.getElementById('orderDetailsBody').innerHTML =
|
||||
"<p class='text-center text-muted'>Loading...</p>";
|
||||
|
||||
modal.show();
|
||||
|
||||
fetch(`/admin/orders/view/${id}`)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
document.getElementById('orderDetailsBody').innerHTML = html;
|
||||
})
|
||||
.catch(() => {
|
||||
document.getElementById('orderDetailsBody').innerHTML =
|
||||
"<p class='text-danger text-center'>Failed to load order details.</p>";
|
||||
fetch(`/admin/orders/view/${id}`)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
document.getElementById('orderDetailsBody').innerHTML = html;
|
||||
})
|
||||
.catch(() => {
|
||||
document.getElementById('orderDetailsBody').innerHTML =
|
||||
"<p class='text-danger text-center'>Failed to load order details.</p>";
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,357 @@
|
||||
@section('page-title', 'Edit Invoice')
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
/* World-Class UI Design System - No Blur Effects */
|
||||
:root {
|
||||
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
--success-gradient: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||
--glass-bg: #ffffff;
|
||||
--glass-border: rgba(255, 255, 255, 0.2);
|
||||
--shadow-soft: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
--shadow-medium: 0 12px 48px rgba(0, 0, 0, 0.15);
|
||||
--shadow-strong: 0 20px 60px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Enhanced Card - No Blur */
|
||||
.card {
|
||||
background: var(--glass-bg);
|
||||
border-radius: 24px;
|
||||
box-shadow: var(--shadow-strong);
|
||||
border: 1px solid #e4e6ef;
|
||||
animation: cardEntrance 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(45deg,
|
||||
rgba(102, 126, 234, 0.03) 0%,
|
||||
rgba(118, 75, 162, 0.03) 50%,
|
||||
rgba(16, 185, 129, 0.03) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes cardEntrance {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(30px) scale(0.95);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Premium Card Header */
|
||||
.card-header {
|
||||
background: var(--primary-gradient);
|
||||
color: white;
|
||||
border-bottom: none;
|
||||
padding: 28px 35px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: linear-gradient(45deg,
|
||||
transparent 0%,
|
||||
rgba(255, 255, 255, 0.1) 50%,
|
||||
transparent 100%);
|
||||
animation: headerShimmer 6s infinite linear;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
@keyframes headerShimmer {
|
||||
0% { transform: translateX(-100%) rotate(45deg); }
|
||||
100% { transform: translateX(100%) rotate(45deg); }
|
||||
}
|
||||
|
||||
.card-header h4 {
|
||||
margin: 0;
|
||||
font-weight: 800;
|
||||
font-size: 1.6rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.card-header h4::before {
|
||||
content: '✨';
|
||||
font-size: 1.4rem;
|
||||
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 35px;
|
||||
background: #f8fafc;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* World-Class Form Elements - No Blur */
|
||||
.form-label {
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 10px;
|
||||
font-size: 0.95rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-label::before {
|
||||
content: '';
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
background: var(--primary-gradient);
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 16px;
|
||||
padding: 16px 20px;
|
||||
font-size: 1rem;
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-control:focus, .form-select:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow:
|
||||
0 0 0 4px rgba(102, 126, 234, 0.15),
|
||||
0 8px 24px rgba(102, 126, 234, 0.2),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||
background: #ffffff;
|
||||
transform: translateY(-2px) scale(1.02);
|
||||
animation: inputGlow 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes inputGlow {
|
||||
0%, 100% { box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.15), 0 8px 24px rgba(102, 126, 234, 0.2); }
|
||||
50% { box-shadow: 0 0 0 6px rgba(102, 126, 234, 0.1), 0 12px 32px rgba(102, 126, 234, 0.25); }
|
||||
}
|
||||
|
||||
.form-control:hover, .form-select:hover {
|
||||
border-color: #cbd5e1;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/* Enhanced Grid System */
|
||||
.row.g-3 {
|
||||
margin: -15px;
|
||||
}
|
||||
|
||||
.row.g-3 > [class*="col-"] {
|
||||
padding: 15px;
|
||||
animation: formElementEntrance 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||
}
|
||||
|
||||
@keyframes formElementEntrance {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(25px) scale(0.9);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Staggered Animation Delays */
|
||||
.row.g-3 > [class*="col-"]:nth-child(1) { animation-delay: 0.1s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(2) { animation-delay: 0.2s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(3) { animation-delay: 0.3s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(4) { animation-delay: 0.4s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(5) { animation-delay: 0.5s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(6) { animation-delay: 0.6s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(7) { animation-delay: 0.7s; }
|
||||
.row.g-3 > [class*="col-"]:nth-child(8) { animation-delay: 0.8s; }
|
||||
|
||||
/* Premium Textarea */
|
||||
textarea.form-control {
|
||||
resize: vertical;
|
||||
min-height: 120px;
|
||||
line-height: 1.6;
|
||||
background: #ffffff;
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
textarea.form-control:focus {
|
||||
transform: translateY(-2px) scale(1.01);
|
||||
box-shadow:
|
||||
0 0 0 4px rgba(102, 126, 234, 0.15),
|
||||
0 12px 32px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
/* World-Class Button Design - No Blur */
|
||||
.btn-success {
|
||||
background: var(--success-gradient);
|
||||
border: none;
|
||||
padding: 18px 45px;
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: var(--shadow-medium);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-success::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.4),
|
||||
transparent);
|
||||
transition: left 0.6s ease;
|
||||
}
|
||||
|
||||
.btn-success:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
transform: translateY(-4px) scale(1.05);
|
||||
box-shadow:
|
||||
0 16px 40px rgba(16, 185, 129, 0.4),
|
||||
0 0 0 1px rgba(255, 255, 255, 0.1);
|
||||
background: var(--success-gradient);
|
||||
}
|
||||
|
||||
.btn-success:active {
|
||||
transform: translateY(-1px) scale(1.02);
|
||||
transition: all 0.1s ease;
|
||||
}
|
||||
|
||||
/* Enhanced Select Styling */
|
||||
.form-select {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23667eea' stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right 20px center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 18px;
|
||||
padding-right: 50px;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
/* Advanced Loading Animation */
|
||||
.btn-success.loading {
|
||||
pointer-events: none;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
.btn-success.loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-top: -10px;
|
||||
border: 2px solid transparent;
|
||||
border-top: 2px solid white;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Premium Focus States */
|
||||
.form-control:focus-visible,
|
||||
.form-select:focus-visible,
|
||||
.btn-success:focus-visible {
|
||||
outline: 3px solid #667eea;
|
||||
outline-offset: 2px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* Advanced Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.card-body {
|
||||
padding: 25px 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding: 22px 25px;
|
||||
}
|
||||
|
||||
.card-header h4 {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
width: 100%;
|
||||
padding: 16px 30px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
padding: 14px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Micro-interactions for Enhanced UX */
|
||||
.form-control:valid {
|
||||
border-left: 3px solid #10b981;
|
||||
}
|
||||
|
||||
.form-control:invalid:not(:focus):not(:placeholder-shown) {
|
||||
border-left: 3px solid #ef4444;
|
||||
animation: shake 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-5px); }
|
||||
75% { transform: translateX(5px); }
|
||||
}
|
||||
|
||||
/* Smooth scrolling for better UX */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Performance optimized animations */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-light">
|
||||
@@ -10,7 +361,6 @@
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<form action="{{ route('admin.invoices.update', $invoice->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
@@ -82,8 +432,50 @@
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
<script>
|
||||
// World-Class Interactive Enhancements - No Parallax
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const form = document.querySelector('form');
|
||||
const submitBtn = document.querySelector('.btn-success');
|
||||
const inputs = document.querySelectorAll('input, select, textarea');
|
||||
|
||||
// Enhanced form submission
|
||||
form.addEventListener('submit', function(e) {
|
||||
submitBtn.classList.add('loading');
|
||||
submitBtn.innerHTML = 'Updating Invoice...';
|
||||
|
||||
// Add a small delay to show loading state
|
||||
setTimeout(() => {
|
||||
if (!form.checkValidity()) {
|
||||
submitBtn.classList.remove('loading');
|
||||
submitBtn.innerHTML = 'Update Invoice';
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// Real-time validation with visual feedback
|
||||
inputs.forEach(input => {
|
||||
input.addEventListener('input', function() {
|
||||
if (this.checkValidity()) {
|
||||
this.style.borderLeftColor = '#10b981';
|
||||
} else {
|
||||
this.style.borderLeftColor = '#ef4444';
|
||||
}
|
||||
});
|
||||
|
||||
// Add focus effects
|
||||
input.addEventListener('focus', function() {
|
||||
this.parentElement.style.transform = 'translateY(-2px)';
|
||||
});
|
||||
|
||||
input.addEventListener('blur', function() {
|
||||
this.parentElement.style.transform = 'translateY(0)';
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@@ -5,6 +5,8 @@
|
||||
<title>Admin Panel</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
@@ -17,7 +19,7 @@
|
||||
|
||||
/* ✨ Sidebar Glass + Animated Highlight Effect */
|
||||
.sidebar {
|
||||
width: 190px;
|
||||
width: 200px;
|
||||
height: 100vh;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(232, 240, 255, 0.95)) !important;
|
||||
box-shadow: 2px 0 25px rgba(0, 0, 0, 0.08);
|
||||
@@ -29,6 +31,10 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: all 0.3s ease-in-out;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
}
|
||||
|
||||
.sidebar .logo {
|
||||
@@ -126,6 +132,7 @@
|
||||
margin-top: 12px;
|
||||
font-weight: 500;
|
||||
transition: 0.3s ease;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.sidebar form button:hover {
|
||||
@@ -141,6 +148,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: calc(100vw - 190px);
|
||||
margin-left: 190px;
|
||||
}
|
||||
|
||||
header {
|
||||
|
||||
@@ -3,167 +3,270 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{ $invoice->invoice_number }}</title>
|
||||
|
||||
<style>
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
font-family: 'Segoe UI', 'Roboto', Arial, sans-serif;
|
||||
background: #F7FBFC;
|
||||
color: #1A222B;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.header-box {
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
border-bottom: 2px solid #000;
|
||||
margin-bottom: 20px;
|
||||
.container {
|
||||
max-width: 850px;
|
||||
margin: 24px auto 0 auto;
|
||||
background: #fff;
|
||||
border-radius: 13px;
|
||||
box-shadow: 0 2px 14px rgba(40,105,160,0.08);
|
||||
padding: 35px 32px 18px 32px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
border-bottom: 2px solid #E6EBF0;
|
||||
padding-bottom: 13px;
|
||||
}
|
||||
.logo-company {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 120px;
|
||||
margin-bottom: 8px;
|
||||
height: 50px;
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 22px;
|
||||
.company-details {
|
||||
margin-top: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
.company-title {
|
||||
font-size: 21px;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
margin-top: 3px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
.company-sub {
|
||||
font-size: 16px;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.invoice-details {
|
||||
text-align: right;
|
||||
min-width: 220px;
|
||||
}
|
||||
.invoice-title {
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 6px;
|
||||
color: #222;
|
||||
font-size: 23px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.paid-label {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.paid-tag {
|
||||
background: #23BF47;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
border-radius: 8px;
|
||||
padding: 4px 16px 4px 22px;
|
||||
font-size: 17px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.paid-tag:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 7px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.paid-date {
|
||||
font-size: 14px;
|
||||
color: #23BF47;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
.bill-section {
|
||||
background: #F3F7FB;
|
||||
border-radius: 11px;
|
||||
padding: 20px 18px 13px 18px;
|
||||
margin: 28px 0 16px 0;
|
||||
box-shadow: 0 0px 0px #0000;
|
||||
}
|
||||
.bill-title {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
color: #23355D;
|
||||
margin-bottom: 4px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
.bill-details {
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 12px;
|
||||
margin-top: 9px;
|
||||
margin-bottom: 13px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #efefef;
|
||||
padding: 6px;
|
||||
font-size: 13px;
|
||||
background: #F6F7F9;
|
||||
padding: 10px 0;
|
||||
font-size: 15px;
|
||||
color: #6781A6;
|
||||
font-weight: bold;
|
||||
border: 1px solid #444;
|
||||
border: none;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 6px;
|
||||
border: 1px solid #444;
|
||||
font-size: 12px;
|
||||
padding: 7px 0;
|
||||
color: #222;
|
||||
font-size: 15px;
|
||||
border: none;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.totals-box {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border: 1px solid #bbb;
|
||||
background: #fafafa;
|
||||
tbody tr:not(:last-child) td {
|
||||
border-bottom: 1px solid #E6EBF0;
|
||||
}
|
||||
tbody tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
.totals-row td {
|
||||
font-weight: bold;
|
||||
color: #23355D;
|
||||
}
|
||||
.gst-row td {
|
||||
font-weight: 500;
|
||||
color: #23BF47;
|
||||
}
|
||||
.total-row td {
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
color: #222;
|
||||
}
|
||||
.payment-info {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 9px;
|
||||
font-size: 15px;
|
||||
}
|
||||
.ref-number {
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
color: #6781A6;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.footer {
|
||||
border-top: 1.2px solid #E6EBF0;
|
||||
margin-top: 25px;
|
||||
padding-top: 12px;
|
||||
font-size: 16px;
|
||||
color: #888;
|
||||
text-align: center;
|
||||
}
|
||||
.footer strong {
|
||||
color: #222;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- HEADER -->
|
||||
<div class="header-box">
|
||||
|
||||
<!-- LOGO -->
|
||||
<img src="{{ public_path('images/kent_logo2.png') }}" class="logo">
|
||||
|
||||
<div class="title">KENT LOGISTICS</div>
|
||||
<div class="subtitle">Official Invoice</div>
|
||||
<div class="container">
|
||||
<!-- Header Section -->
|
||||
<div class="header">
|
||||
<div class="logo-company">
|
||||
<img src="{{ public_path('images/kent_logo2.png') }}" class="logo">
|
||||
<div class="company-details">
|
||||
<div class="company-title">{{ $invoice->company_name ?? 'Kent International Pvt. Ltd.' }}</div>
|
||||
<div class="company-sub"></div>
|
||||
{{ $invoice->company_address ?? '123 Business Park, Sector 5' }}<br>
|
||||
{{ $invoice->company_city ?? 'Gurugram, Haryana 122001' }}<br>
|
||||
{{ $invoice->company_country ?? 'India' }}<br>
|
||||
GST: {{ $invoice->company_gst ?? 'GST123456789' }}<br>
|
||||
Email: {{ $invoice->company_email ?? 'billing@kent.com' }}<br>
|
||||
Phone: {{ $invoice->company_phone ?? '+91 124 123 4567' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-details">
|
||||
<div class="invoice-title">INVOICE</div>
|
||||
Invoice #: {{ $invoice->invoice_number }}<br>
|
||||
Issue Date: {{ date('d M Y', strtotime($invoice->invoice_date)) }}<br>
|
||||
Due Date: {{ date('d M Y', strtotime($invoice->due_date)) }}
|
||||
@if(strtolower($invoice->status) == 'paid')
|
||||
<div class="paid-label">
|
||||
<span class="paid-tag">Paid</span>
|
||||
</div>
|
||||
<div class="paid-date">
|
||||
Paid on: {{ date('d M Y', strtotime($invoice->paid_date ?? now())) }}
|
||||
</div>
|
||||
@else
|
||||
<div class="paid-date" style="color:#d00;">Status: {{ ucfirst($invoice->status) }}</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<!-- Bill To Section -->
|
||||
<div class="bill-section">
|
||||
<div class="bill-title">Bill To</div>
|
||||
<div class="bill-details">
|
||||
<strong>{{ $invoice->customer_name }}</strong><br>
|
||||
{{ $invoice->customer_address }}<br>
|
||||
GST: {{ $invoice->customer_gst ?? '-' }}<br>
|
||||
Email: {{ $invoice->customer_email }}<br>
|
||||
Phone: {{ $invoice->customer_mobile }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Items Table -->
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<th>Qty</th>
|
||||
<th>Rate (₹)</th>
|
||||
<th>Amount (₹)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($invoice->items as $item)
|
||||
<tr>
|
||||
<td>{{ $item->description }}</td>
|
||||
<td>{{ $item->qty }}</td>
|
||||
<td>{{ number_format($item->price, 0) }}</td>
|
||||
<td>{{ number_format($item->ttl_amount, 0) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
<tr class="totals-row">
|
||||
<td colspan="3" style="text-align:right;">Subtotal:</td>
|
||||
<td>{{ number_format($invoice->subtotal, 0) }}</td>
|
||||
</tr>
|
||||
<tr class="gst-row">
|
||||
<td colspan="3" style="text-align:right;">GST ({{ $invoice->gst_percent }}%):</td>
|
||||
<td>{{ number_format($invoice->gst_amount, 0) }}</td>
|
||||
</tr>
|
||||
<tr class="total-row">
|
||||
<td colspan="3" style="text-align:right;">Total:</td>
|
||||
<td>{{ number_format($invoice->final_amount_with_gst, 0) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- Payment Info & Reference -->
|
||||
<div class="payment-info">
|
||||
<strong>Payment Method:</strong> {{ $invoice->payment_method ?? 'Bank Transfer' }}
|
||||
</div>
|
||||
<div class="ref-number">
|
||||
Reference Number: {{ $invoice->reference_no ?? "REF123456789" }}
|
||||
</div>
|
||||
<!-- Footer -->
|
||||
<div class="footer">
|
||||
Thank you for your business!<br>
|
||||
For any queries, please contact us at <strong>{{ $invoice->company_email ?? 'billing@kent.com' }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- INVOICE INFO -->
|
||||
<div class="info-box">
|
||||
<strong>Invoice No:</strong> {{ $invoice->invoice_number }} <br>
|
||||
<strong>Invoice Date:</strong> {{ $invoice->invoice_date }} <br>
|
||||
<strong>Due Date:</strong> {{ $invoice->due_date }} <br>
|
||||
<strong>Status:</strong> {{ ucfirst($invoice->status) }}
|
||||
</div>
|
||||
|
||||
<!-- CUSTOMER DETAILS -->
|
||||
<div class="section-title">Customer Details</div>
|
||||
<div class="info-box">
|
||||
<strong>{{ $invoice->customer_name }}</strong><br>
|
||||
{{ $invoice->company_name }} <br>
|
||||
{{ $invoice->customer_mobile }} <br>
|
||||
{{ $invoice->customer_email }} <br>
|
||||
{{ $invoice->customer_address }}
|
||||
</div>
|
||||
|
||||
<!-- ITEMS TABLE -->
|
||||
<div class="section-title">Invoice Items</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Description</th>
|
||||
<th>CTN</th>
|
||||
<th>QTY</th>
|
||||
<th>TTL/QTY</th>
|
||||
<th>Unit</th>
|
||||
<th>Price</th>
|
||||
<th>TTL Amount</th>
|
||||
<th>CBM</th>
|
||||
<th>TTL CBM</th>
|
||||
<th>KG</th>
|
||||
<th>TTL KG</th>
|
||||
<th>Shop No</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach($invoice->items as $i => $item)
|
||||
<tr>
|
||||
<td>{{ $i + 1 }}</td>
|
||||
<td>{{ $item->description }}</td>
|
||||
<td>{{ $item->ctn }}</td>
|
||||
<td>{{ $item->qty }}</td>
|
||||
<td>{{ $item->ttl_qty }}</td>
|
||||
<td>{{ $item->unit }}</td>
|
||||
<td>{{ number_format($item->price, 2) }}</td>
|
||||
<td>{{ number_format($item->ttl_amount, 2) }}</td>
|
||||
<td>{{ $item->cbm }}</td>
|
||||
<td>{{ $item->ttl_cbm }}</td>
|
||||
<td>{{ $item->kg }}</td>
|
||||
<td>{{ $item->ttl_kg }}</td>
|
||||
<td>{{ $item->shop_no }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- TOTALS -->
|
||||
<div class="section-title">Totals</div>
|
||||
|
||||
<div class="totals-box">
|
||||
<strong>Amount:</strong> ₹{{ number_format($invoice->final_amount, 2) }} <br>
|
||||
<strong>GST ({{ $invoice->gst_percent }}%):</strong> ₹{{ number_format($invoice->gst_amount, 2) }} <br>
|
||||
<strong>Total With GST:</strong> <strong>₹{{ number_format($invoice->final_amount_with_gst, 2) }}</strong>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,73 +1,207 @@
|
||||
<div>
|
||||
<h4 class="fw-bold mb-2">
|
||||
Invoice: {{ $invoice->invoice_number }}
|
||||
</h4>
|
||||
|
||||
<p><strong>Invoice Date:</strong> {{ $invoice->invoice_date }}</p>
|
||||
<p><strong>Due Date:</strong> {{ $invoice->due_date }}</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h5>Customer Details</h5>
|
||||
<p>
|
||||
<strong>{{ $invoice->customer_name }}</strong><br>
|
||||
{{ $invoice->company_name }}<br>
|
||||
{{ $invoice->customer_mobile }}<br>
|
||||
{{ $invoice->customer_email }}<br>
|
||||
{{ $invoice->customer_address }}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h5>Invoice Items</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered align-middle text-center">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Description</th>
|
||||
<th>CTN</th>
|
||||
<th>QTY</th>
|
||||
<th>TTL/QTY</th>
|
||||
<th>Unit</th>
|
||||
<th>Price</th>
|
||||
<th>TTL Amount</th>
|
||||
<th>CBM</th>
|
||||
<th>TTL CBM</th>
|
||||
<th>KG</th>
|
||||
<th>TTL KG</th>
|
||||
<th>Shop No</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach($invoice->items as $i => $item)
|
||||
<tr>
|
||||
<td>{{ $i+1 }}</td>
|
||||
<td>{{ $item->description }}</td>
|
||||
<td>{{ $item->ctn }}</td>
|
||||
<td>{{ $item->qty }}</td>
|
||||
<td>{{ $item->ttl_qty }}</td>
|
||||
<td>{{ $item->unit }}</td>
|
||||
<td>{{ number_format($item->price,2) }}</td>
|
||||
<td>{{ number_format($item->ttl_amount,2) }}</td>
|
||||
<td>{{ $item->cbm }}</td>
|
||||
<td>{{ $item->ttl_cbm }}</td>
|
||||
<td>{{ $item->kg }}</td>
|
||||
<td>{{ $item->ttl_kg }}</td>
|
||||
<td>{{ $item->shop_no }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="p-4">
|
||||
<!-- Invoice Header -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<h2 class="fw-bold text-primary mb-1">
|
||||
<i class="fas fa-file-invoice me-2"></i>INVOICE
|
||||
</h2>
|
||||
<h4 class="fw-bold text-dark mb-0">{{ $invoice->invoice_number }}</h4>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<div class="d-inline-block bg-light rounded-3 p-3">
|
||||
<span class="badge
|
||||
@if($invoice->status=='paid') bg-success
|
||||
@elseif($invoice->status=='overdue') bg-danger
|
||||
@elseif($invoice->status=='pending') bg-warning text-dark
|
||||
@else bg-secondary @endif
|
||||
fs-6 px-3 py-2">
|
||||
<i class="fas
|
||||
@if($invoice->status=='paid') fa-check-circle
|
||||
@elseif($invoice->status=='overdue') fa-exclamation-circle
|
||||
@elseif($invoice->status=='pending') fa-clock
|
||||
@else fa-question-circle @endif me-1"></i>
|
||||
{{ ucfirst($invoice->status) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<!-- Dates - Compact Professional Layout -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body py-2">
|
||||
<div class="row align-items-center text-center">
|
||||
<div class="col-md-5">
|
||||
<div class="mb-0">
|
||||
<div class="text-muted fw-semibold small">INVOICE DATE</div>
|
||||
</div>
|
||||
<div class="fw-bold text-dark" style="font-size: 0.95rem;">
|
||||
{{ \Carbon\Carbon::parse($invoice->invoice_date)->format('M d, Y') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="date-connector">
|
||||
<i class="fas fa-arrow-right text-muted small"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="mb-0">
|
||||
<div class="text-muted fw-semibold small">DUE DATE</div>
|
||||
</div>
|
||||
<div class="fw-bold @if($invoice->status == 'overdue') text-danger @else text-dark @endif" style="font-size: 0.95rem;">
|
||||
{{ \Carbon\Carbon::parse($invoice->due_date)->format('M d, Y') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5>Final Summary</h5>
|
||||
<p><strong>Amount:</strong> ₹{{ number_format($invoice->final_amount,2) }}</p>
|
||||
<p><strong>GST ({{ $invoice->gst_percent }}%):</strong> ₹{{ number_format($invoice->gst_amount,2) }}</p>
|
||||
<p><strong>Total With GST:</strong> ₹{{ number_format($invoice->final_amount_with_gst,2) }}</p>
|
||||
<!-- Customer Details -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-light py-2">
|
||||
<h6 class="mb-0 fw-bold text-dark">
|
||||
<i class="fas fa-user me-2"></i>Customer Details
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6 class="fw-bold text-primary mb-1">{{ $invoice->customer_name }}</h6>
|
||||
@if($invoice->company_name)
|
||||
<p class="mb-1">
|
||||
<strong>Company:</strong> {{ $invoice->company_name }}
|
||||
</p>
|
||||
@endif
|
||||
<p class="mb-1">
|
||||
<strong>Mobile:</strong> {{ $invoice->customer_mobile }}
|
||||
</p>
|
||||
<p class="mb-1">
|
||||
<strong>Email:</strong> {{ $invoice->customer_email }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p class="mb-0">
|
||||
<strong>Address:</strong><br>
|
||||
{{ $invoice->customer_address }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p><strong>Status:</strong> {{ ucfirst($invoice->status) }}</p>
|
||||
<!-- Invoice Items -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-light py-2">
|
||||
<h6 class="mb-0 fw-bold text-dark">
|
||||
<i class="fas fa-list me-2"></i>Invoice Items
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="text-center">#</th>
|
||||
<th>Description</th>
|
||||
<th class="text-center">CTN</th>
|
||||
<th class="text-center">QTY</th>
|
||||
<th class="text-center">TTL/QTY</th>
|
||||
<th class="text-center">Unit</th>
|
||||
<th class="text-center">Price</th>
|
||||
<th class="text-center">TTL Amount</th>
|
||||
<th class="text-center">CBM</th>
|
||||
<th class="text-center">TTL CBM</th>
|
||||
<th class="text-center">KG</th>
|
||||
<th class="text-center">TTL KG</th>
|
||||
<th class="text-center">Shop No</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($invoice->items as $i => $item)
|
||||
<tr>
|
||||
<td class="text-center fw-bold text-muted">{{ $i+1 }}</td>
|
||||
<td class="fw-semibold">{{ $item->description }}</td>
|
||||
<td class="text-center">{{ $item->ctn }}</td>
|
||||
<td class="text-center">{{ $item->qty }}</td>
|
||||
<td class="text-center fw-bold">{{ $item->ttl_qty }}</td>
|
||||
<td class="text-center">{{ $item->unit }}</td>
|
||||
<td class="text-center text-success fw-bold">₹{{ number_format($item->price,2) }}</td>
|
||||
<td class="text-center text-primary fw-bold">₹{{ number_format($item->ttl_amount,2) }}</td>
|
||||
<td class="text-center">{{ $item->cbm }}</td>
|
||||
<td class="text-center">{{ $item->ttl_cbm }}</td>
|
||||
<td class="text-center">{{ $item->kg }}</td>
|
||||
<td class="text-center">{{ $item->ttl_kg }}</td>
|
||||
<td class="text-center">
|
||||
<span class="badge bg-light text-dark border">{{ $item->shop_no }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Final Summary -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 offset-md-6">
|
||||
<div class="card border-0 bg-light">
|
||||
<div class="card-header bg-dark text-white py-2">
|
||||
<h6 class="mb-0 fw-bold">
|
||||
<i class="fas fa-calculator me-2"></i>Final Summary
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2 pb-1 border-bottom">
|
||||
<span class="fw-semibold">Amount:</span>
|
||||
<span class="fw-bold text-dark">₹{{ number_format($invoice->final_amount,2) }}</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2 pb-1 border-bottom">
|
||||
<span class="fw-semibold">GST ({{ $invoice->gst_percent }}%):</span>
|
||||
<span class="fw-bold text-danger">₹{{ number_format($invoice->gst_amount,2) }}</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center pt-1">
|
||||
<span class="fw-bold text-dark">Total With GST:</span>
|
||||
<span class="fw-bold text-success">₹{{ number_format($invoice->final_amount_with_gst,2) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.date-connector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: #6c757d;
|
||||
}
|
||||
.date-connector i {
|
||||
background: #f8f9fa;
|
||||
padding: 4px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #e9ecef;
|
||||
}
|
||||
.card {
|
||||
border-radius: 6px;
|
||||
}
|
||||
.table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.table > :not(caption) > * > * {
|
||||
padding: 10px 6px;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -143,6 +143,10 @@ Route::prefix('admin')
|
||||
Route::post('/invoices/{id}/update', [AdminInvoiceController::class, 'update'])
|
||||
->name('admin.invoices.update');
|
||||
|
||||
//Add New Invoice
|
||||
Route::get('/admin/invoices/create', [InvoiceController::class, 'create'])->name('admin.invoices.create');
|
||||
|
||||
|
||||
|
||||
// ---------------------------
|
||||
// CUSTOMERS
|
||||
|
||||
Reference in New Issue
Block a user