diff --git a/app/Console/Commands/clientAssetGenerator.php b/app/Console/Commands/clientAssetGenerator.php
index d0e72b3..5ad3746 100644
--- a/app/Console/Commands/clientAssetGenerator.php
+++ b/app/Console/Commands/clientAssetGenerator.php
@@ -40,7 +40,7 @@ class clientAssetGenerator extends Command
// prepare client.scss and add gfx variable
- $js = "// PLEASE DO NOT EDIT THIS FILE, \n// IF YOU WANT ADD ANY CODE CREATE NEW JS INTO client-custom" . PHP_EOL;
+ $js = "// PLEASE DO NOT EDIT THIS FILE, \n// IF YOU WANT ADD ANY CODE CREATE NEW JS INTO client-custom \n import axios from 'axios'; \n window.axios = axios; \n \n window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';" . PHP_EOL;
$variables = "// PLEASE DO NOT EDIT THIS FILE, \n// IF YOU WANT ADD ANY CODE CREATE NEW SCSS INTO client-custom" . PHP_EOL;
foreach ($vars as $k => $var) {
$variables .= '$'."$k:$var;" . PHP_EOL;
diff --git a/app/Helpers/TVisitor.php b/app/Helpers/TVisitor.php
new file mode 100644
index 0000000..f2c436d
--- /dev/null
+++ b/app/Helpers/TVisitor.php
@@ -0,0 +1,426 @@
+
+ * @date : 3-April-2013 (14-1-1392)
+ * @time : 20:32
+ * @subpackage TVisitor
+ * @version 1.0
+ * @todo : TVisitor class for get visitor info
+ */
+class TVisitor {
+
+ function __construct() {
+
+ }
+
+ /**
+ * @todo Detect visitor OS
+ * @return int os number
+ */
+ public static function DetectOSI() {
+ if (!isset($_SERVER['HTTP_USER_AGENT']))
+ return 0;
+
+ $os_list = array(
+ '(Linux)',
+ '(Windows NT 11.0)', // Added Windows 11
+ '(Windows NT 10.0)',
+ '(Windows NT 6.3)',
+ '(Windows NT 6.2)',
+ '(Windows NT 6.1)',
+ '(Windows NT 6.0)',
+ '(Windows NT 5.2)',
+ '(Windows NT 5.1)',
+ '(Windows NT 5.0)',
+ '(Windows NT 4.0)',
+ '(Win 9x 4.90)',
+ '(Windows 98)',
+ '(Windows 95)',
+ '(Windows CE)',
+ 'Windows (iPhone|iPad)',
+ '(iPhone)|(iPad)',
+ '(Mac OS X)',
+ '(MacPPC)|(Mac_PowerPC)|(Macintosh)',
+ '(Ubuntu)',
+ '(Linux Mint)',
+ '(Debian)',
+ '(Fedora)',
+ '(Red Hat)',
+ '(SuSE)',
+ '(Android)',
+ '(webOS)|(hpwOS)',
+ '(BlackBerry)',
+ '(Symbian)',
+ '(FreeBSD)',
+ '(OpenBSD)',
+ '(NetBSD)',
+ '(SunOS)',
+ '(OpenSolaris)',
+ '(Chrome OS)',
+ '(CrOS)',
+ '(bot)'
+ );
+
+ foreach ($os_list as $index => $match) {
+ if (preg_match("/$match/i", $_SERVER['HTTP_USER_AGENT'])) {
+ return $index + 1;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @todo Detect visitor OS
+ * @return string OS name
+ */
+ public static function DetectOS() {
+ if (!isset($_SERVER['HTTP_USER_AGENT']))
+ return 'Unknown';
+
+ $os_list = array(
+ 'Linux' => '(Linux)',
+ 'Windows 11' => '(Windows NT 11.0)', // Added Windows 11
+ 'Windows 10' => '(Windows NT 10.0)',
+ 'Windows 8.1' => '(Windows NT 6.3)',
+ 'Windows 8' => '(Windows NT 6.2)',
+ 'Windows 7' => '(Windows NT 6.1)',
+ 'Windows Vista' => '(Windows NT 6.0)',
+ 'Windows Server 2003/XP x64' => '(Windows NT 5.2)',
+ 'Windows XP' => '(Windows NT 5.1)',
+ 'Windows 2000' => '(Windows NT 5.0)',
+ 'Windows ME' => '(Win 9x 4.90)',
+ 'Windows 98' => '(Windows 98)',
+ 'Windows 95' => '(Windows 95)',
+ 'Windows CE' => '(Windows CE)',
+ 'Windows (iPhone/iPad)' => 'Windows (iPhone|iPad)',
+ 'iPhone/iPad' => '(iPhone)|(iPad)',
+ 'Mac OS X' => '(Mac OS X)',
+ 'Mac OS' => '(MacPPC)|(Mac_PowerPC)|(Macintosh)',
+ 'Ubuntu' => '(Ubuntu)',
+ 'Linux Mint' => '(Linux Mint)',
+ 'Debian' => '(Debian)',
+ 'Fedora' => '(Fedora)',
+ 'Red Hat' => '(Red Hat)',
+ 'SuSE' => '(SuSE)',
+ 'Android' => '(Android)',
+ 'webOS' => '(webOS)|(hpwOS)',
+ 'BlackBerry' => '(BlackBerry)',
+ 'Symbian' => '(Symbian)',
+ 'FreeBSD' => '(FreeBSD)',
+ 'OpenBSD' => '(OpenBSD)',
+ 'NetBSD' => '(NetBSD)',
+ 'SunOS' => '(SunOS)',
+ 'OpenSolaris' => '(OpenSolaris)',
+ 'Chrome OS' => '(Chrome OS)|(CrOS)',
+ 'bot' => '(bot)'
+ );
+
+ foreach ($os_list as $os => $pattern) {
+ if (preg_match("/$pattern/i", $_SERVER['HTTP_USER_AGENT'])) {
+ return $os;
+ }
+ }
+
+ return 'Unknown';
+ }
+
+ /**
+ * @todo Detect if visitor is using a mobile device
+ * @return bool
+ */
+ public static function IsMobile() {
+ if (!isset($_SERVER['HTTP_USER_AGENT'])) {
+ return false;
+ }
+
+ $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
+
+ // List of mobile devices and operating systems
+ $mobile_agents = [
+ 'mobile', 'android', 'iphone', 'ipod', 'ipad', 'windows phone', 'blackberry', 'kindle', 'silk',
+ 'opera mini', 'opera mobi', 'webos', 'symbian', 'nokia', 'samsung', 'lg', 'htc', 'mot', 'tablet',
+ 'rim tablet', 'meego', 'netfront', 'bolt', 'fennec', 'series60', 'maemo', 'midp', 'cldc', 'up.browser',
+ 'up.link', 'mmp', 'symbian', 'smartphone', 'wap'
+ ];
+
+ // Check if user agent contains any mobile keywords
+ foreach ($mobile_agents as $agent) {
+ if (strpos($user_agent, $agent) !== false) {
+ return true;
+ }
+ }
+
+ // Check for mobile-specific headers
+ if (isset($_SERVER['HTTP_ACCEPT'])) {
+ if (strpos(strtolower($_SERVER['HTTP_ACCEPT']), 'application/vnd.wap.xhtml+xml') !== false) {
+ return true;
+ }
+ }
+
+ if (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
+ return true;
+ }
+
+ // Check for Opera Mini
+ if (isset($_SERVER['HTTP_X_OPERAMINI_PHONE_UA'])) {
+ return true;
+ }
+
+ // Use PHP's built-in mobile detection (if available)
+ if (function_exists('http_negotiate_language')) {
+ $accept = http_negotiate_language(['wap', 'html']);
+ if ($accept === 'wap') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+
+ /**
+ * @todo Get browser name only
+ * @return string browser name
+ */
+ public static function DetectBrowser() {
+ if (!isset($_SERVER['HTTP_USER_AGENT']))
+ return 'Unknown';
+
+ $browser_list = array(
+ 'Firefox' => '(Firefox)',
+ 'Edge' => '(Edg|Edge)',
+ 'Chrome' => '(Chrome)(?!.*Edge)',
+ 'Safari' => '(Safari)(?!.*Chrome)',
+ 'Opera' => '(OPR|Opera)',
+ 'Brave' => '(Brave)',
+ 'Internet Explorer' => '(MSIE|Trident)',
+ 'DeepNet Explorer' => '(Deepnet)',
+ 'Flock' => '(Flock)',
+ 'Maxthon' => '(Maxthon)',
+ 'Avant Browser' => '(Avant)',
+ 'AOL' => '(AOL)',
+ 'Vivaldi' => '(Vivaldi)',
+ 'UC Browser' => '(UCBrowser)',
+ 'Yandex Browser' => '(YaBrowser)',
+ 'Samsung Internet' => '(SamsungBrowser)',
+ );
+
+ foreach ($browser_list as $browser => $pattern) {
+ if (preg_match("/$pattern/i", $_SERVER['HTTP_USER_AGENT'])) {
+ return $browser;
+ }
+ }
+
+ return 'Other';
+ }
+
+ /**
+ * @todo Get browser name only
+ * @return int browser num
+ */
+ public static function DetectBrowserI() {
+ if (!isset($_SERVER['HTTP_USER_AGENT']))
+ return 0;
+
+ $browser_list = array(
+ '(Firefox)',
+ '(Edg|Edge)',
+ '(Chrome)(?!.*Edge)',
+ '(Safari)(?!.*Chrome)',
+ '(OPR|Opera)',
+ '(Brave)',
+ '(MSIE|Trident)',
+ '(Deepnet)',
+ '(Flock)',
+ '(Maxthon)',
+ '(Avant)',
+ '(AOL)',
+ '(Vivaldi)',
+ '(UCBrowser)',
+ '(YaBrowser)',
+ '(SamsungBrowser)',
+ );
+
+ foreach ($browser_list as $index => $pattern) {
+ if (preg_match("/$pattern/i", $_SERVER['HTTP_USER_AGENT'])) {
+ return $index + 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * @todo Find browser version
+ * @return string version
+ */
+ public static function BrowserVersion() {
+ if (!isset($_SERVER['HTTP_USER_AGENT'])) {
+ return '0';
+ }
+
+ $ua = $_SERVER['HTTP_USER_AGENT'];
+ $browser = self::DetectBrowser();
+
+ $version = null;
+
+ switch ($browser) {
+ case 'Edge':
+ if (preg_match('/(Edge|Edg)\/(\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[2];
+ }
+ break;
+ case 'Chrome':
+ if (preg_match('/Chrome\/(\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[1];
+ }
+ break;
+ case 'Firefox':
+ if (preg_match('/Firefox\/(\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[1];
+ }
+ break;
+ case 'Safari':
+ if (preg_match('/Version\/(\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[1];
+ }
+ break;
+ case 'Opera':
+ if (preg_match('/(OPR|Opera)\/(\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[2];
+ }
+ break;
+ case 'Internet Explorer':
+ if (preg_match('/MSIE (\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[1];
+ } elseif (preg_match('/rv:(\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[1]; // For IE 11
+ }
+ break;
+ default:
+ // Generic version detection for other browsers
+ if (preg_match('/' . preg_quote($browser, '/') . '\/(\d+(\.\d+)*)/', $ua, $matches)) {
+ $version = $matches[1];
+ }
+ break;
+ }
+
+ return $version;
+ }
+
+ /**
+ * Get searched keywords from referrer URL
+ * @param string $referer
+ * @return array|null
+ */
+ public static function GetKeyword($referer = null) {
+ if ($referer === null) {
+ $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
+ }
+
+ if (empty($referer)) {
+ return null;
+ }
+
+ $engines = [
+ 'google' => ['q', 'query'],
+ 'bing' => ['q'],
+ 'yahoo' => ['p'],
+ 'yandex' => ['text'],
+ 'baidu' => ['wd', 'word'],
+ 'duckduckgo' => ['q'],
+ 'ask' => ['q'],
+ 'aol' => ['q'],
+ 'naver' => ['query'],
+ 'ecosia' => ['q'],
+ ];
+
+ $parsed_url = parse_url($referer);
+ $host = isset($parsed_url['host']) ? strtolower($parsed_url['host']) : '';
+ $query = isset($parsed_url['query']) ? $parsed_url['query'] : '';
+
+ parse_str($query, $query_params);
+
+ foreach ($engines as $engine => $params) {
+ if (strpos($host, $engine) !== false) {
+ foreach ($params as $param) {
+ if (isset($query_params[$param]) && !empty($query_params[$param])) {
+ return [
+ 'engine' => $engine,
+ 'keyword' => urldecode($query_params[$param])
+ ];
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+// /**
+// * @param string $class alternative class
+// * return vistor os icon
+// * @uses awesome font
+// */
+// static public function GetOSIcon($class = '') {
+// // get os
+// $os_int = self::DetectOSI();
+//
+// $win = range(1, 16);
+// $linux = range(17, 19);
+// $osx = array(20, 21);
+// $android = array(25);
+// $searchbot = array(27);
+// $other = array(0, 22, 23, 24, 26);
+//
+// switch (true) {
+// case in_array($os_int, $win):
+// $icon = 'windows';
+// break;
+// case in_array($os_int, $linux):
+// $icon = 'linux';
+// break;
+// case in_array($os_int, $osx):
+// $icon = 'apple';
+// break;
+//
+// case in_array($os_int, $android):
+// $icon = 'android';
+// break;
+//
+// case in_array($os_int, $searchbot):
+// $icon = 'google';
+// break;
+// default:
+// $icon = 'question';
+// break;
+// }
+//
+// $result = '';
+//
+// return $result;
+// }
+// /**
+// * @param string $class alternative class
+// * return vistor browser icon
+// * @uses awesome font
+// */
+// static public function GetBrowerIcon($class = '') {
+// // get os
+// $bowser = self::DetectBrowser();
+//
+//
+//
+// $result = '';
+// return $result;
+// }
+
+}
diff --git a/app/Http/Controllers/Api/VisitorController.php b/app/Http/Controllers/Api/VisitorController.php
new file mode 100644
index 0000000..1c5b58d
--- /dev/null
+++ b/app/Http/Controllers/Api/VisitorController.php
@@ -0,0 +1,20 @@
+ip())->orderByDesc('id')->first();
+ if ($visitor != null){
+ $visitor->display = $request->input('display',null);
+ $visitor->save();
+ }
+ return ['OK'=>true];
+ }
+}
diff --git a/app/Http/Controllers/VisitorController.php b/app/Http/Controllers/VisitorController.php
new file mode 100644
index 0000000..3df5f3b
--- /dev/null
+++ b/app/Http/Controllers/VisitorController.php
@@ -0,0 +1,10 @@
+',date("Y-m-d H:i:s" ,time() - (60*60)))
+ ->where('ip', $request->ip())->first();
+ if ($visitor === null) {
+ $visitor = new Visitor();
+ $visitor->ip = $request->ip();
+ $visitor->browser = TVisitor::DetectBrowserI();
+ $visitor->os = TVisitor::DetectOSI();
+ $visitor->version = TVisitor::BrowserVersion();
+ $visitor->keywords = TVisitor::GetKeyword();
+ $visitor->is_mobile = TVisitor::IsMobile();
+ $visitor->save();
+ }else{
+ $visitor->increment('visit');
+ }
+ return $next($request);
+ }
+}
diff --git a/app/Models/Visitor.php b/app/Models/Visitor.php
new file mode 100644
index 0000000..adb03f9
--- /dev/null
+++ b/app/Models/Visitor.php
@@ -0,0 +1,11 @@
+
+ */
+class VisitorFactory extends Factory
+{
+ /**
+ * Define the model's default state.
+ *
+ * @return array
+ */
+ public function definition(): array
+ {
+
+ $displays = ['1920x1080','1366x768','1920x1080','1366x768','1280x1024',null, null];
+ $date = $this->faker->dateTimeBetween('-31 days', 'now');
+ return [
+ //
+ 'ip' => $this->faker->ipv4(),
+ 'visit' => rand(1,rand(2,12)),
+ 'browser' => rand(0,5),
+ 'os' => rand(0,14),
+ 'version' => rand(100,132),
+ 'display' => $displays[count($displays)-1],
+ 'updated_at' => $date,
+ 'created_at' => $date,
+ ];
+ }
+}
diff --git a/database/migrations/2024_07_16_042925_create_visitors_table.php b/database/migrations/2024_07_16_042925_create_visitors_table.php
new file mode 100644
index 0000000..f699d38
--- /dev/null
+++ b/database/migrations/2024_07_16_042925_create_visitors_table.php
@@ -0,0 +1,35 @@
+id();
+ $table->ipAddress('ip');
+ $table->unsignedInteger('visit')->default(1);
+ $table->unsignedInteger('browser')->nullable();
+ $table->unsignedInteger('os')->nullable();
+ $table->string('version')->nullable();
+ $table->string('display')->nullable();
+ $table->string('keywords')->nullable();
+ $table->boolean('is_mobile')->default(false);
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('visitors');
+ }
+};
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index fe9eb63..a14da41 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -37,6 +37,7 @@ class DatabaseSeeder extends Seeder
GfxSeeder::class,
AreaSeeder::class,
PartSeeder::class,
+ VisitorSeeder::class
]
);
}
diff --git a/database/seeders/VisitorSeeder.php b/database/seeders/VisitorSeeder.php
new file mode 100644
index 0000000..8c2d995
--- /dev/null
+++ b/database/seeders/VisitorSeeder.php
@@ -0,0 +1,19 @@
+count(110)->create();
+ }
+}
diff --git a/public/upload/images/index.ParallaxShort.jpg b/public/upload/images/index.ParallaxShort.jpg
new file mode 100644
index 0000000..8f60d93
Binary files /dev/null and b/public/upload/images/index.ParallaxShort.jpg differ
diff --git a/resources/js/client-custom/windowLoader.js b/resources/js/client-custom/windowLoader.js
new file mode 100644
index 0000000..57d3b31
--- /dev/null
+++ b/resources/js/client-custom/windowLoader.js
@@ -0,0 +1,49 @@
+window.addEventListener('load', function () {
+ const API_COOKIE_NAME = 'last_api_call';
+ const COOKIE_EXPIRY_MINUTES = 59;
+
+ function setCookie(name, value, minutes) {
+ let expires = "";
+ if (minutes) {
+ let date = new Date();
+ date.setTime(date.getTime() + (minutes * 60 * 1000));
+ expires = "; expires=" + date.toUTCString();
+ }
+ document.cookie = name + "=" + (value || "") + expires + "; path=/";
+ }
+
+ function getCookie(name) {
+ let nameEQ = name + "=";
+ let ca = document.cookie.split(';');
+ for (let i = 0; i < ca.length; i++) {
+ let c = ca[i];
+ while (c.charAt(0) == ' ') c = c.substring(1, c.length);
+ if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
+ }
+ return null;
+ }
+
+ function canSendData() {
+ let lastCall = getCookie(API_COOKIE_NAME);
+ if (!lastCall) return true;
+
+ let lastCallTime = new Date(parseInt(lastCall));
+ let currentTime = new Date();
+ let timeDiff = (currentTime - lastCallTime) / (1000 * 60); // difference in minutes
+
+ return timeDiff >= COOKIE_EXPIRY_MINUTES;
+ }
+
+ if (canSendData()) {
+ axios.post(document.querySelector('#api-display-url').value, {
+ display: window.screen.availWidth + 'x' + window.screen.availHeight,
+ }).then(function (response) {
+ // If the API call is successful, set the cookie
+ setCookie(API_COOKIE_NAME, new Date().getTime(), COOKIE_EXPIRY_MINUTES);
+ }).catch(function (error) {
+ console.error('Error sending data:', error);
+ });
+ } else {
+ console.log('Data was sent recently. Skipping this time.');
+ }
+});
diff --git a/resources/js/client.js b/resources/js/client.js
index b719cc7..b49c101 100644
--- a/resources/js/client.js
+++ b/resources/js/client.js
@@ -1,9 +1,16 @@
// PLEASE DO NOT EDIT THIS FILE,
-// IF YOU WANT ADD ANY CODE CREATE NEW JS INTO client-custom
+// IF YOU WANT ADD ANY CODE CREATE NEW JS INTO client-custom
+ import axios from 'axios';
+ window.axios = axios;
+
+ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
import "./client-custom/assetsNode.js";
import "./client-custom/confirm.js";
+import "./client-custom/windowLoader.js";
import "../views/segments/preloader/PreloaderCircle/PreloaderCircle.js";
import "../views/segments/top/TopSimple/TopSimple.js";
import "../views/segments/slider/SliderSimple/SliderSimple.js";
import "../views/segments/posts/PostsIconSimple/PostsIconSimple.js";
import "../views/segments/index/GradientTextLink/GradientTextLink.js";
+import "../views/segments/category/FavProductWithMeta/FavProductWithMeta.js";
+import "../views/segments/parallax/ParallaxShort/ParallaxShort.js";
diff --git a/resources/sass/client.scss b/resources/sass/client.scss
index d406d05..079ceed 100644
--- a/resources/sass/client.scss
+++ b/resources/sass/client.scss
@@ -1,19 +1,19 @@
// PLEASE DO NOT EDIT THIS FILE,
// IF YOU WANT ADD ANY CODE CREATE NEW SCSS INTO client-custom
$xshop-background:#ffffff;
-$xshop-primary:#6e0000;
+$xshop-primary:#009dff;
$xshop-diff:#ffffff;
-$xshop-secondary:#ff0000;
+$xshop-secondary:#0008ff;
$xshop-text:#111111;
-$xshop-border-radius:6px;
+$xshop-border-radius:0px;
$xshop-shadow:2px 2px 4px #777777;
:root{
--xshop-background:#ffffff;
---xshop-primary:#6e0000;
+--xshop-primary:#009dff;
--xshop-diff:#ffffff;
---xshop-secondary:#ff0000;
+--xshop-secondary:#0008ff;
--xshop-text:#111111;
---xshop-border-radius:6px;
+--xshop-border-radius:0px;
--xshop-shadow:2px 2px 4px #777777;
}
@@ -25,3 +25,5 @@ $xshop-shadow:2px 2px 4px #777777;
@import "../views/segments/slider/SliderSimple/SliderSimple";
@import "../views/segments/posts/PostsIconSimple/PostsIconSimple";
@import "../views/segments/index/GradientTextLink/GradientTextLink";
+@import "../views/segments/category/FavProductWithMeta/FavProductWithMeta";
+@import "../views/segments/parallax/ParallaxShort/ParallaxShort";
diff --git a/resources/views/website/inc/website-foot.blade.php b/resources/views/website/inc/website-foot.blade.php
index e0d118a..bd4a77d 100644
--- a/resources/views/website/inc/website-foot.blade.php
+++ b/resources/views/website/inc/website-foot.blade.php
@@ -1,3 +1,4 @@
@yield('custom-foot')
+