17 Commits

Author SHA1 Message Date
Frank John Begornia
d4a6028599 chore: remove SSH Keys Setup guide to enhance security practices 2026-04-16 23:21:45 +08:00
Frank John Begornia
4888f93eac feat(teamstore): add league/conference sub-sub-category pill filter (hi-five-franchise-store only) 2026-04-16 23:19:19 +08:00
Frank John Begornia
49921a26a9 Add centering guidelines script and update script references in designer view
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 3m7s
2026-04-02 03:33:19 +08:00
Frank John Begornia
3b6e0ec447 Refactor image handling in PrintPatternController and TemplatesController to use MinIO for improved storage management 2026-04-02 03:31:08 +08:00
Frank John Begornia
c16203110b Refactor image URLs to use MinIO storage for improved asset management
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 2m39s
2026-04-02 03:04:49 +08:00
Frank John Begornia
60fcf08cbc Enhance TestEmailController and view to include CSRF token and improve form security
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 1m51s
2026-02-26 23:12:00 +08:00
Frank John Begornia
701a433174 Update exception handling in Handler and TestEmailController for improved error reporting
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 1m51s
2026-02-26 22:58:28 +08:00
Frank John Begornia
47b354d8b7 Add TestEmailController and views for sending test emails
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 2m51s
2026-02-26 22:46:14 +08:00
Frank John Begornia
dfdb48920d Add SSH keys setup guide and update configurations for secure key management
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 4m31s
2026-02-23 02:01:12 +08:00
Frank John Begornia
3dac8ee685 Fix image path for PayPal button in cart view
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 2m1s
2026-01-07 01:42:43 +08:00
Frank John Begornia
09974721f3 Update DesignerController and site_config for MinIO integration and URL adjustments
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 2m23s
2026-01-07 01:28:47 +08:00
Frank John Begornia
8215ad8337 Refactor image URLs to use MinIO storage across various views and controllers
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 2m16s
2026-01-07 01:10:15 +08:00
Frank John Begornia
368ac50729 Add MinIO configuration and update image URLs in MainController
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 1m57s
2026-01-06 15:34:02 +08:00
Frank John Begornia
8f094ee89c Use MinIO for sports category images
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 1m56s
2026-01-06 15:27:17 +08:00
Frank John Begornia
0551cb078f Add MinIO S3 storage integration
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 2m9s
- Add minio disk configuration in filesystems.php
- Create helper functions for MinIO URLs (minio_url, minio_image_url)
- Update composer.json with AWS SDK (for future S3 support)
- Add MinIO env vars to docker-compose.local.yml
- Add .env examples for MinIO configuration
2026-01-06 15:20:15 +08:00
Frank John Begornia
26620fc043 Update README.md to reflect project details and installation instructions
All checks were successful
Deploy Production (crewsportswear.com) / deploy (push) Successful in 2m1s
2026-01-05 23:15:14 +08:00
Frank John Begornia
f10d6daa6f Update APP_URL and Traefik rules for production environment 2026-01-05 23:13:37 +08:00
45 changed files with 1001 additions and 196 deletions

26
.env.local Normal file
View File

@@ -0,0 +1,26 @@
# Local Development Configuration
# Copy to .env.local and fill in your values.
# ── MinIO credentials ─────────────────────────────────────────────────────────
MINIO_KEY=your_minio_root_user
MINIO_SECRET=your_minio_root_password
# ── SSH tunnel (remote DB) ────────────────────────────────────────────────────
# Only needed when starting with --profile ssh-db.
# NOTE: no inline comments allowed after values — Docker reads them literally.
SSH_HOST=136.114.183.15
SSH_PORT=22
SSH_USER=webmaster
# Must be an absolute path — Docker Compose does NOT expand ~
SSH_KEY_PATH=/Users/webmaster/.ssh/id_ed25519_crew_webmaster
SSH_DB_REMOTE_HOST=127.0.0.1
SSH_DB_REMOTE_PORT=3306
# Tell the app to route DB traffic through the tunnel container:
DB_HOST=db-tunnel
DB_PORT=3306
DB_DATABASE=custom_designs
DB_USERNAME=root
DB_PASSWORD=VeryStrongRootPass2025!

26
.env.local.example Normal file
View File

@@ -0,0 +1,26 @@
# Local Development Configuration
# Copy to .env.local and fill in your values.
# ── MinIO credentials ─────────────────────────────────────────────────────────
MINIO_KEY=your_minio_root_user
MINIO_SECRET=your_minio_root_password
# ── SSH tunnel (remote DB) ────────────────────────────────────────────────────
# Only needed when starting with --profile ssh-db.
# IMPORTANT: no inline comments after values — Docker Compose reads them literally.
# IMPORTANT: SSH_KEY_PATH must be an absolute path — ~ is NOT expanded by Docker Compose.
#
SSH_HOST=your.server.ip.or.hostname
SSH_PORT=22
SSH_USER=root
SSH_KEY_PATH=/absolute/path/to/your/private/key
#
SSH_DB_REMOTE_HOST=127.0.0.1 # DB host as seen from the SSH server
SSH_DB_REMOTE_PORT=3306 # DB port as seen from the SSH server
#
# Tell the app to route DB traffic through the tunnel container:
DB_HOST=db-tunnel
DB_PORT=3306
DB_DATABASE=your_remote_db_name
DB_USERNAME=your_remote_db_user
DB_PASSWORD=your_remote_db_password

21
.env.minio.example Normal file
View File

@@ -0,0 +1,21 @@
# MinIO S3 Storage Configuration
# Add these to your production .env file
# MinIO Endpoint (internal Docker network)
MINIO_ENDPOINT=http://crew-minio-prod:9000
# MinIO Credentials (get from /var/www/apps/minio-storage/.env)
MINIO_KEY=your_minio_root_user
MINIO_SECRET=your_minio_root_password
# Bucket name
MINIO_BUCKET=crewsportswear
# Region (required for S3 compatibility)
MINIO_REGION=us-east-1
# Use path-style endpoint (required for MinIO)
MINIO_USE_PATH_STYLE=true
# Public URL for accessing files (use your actual domain)
MINIO_URL=https://minio.crewsportswear.app

11
.gitignore vendored
View File

@@ -1,3 +1,14 @@
/vendor
/node_modules
.env
# SSH Keys - Never commit private keys
*.ppk
*.pem
*.key
id_rsa
id_dsa
id_ecdsa
id_ed25519
_key/
.ssh/

17
Makefile Normal file
View File

@@ -0,0 +1,17 @@
COMPOSE_LOCAL = docker compose -f docker-compose.local.yml
# ── Local stack (local MariaDB) ───────────────────────────────────────────────
up:
$(COMPOSE_LOCAL) up --build
down:
$(COMPOSE_LOCAL) down
# ── Local stack with SSH tunnel to remote DB ──────────────────────────────────
up-ssh:
$(COMPOSE_LOCAL) --env-file .env.local --profile ssh-db up --build
down-ssh:
$(COMPOSE_LOCAL) --env-file .env.local --profile ssh-db down
.PHONY: up down up-ssh down-ssh

View File

@@ -22,8 +22,11 @@ class Handler extends ExceptionHandler {
* @param \Exception $e
* @return void
*/
public function report(Exception $e)
public function report($e)
{
if (!$e instanceof Exception) {
$e = new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
}
return parent::report($e);
}
@@ -31,11 +34,14 @@ class Handler extends ExceptionHandler {
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @param mixed $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
public function render($request, $e)
{
if (!$e instanceof Exception) {
$e = new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
}
return parent::render($request, $e);
}

View File

@@ -31,7 +31,7 @@ class MainController extends Controller {
foreach ($fetchData as $row) {
?>
<div class="col-md-3 col-sm-6 col-xs-12 list-sport">
<a href="<?php echo url('sports') . "/" . $row->URL; ?>"><img src="<?php echo config('site_config.uploads') . 'sports-thumbnails/' . $row->Thumbnail; ?>" alt="" class="img img-responsive product-center" /></a>
<a href="<?php echo url('sports') . "/" . $row->URL; ?>"><img src="<?php echo minio_url('uploads/images/sports-thumbnails/' . $row->Thumbnail); ?>" alt="" class="img img-responsive product-center" /></a>
<h3 class="text-center sports-title"><?php echo $row->SportsName ?></h3>
</div>
<?php

View File

@@ -5,6 +5,7 @@ use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Request1;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Models\PrintPatternModel;
use App\Models\SizesModel;
@@ -46,7 +47,7 @@ class PrintPatternController extends Controller {
$NewImageName = $templateSize.'.'.$imageExt;
$thumbnail = "uniform-templates/".$templatecode."/".$templateType."/SIZES/" . $NewImageName;
$thumbnail = "uploads/images/uniform-templates/".$templatecode."/".$templateType."/SIZES/" . $NewImageName;
$data = array(
'TemplateCode' => $templatecode,
@@ -58,9 +59,7 @@ class PrintPatternController extends Controller {
$i = $m->insertPrintPattern($data);
//var_dump($data);
if($i){
$r = $request->file('preview_print_template')->move(
base_path() . "/public/images/uniform-templates/".$templatecode."/".$templateType."/SIZES/", $NewImageName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templatecode.'/'.$templateType.'/SIZES/'.$NewImageName, file_get_contents($request->file('preview_print_template')->getRealPath()));
echo '<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-check"></i> Success!</h4>

View File

@@ -4,6 +4,7 @@ use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Models\TemplatesModel;
use App\Models\SportsModel;
use App\Models\PrintPatternModel;
@@ -48,7 +49,7 @@ class TemplatesController extends Controller {
<h3><?php echo $row->TemplateName ?></h3>
</div>
<div class="sports-border">
<a href=""><img src="<?php echo url('public') . "/" . $row->Thumbnail ?>" alt="Sports" height="400px;" class="img img-responsive product-center" /></a>
<a href=""><img src="<?php echo minio_url($row->Thumbnail) ?>" alt="Sports" height="400px;" class="img img-responsive product-center" /></a>
<div class="sport-edit-btn">
<a href="<?php echo url('admin/templates') . "/edit/" . $row->TemplateCode . "/" ?>" class="btn btn-primary btn-block"><i class="fa fa-edit"></i> Edit</a>
</div>
@@ -129,15 +130,13 @@ class TemplatesController extends Controller {
if($i){
$request->file('tempateImage')->move(
base_path() . '/public/images/templates/thumbnail', $NewImageName
);
Storage::disk('minio')->put('images/templates/thumbnail/' . $NewImageName, file_get_contents($request->file('tempateImage')->getRealPath()));
//for front jersey
if(!empty($request->file('svgJerseyFront')->getClientOriginalName())){
$svgName = $request->file('svgJerseyFront')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
//var_dump($svgThumbnail);
$Templatedata = array(
'TemplateCode' => $templateCode,
@@ -149,16 +148,14 @@ class TemplatesController extends Controller {
$i = $m->insertTempaltePaths($Templatedata);
if($i){
$request->file('svgJerseyFront')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgJerseyFront')->getRealPath()));
}
}
if(!empty($request->file('svgJerseyBack')->getClientOriginalName())){
$svgName = $request->file('svgJerseyBack')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$Templatedata = array(
'TemplateCode' => $templateCode,
@@ -170,16 +167,14 @@ class TemplatesController extends Controller {
$i = $m->insertTempaltePaths($Templatedata);
if($i){
$request->file('svgJerseyBack')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgJerseyBack')->getRealPath()));
}
}
if(!empty($request->file('svgShortRight')->getClientOriginalName())){
$svgName = $request->file('svgShortRight')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$Templatedata = array(
'TemplateCode' => $templateCode,
@@ -191,16 +186,14 @@ class TemplatesController extends Controller {
$i = $m->insertTempaltePaths($Templatedata);
if($i){
$request->file('svgShortRight')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgShortRight')->getRealPath()));
}
}
if(!empty($request->file('svgShortLeft')->getClientOriginalName())){
$svgName = $request->file('svgShortLeft')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$Templatedata = array(
'TemplateCode' => $templateCode,
@@ -212,9 +205,7 @@ class TemplatesController extends Controller {
$i = $m->insertTempaltePaths($Templatedata);
if($i){
$request->file('svgShortLeft')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgShortLeft')->getRealPath()));
}
}
@@ -270,9 +261,7 @@ class TemplatesController extends Controller {
'PatternId' => $getSkins
);
$request->file('tempateImage')->move(
base_path() . '/public/images/templates/thumbnail', $NewImageName
);
Storage::disk('minio')->put('images/templates/thumbnail/' . $NewImageName, file_get_contents($request->file('tempateImage')->getRealPath()));
}else{
@@ -298,7 +287,7 @@ class TemplatesController extends Controller {
//echo 'meron jerset front';
$svgName = $request->file('svgJerseyFront')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$Templatedata = array(
'Type' => 'Jersey',
@@ -308,9 +297,7 @@ class TemplatesController extends Controller {
$i = $m->updateTemplatePaths($Templatedata, $post['id_svgJerseyFront']);
if($i){
$request->file('svgJerseyFront')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgJerseyFront')->getRealPath()));
//echo 'image move success';
}
}
@@ -318,7 +305,7 @@ class TemplatesController extends Controller {
if (array_key_exists('svgJerseyBack', $post)) {
$svgName = $request->file('svgJerseyBack')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$Templatedata = array(
'Type' => 'Jersey',
@@ -327,16 +314,13 @@ class TemplatesController extends Controller {
);
$i = $m->updateTemplatePaths($Templatedata, $post['id_svgJerseyBack']);
if($i){
$request->file('svgJerseyBack')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgJerseyBack')->getRealPath()));
}
}
if (array_key_exists('svgShortRight', $post)) {
$svgName = $request->file('svgShortRight')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$Templatedata = array(
'Type' => 'Shorts',
@@ -346,15 +330,13 @@ class TemplatesController extends Controller {
$i = $m->updateTemplatePaths($Templatedata, $post['id_svgShortRight']);
if($i){
$request->file('svgShortRight')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgShortRight')->getRealPath()));
}
}
if (array_key_exists('svgShortLeft', $post)) {
$svgName = $request->file('svgShortLeft')->getClientOriginalName();
$svgThumbnail = "uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$svgThumbnail = "uploads/images/uniform-templates/".$templateCode."/DISPLAY/".$svgName;
$Templatedata = array(
'Type' => 'Shorts',
@@ -364,9 +346,7 @@ class TemplatesController extends Controller {
$i = $m->updateTemplatePaths($Templatedata, $post['id_svgShortLeft']);
if($i){
$request->file('svgShortLeft')->move(
base_path() . '/public/images/uniform-templates/'.$templateCode. '/DISPLAY' , $svgName
);
Storage::disk('minio')->put('uploads/images/uniform-templates/'.$templateCode.'/DISPLAY/'.$svgName, file_get_contents($request->file('svgShortLeft')->getRealPath()));
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class TestEmailController extends Controller
{
public function show()
{
return view('test-email', ['token' => csrf_token()]);
}
public function send(Request $request)
{
$this->validate($request, [
'recipient' => 'required|email',
]);
$recipient = $request->input('recipient');
$config = [
'driver' => config('mail.driver'),
'host' => config('mail.host'),
'port' => config('mail.port'),
'username' => config('mail.username'),
'encryption' => config('mail.encryption'),
];
try {
Mail::send('emails.test', ['config' => $config, 'recipient' => $recipient], function ($message) use ($recipient) {
$message->from('no-reply@crewsportswear.com', 'CREW Sportswear');
$message->to($recipient)->subject('CREW Sportswear — Test Email');
});
$status = 'success';
$message = 'Test email sent successfully to ' . $recipient . '.';
} catch (\Throwable $e) {
$status = 'danger';
$message = 'Failed to send email: ' . $e->getMessage();
}
return redirect()->back()->with('status', $status)->with('message', $message);
}
}

View File

@@ -367,14 +367,11 @@ class DesignerController extends Controller {
?>
<div class="form-group col-md-3">
<div class="thumbnail clipart-thumnail">
<a href="#" class="img-clipart" data-link="<?php echo $row->SVGFilename; ?>"><img src="<?php echo config('site_config.uploads') . 'cliparts/'. $row->SVGFilename; ?>" width="100%"></a>
<a href="#" class="img-clipart" data-link="<?php echo $row->SVGFilename; ?>"><img src="<?php echo minio_url('uploads/images/cliparts/') . $row->SVGFilename; ?>" width="100%"></a>
</div>
</div>
<?php
}
}
public function clipartProperties(Request $request)
@@ -829,8 +826,9 @@ class DesignerController extends Controller {
}
$arr = array(
'small' => config('site_config.uploads') . $small ,
'large' => config('site_config.uploads') . $large
'small' => minio_url('uploads/images') . $small ,
'large' => minio_url('uploads/images') . $large
);
return json_encode($arr);

View File

@@ -41,6 +41,10 @@ Route::get('cart', ['as' => 'cart', 'uses' => 'teamstore\TeamStoreController@car
Route::get('/checkout', 'teamstore\TeamStoreController@checkout');
Route::get('/mail', 'teamstore\TeamStoreController@mail');
// Test email page
Route::get('/test-email', 'TestEmailController@show');
Route::post('/test-email/send', 'TestEmailController@send');
Route::get('/designer/{templateid}', 'designer\DesignerController@index');
Route::get('/designer/preview/{designCode}', 'designer\DesignerController@getDesign');

33
app/helpers.php Normal file
View File

@@ -0,0 +1,33 @@
<?php
if (!function_exists('minio_url')) {
/**
* Generate MinIO URL for a file
*
* @param string $path File path relative to bucket
* @return string Full MinIO URL
*/
function minio_url($path)
{
$bucket = env('MINIO_BUCKET', 'crewsportswear');
$baseUrl = env('MINIO_URL', 'https://minio.crewsportswear.app');
// Remove leading slash if present
$path = ltrim($path, '/');
return $baseUrl . '/' . $bucket . '/' . $path;
}
}
if (!function_exists('minio_image_url')) {
/**
* Generate MinIO URL for an image in uploads/images/
*
* @param string $filename Image filename
* @return string Full MinIO URL
*/
function minio_image_url($filename)
{
return minio_url('uploads/images/' . $filename);
}
}

View File

@@ -11,7 +11,8 @@
"guzzlehttp/guzzle": "~5.0",
"google/recaptcha": "~1.1",
"spatie/laravel-analytics": "^1.4",
"league/flysystem-sftp": "^1.0"
"league/flysystem-sftp": "^1.0",
"aws/aws-sdk-php": "~3.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
@@ -24,7 +25,10 @@
],
"psr-4": {
"App\\": "app/"
}
},
"files": [
"app/helpers.php"
]
},
"autoload-dev": {
"classmap": [

View File

@@ -77,7 +77,7 @@ return [
'port' => 22,
'username' => 'root',
'password' => '',
'privateKey' => '/var/www/html/_key/instance2/root.ppk',
'privateKey' => '/var/keys/root.ppk',
'root' => '/var/www/html/images',
'timeout' => 10
],
@@ -86,6 +86,18 @@ return [
'driver' => 'local',
'root' => '/var/www/html/uploads/images',
],
'minio' => [
'driver' => 's3',
'key' => env('MINIO_KEY'),
'secret' => env('MINIO_SECRET'),
'region' => env('MINIO_REGION', 'us-east-1'),
'bucket' => env('MINIO_BUCKET', 'crewsportswear'),
'endpoint' => env('MINIO_ENDPOINT'),
'use_path_style_endpoint' => env('MINIO_USE_PATH_STYLE', true),
'url' => env('MINIO_URL', 'https://minio.crewsportswear.app'),
],
],
];
];

View File

@@ -18,6 +18,7 @@ return [
'prod_private_server_ip' => env('https://crewsportswear.app', 'https://crewsportswear.app'),
'images_url' => env('https://crewsportswear.app:5955', 'https://crewsportswear.app:5955'),
'minio_url' => env('MINIO_URL', 'https://minio.crewsportswear.app/crewsportswear'),
'uploads' => env('https://crewsportswear.com/uploads/images/', 'https://crewsportswear.com/uploads/images/'), // local

View File

@@ -31,6 +31,7 @@ services:
volumes:
- ./storage:/var/www/html/storage
- ./public/uploads:/var/www/html/public/uploads
- /var/crew-keys:/var/keys:ro
labels:
- "traefik.enable=true"
# Development environment (dev.crewsportswear.app)

View File

@@ -1,3 +1,19 @@
# ─────────────────────────────────────────────────────────────────────────────
# Local development stack
#
# Default (local MariaDB):
# docker compose -f docker-compose.local.yml up --build
#
# Remote DB via SSH private-key tunnel:
# 1. Set SSH_HOST, SSH_USER, SSH_KEY_PATH, SSH_DB_REMOTE_HOST,
# SSH_DB_REMOTE_PORT (and DB_* creds) in .env.local
# 2. docker compose -f docker-compose.local.yml --profile ssh-db up --build
# The app will talk to db-tunnel (port 3306) instead of the local db.
#
# App: http://localhost:8082
# phpMyAdmin: http://localhost:8083
# ─────────────────────────────────────────────────────────────────────────────
services:
db:
image: mariadb:10.6
@@ -29,11 +45,7 @@ services:
- APP_DEBUG=true
- APP_URL=http://localhost:8082
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_PORT=3306
- DB_DATABASE=crewsportswear
- DB_USERNAME=crewsportswear
- DB_PASSWORD=secret
- DB_PORT=${DB_PORT:-3306}
- PROD_PRIVATE=http://localhost:8082
- IMAGES_URL=http://localhost:8082
- UPLOAD_URL=http://localhost:8082/uploads/
@@ -48,15 +60,73 @@ services:
- ANALYTICS_SITE_ID=
- ANALYTICS_CLIENT_ID=
- ANALYTICS_SERVICE_EMAIL=
# MinIO S3 Storage (connect to production MinIO for testing)
- MINIO_ENDPOINT=https://minio.crewsportswear.app
- MINIO_KEY=${MINIO_KEY:-minioadmin}
- MINIO_SECRET=${MINIO_SECRET:-minioadmin}
- MINIO_BUCKET=crewsportswear
- MINIO_REGION=us-east-1
- MINIO_USE_PATH_STYLE=false
- MINIO_URL=https://minio.crewsportswear.app
# DB_HOST defaults to local container; set to db-tunnel in .env.local for SSH mode
- DB_HOST=${DB_HOST:-db}
- DB_DATABASE=${DB_DATABASE:-crewsportswear}
- DB_USERNAME=${DB_USERNAME:-crewsportswear}
- DB_PASSWORD=${DB_PASSWORD:-secret}
env_file:
- path: .env.local
required: false
volumes:
- ./:/var/www/html
- ./storage:/var/www/html/storage
- ./public/uploads:/var/www/html/public/uploads
# Keep the vendor/ directory from the image — prevents the bind-mount
# from wiping out the composer install done during docker build.
- vendor_local:/var/www/html/vendor
depends_on:
- db
networks:
- crewsportswear-local
# ── SSH tunnel to a remote database ────────────────────────────────────────
# Activated only with: --profile ssh-db
# Requires SSH_HOST, SSH_USER, SSH_KEY_PATH (and optionally SSH_PORT,
# SSH_DB_REMOTE_HOST, SSH_DB_REMOTE_PORT) set in .env.local.
db-tunnel:
profiles:
- ssh-db
image: alpine:3.19
container_name: crewsportswear_db_tunnel
restart: unless-stopped
environment:
- SSH_HOST=${SSH_HOST}
- SSH_PORT=${SSH_PORT:-22}
- SSH_USER=${SSH_USER:-root}
- SSH_DB_REMOTE_HOST=${SSH_DB_REMOTE_HOST:-127.0.0.1}
- SSH_DB_REMOTE_PORT=${SSH_DB_REMOTE_PORT:-3306}
volumes:
# Mount your private key read-only; path configured in .env.local
- ${SSH_KEY_PATH:-~/.ssh/id_rsa}:/ssh/id_rsa:ro
command:
- sh
- -c
- |
apk add --no-cache openssh-client
cp /ssh/id_rsa /tmp/id_rsa
chmod 600 /tmp/id_rsa
echo "Starting SSH tunnel to $$SSH_HOST..."
exec ssh -N \
-o StrictHostKeyChecking=no \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes \
-i /tmp/id_rsa \
-L "0.0.0.0:3306:$$SSH_DB_REMOTE_HOST:$$SSH_DB_REMOTE_PORT" \
-p "$$SSH_PORT" \
"$$SSH_USER@$$SSH_HOST"
networks:
- crewsportswear-local
phpmyadmin:
image: arm64v8/phpmyadmin
platform: linux/arm64
@@ -79,3 +149,4 @@ networks:
volumes:
db_data:
vendor_local:

View File

@@ -6,7 +6,7 @@ services:
environment:
- APP_ENV=${APP_ENV:-production}
- APP_DEBUG=${APP_DEBUG:-false}
- APP_URL=${APP_URL:-https://dev-crew.crewsportswear.app}
- APP_URL=${APP_URL:-https://crewsportswear.com}
- DB_CONNECTION=mysql
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT:-3306}
@@ -31,19 +31,20 @@ services:
volumes:
- ./storage:/var/www/html/storage
- ./public/uploads:/var/www/html/public/uploads
- /var/crew-keys:/var/keys:ro
labels:
- "traefik.enable=true"
# Production environment (dev-crew.crewsportswear.app) - Uses Let's Encrypt
- "traefik.http.routers.crewsportswear-prod.rule=Host(`dev-crew.crewsportswear.app`)"
# Production environment (crewsportswear.com) - Uses paid SSL certificate
- "traefik.http.routers.crewsportswear-prod.rule=Host(`crewsportswear.com`)"
- "traefik.http.routers.crewsportswear-prod.entrypoints=websecure"
- "traefik.http.routers.crewsportswear-prod.tls=true"
- "traefik.http.routers.crewsportswear-prod.tls.certresolver=le"
- "traefik.http.services.crewsportswear-prod.loadbalancer.server.port=80"
# HTTP to HTTPS redirect
- "traefik.http.routers.crewsportswear-prod-http.rule=Host(`dev-crew.crewsportswear.app`)"
- "traefik.http.routers.crewsportswear-prod-http.rule=Host(`crewsportswear.com`)"
- "traefik.http.routers.crewsportswear-prod-http.entrypoints=web"
- "traefik.http.routers.crewsportswear-prod-http.middlewares=https-redirect"
- "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
networks:
- traefik-public
- crew-app-net

View File

@@ -13,5 +13,11 @@ mkdir -p bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache
# Install/update Composer dependencies if vendor is missing or composer.json changed
if [ ! -f vendor/autoload.php ]; then
echo "vendor/autoload.php not found — running composer install..."
composer install --no-interaction --prefer-dist
fi
# Execute the main command
exec "$@"

View File

@@ -0,0 +1,90 @@
/**
* Augments canvas by assigning to `onObjectMove` and `onAfterRender`.
* This kind of sucks because other code using those methods will stop functioning.
* Need to fix it by replacing callbacks with pub/sub kind of subscription model.
* (or maybe use existing fabric.util.fire/observe (if it won't be too slow))
*/
function initCenteringGuidelines(canvas) {
var canvasWidth = canvas.getWidth(),
canvasHeight = canvas.getHeight(),
canvasWidthCenter = canvasWidth / 2,
canvasHeightCenter = canvasHeight / 2,
canvasWidthCenterMap = { },
canvasHeightCenterMap = { },
centerLineMargin = 4,
centerLineColor = 'rgba(255,0,241,0.5)',
centerLineWidth = 1,
ctx = canvas.getSelectionContext(),
viewportTransform;
for (var i = canvasWidthCenter - centerLineMargin, len = canvasWidthCenter + centerLineMargin; i <= len; i++) {
canvasWidthCenterMap[Math.round(i)] = true;
}
for (var i = canvasHeightCenter - centerLineMargin, len = canvasHeightCenter + centerLineMargin; i <= len; i++) {
canvasHeightCenterMap[Math.round(i)] = true;
}
function showVerticalCenterLine() {
showCenterLine(canvasWidthCenter + 0.5, 0, canvasWidthCenter + 0.5, canvasHeight);
}
function showHorizontalCenterLine() {
showCenterLine(0, canvasHeightCenter + 0.5, canvasWidth, canvasHeightCenter + 0.5);
}
function showCenterLine(x1, y1, x2, y2) {
ctx.save();
ctx.strokeStyle = centerLineColor;
ctx.lineWidth = centerLineWidth;
ctx.beginPath();
ctx.moveTo(x1 * viewportTransform[0], y1 * viewportTransform[3]);
ctx.lineTo(x2 * viewportTransform[0], y2 * viewportTransform[3]);
ctx.stroke();
ctx.restore();
}
var afterRenderActions = [],
isInVerticalCenter,
isInHorizontalCenter;
canvas.on('mouse:down', function () {
viewportTransform = canvas.viewportTransform;
});
canvas.on('object:moving', function(e) {
var object = e.target,
objectCenter = object.getCenterPoint(),
transform = canvas._currentTransform;
if (!transform) return;
isInVerticalCenter = Math.round(objectCenter.x) in canvasWidthCenterMap,
isInHorizontalCenter = Math.round(objectCenter.y) in canvasHeightCenterMap;
if (isInHorizontalCenter || isInVerticalCenter) {
object.setPositionByOrigin(new fabric.Point((isInVerticalCenter ? canvasWidthCenter : objectCenter.x), (isInHorizontalCenter ? canvasHeightCenter : objectCenter.y)), 'center', 'center');
}
});
canvas.on('before:render', function() {
if (canvas.contextTop) {
canvas.clearContext(canvas.contextTop);
}
});
canvas.on('after:render', function() {
if (isInVerticalCenter) {
showVerticalCenterLine();
}
if (isInHorizontalCenter) {
showHorizontalCenterLine();
}
});
canvas.on('mouse:up', function() {
// clear these values, to stop drawing guidelines once mouse is up
isInVerticalCenter = isInHorizontalCenter = null;
canvas.renderAll();
});
}

View File

@@ -1,23 +1,79 @@
## Laravel PHP Framework
# Crew Sportswear
[![Build Status](https://travis-ci.org/laravel/framework.svg)](https://travis-ci.org/laravel/framework)
[![Total Downloads](https://poser.pugx.org/laravel/framework/downloads.svg)](https://packagist.org/packages/laravel/framework)
[![Latest Stable Version](https://poser.pugx.org/laravel/framework/v/stable.svg)](https://packagist.org/packages/laravel/framework)
[![Latest Unstable Version](https://poser.pugx.org/laravel/framework/v/unstable.svg)](https://packagist.org/packages/laravel/framework)
[![License](https://poser.pugx.org/laravel/framework/license.svg)](https://packagist.org/packages/laravel/framework)
A custom sportswear and apparel e-commerce platform built with Laravel.
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. Laravel attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as authentication, routing, sessions, queueing, and caching.
## Production URL
Laravel is accessible, yet powerful, providing powerful tools needed for large, robust applications. A superb inversion of control container, expressive migration system, and tightly integrated unit testing support give you the tools you need to build any application with which you are tasked.
https://crewsportswear.com
## Official Documentation
## Requirements
Documentation for the framework can be found on the [Laravel website](http://laravel.com/docs).
- Docker & Docker Compose
- PHP 7.4+
- MySQL 5.7+
- Composer
- Node.js & NPM
## Contributing
## Installation
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](http://laravel.com/docs/contributions).
1. Clone the repository
2. Copy `.env.example` to `.env` and configure your environment variables
3. Install PHP dependencies:
```bash
composer install
```
4. Install Node dependencies:
```bash
npm install
```
5. Generate application key:
```bash
php artisan key:generate
```
6. Run migrations:
```bash
php artisan migrate
```
### License
## Docker Deployment
The Laravel framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
### Local Development
```bash
docker-compose -f docker-compose.local.yml up -d
```
### Development Environment
```bash
docker-compose -f docker-compose.dev.yml up -d
```
### Production Environment
```bash
docker-compose -f docker-compose.prod.yml up -d
```
The production environment uses Traefik as a reverse proxy with paid SSL certificate for crewsportswear.com.
## Features
- Custom sportswear design interface
- Product catalog and management
- Order processing and tracking
- User authentication and profiles
- Analytics integration
- Email notifications
- reCAPTCHA integration
## Environment Variables
Key environment variables (see `.env.example` for full list):
- `APP_ENV` - Application environment (local, development, production)
- `APP_URL` - Application URL
- `DB_*` - Database configuration
- `MAIL_*` - Mail server configuration
- `ANALYTICS_*` - Google Analytics configuration
- `CAPTCHA_*` - reCAPTCHA keys
## License
Proprietary - All rights reserved

View File

@@ -446,7 +446,7 @@
@foreach ($pattern_arrays as $i => $val)
<div class="item @if ($i == 0) active @endif">
<div class="btn-group patternBox ">
<button type="button" data-pattern-path="{{ $val[0]->SVGPath }}" class="patternThumbs btn" data-id="{{ $val[0]->PatternId }}" style="background-image:url('{{ config('site_config.uploads') }}{{ $val[0]->PatternThumbnail }}'); background-size:cover; background-repeat: no-repeat;" @if ($i == 0) disabled @endif> @if ($i == 0) <i class="fa fa-2 fa-check" aria-hidden="true"></i> @endif</button>
<button type="button" data-pattern-path="{{ $val[0]->SVGPath }}" class="patternThumbs btn" data-id="{{ $val[0]->PatternId }}" style="background-image:url('{{ minio_url('uploads/images/' . $val[0]->PatternThumbnail) }}'); background-size:cover; background-repeat: no-repeat;" @if ($i == 0) disabled @endif> @if ($i == 0) <i class="fa fa-2 fa-check" aria-hidden="true"></i> @endif</button>
</div>
</div>
@endforeach
@@ -546,7 +546,7 @@
@foreach ($pattern_arrays as $r => $val)
<div class="item @if ($r == 0) active @endif">
<div class="btn-group patternBox ">
<button type="button" data-pattern-path="{{ $val[0]->SVGPath }}" class="patternTrimThumbs patternTrim{{ $i }} btn" data-id="{{ $val[0]->PatternId }}" data-trim="{{ $i }}" style="background-image:url('{{ config('site_config.uploads') }}{{ $val[0]->PatternThumbnail }}'); background-size:cover; background-repeat: no-repeat;" @if ($r == 0) disabled @endif> @if ($r == 0) <i class="fa fa-2 fa-check" aria-hidden="true"></i> @endif</button>
<button type="button" data-pattern-path="{{ $val[0]->SVGPath }}" class="patternTrimThumbs patternTrim{{ $i }} btn" data-id="{{ $val[0]->PatternId }}" data-trim="{{ $i }}" style="background-image:url('{{ minio_url('uploads/images/' . $val[0]->PatternThumbnail) }}'); background-size:cover; background-repeat: no-repeat;" @if ($r == 0) disabled @endif> @if ($r == 0) <i class="fa fa-2 fa-check" aria-hidden="true"></i> @endif</button>
</div>
</div>
@endforeach
@@ -886,8 +886,8 @@
<script src="{{asset('/designer/js/custom-script.js')}}"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script src="https://rawgit.com/fabricjs/fabric.js/master/lib/centering_guidelines.js"></script>
<script src="https://rawgit.com/fabricjs/fabric.js/master/lib/aligning_guidelines.js"></script>
<script src="{{asset('/designer/js/centering_guidelines.js')}}"></script>
<script src="{{asset('/designer/js/aligning_guidelines.js')}}"></script>
<script>
$(document).ready(function() {
@@ -1306,7 +1306,7 @@
var patternSVGPath = $(this).attr('data-pattern-path');
var patternPath = "{{ config('site_config.uploads') }}" + patternSVGPath;
var patternPath = "{{ env('MINIO_URL', 'https://minio.crewsportswear.app') }}/{{ env('MINIO_BUCKET', 'crewsportswear') }}/" + patternSVGPath;
var SideAndPath = {!! json_encode($templatepaths_arrays) !!};
@@ -1383,7 +1383,7 @@
$(document).on('button click', '.patternTrimThumbs', function(){
var patternSVGPath = $(this).attr('data-pattern-path');
var patternPath = "{{ config('site_config.uploads') }}" + patternSVGPath;
var patternPath = "{{ env('MINIO_URL', 'https://minio.crewsportswear.app') }}/{{ env('MINIO_BUCKET', 'crewsportswear') }}/" + patternSVGPath;
var getTrimId = $(this).attr('data-trim');
var SideAndPath = {!! json_encode($templatepaths_arrays) !!};
@@ -1527,7 +1527,7 @@
var gradientIds = sideName+"_"+type+"_Gradients";
var gradientPrefix = sideName+"_"+type+"_";
var tempPath = "{{ config('site_config.uploads') }}" + pathLocation;
var tempPath = "{{ env('MINIO_URL', 'https://minio.crewsportswear.app') }}/{{ env('MINIO_BUCKET', 'crewsportswear') }}/" + pathLocation;
console.log(tempPath)
if(!document.getElementById(objectId))
return false;
@@ -1711,7 +1711,7 @@
var type = SideAndPath[i]['Type'];
var pathLocation = SideAndPath[i]['Path'];
var canvasName = "canvas_" + type + "_" + sideName;
var tempPath = "{{ config('site_config.uploads') }}" + pathLocation;
var tempPath = "{{ env('MINIO_URL', 'https://minio.crewsportswear.app') }}/{{ env('MINIO_BUCKET', 'crewsportswear') }}/" + pathLocation;
window['canvas_' + type + '_' + sideName] = new fabric.Canvas(canvasName);
var templateFormat = SideAndPath[i]['TemplateFormat'];
@@ -2043,9 +2043,9 @@
if(objType == "curvedText"){
if(obj.effect == "curved"){
$('#teamname_text_shape').html('Text Shape: <br><img src="{{ config('site_config.uploads') }}text-shapes-logo/curve-logo.png" height="30px">');
$('#teamname_text_shape').html('Text Shape: <br><img src="{{ minio_url('uploads/images/text-shapes-logo/curve-logo.png') }}" height="30px">');
}else if(obj.effect == "arc"){
$('#teamname_text_shape').html('Text Shape: <br><img src="{{ config('site_config.uploads') }}text-shapes-logo/arch-logo.png" height="30px">');
$('#teamname_text_shape').html('Text Shape: <br><img src="{{ minio_url('uploads/images/text-shapes-logo/arch-logo.png') }}" height="30px">');
}else{
$('#teamname_text_shape').html('Add text Shape');
}
@@ -3345,7 +3345,7 @@
function loadSVGClipart(dataUrl){
var k = 0;
var arrayPathId = [];
var svgUrl = "{{ config('site_config.uploads') }}cliparts/" + dataUrl;
var svgUrl = "{{ env('MINIO_URL', 'https://minio.crewsportswear.app') }}/{{ env('MINIO_BUCKET', 'crewsportswear') }}/uploads/images/cliparts/" + dataUrl;
fabric.loadSVGFromURL(svgUrl, function(objects, options) {
var clipart = fabric.util.groupSVGElements(objects, options );
clipart.set({

View File

@@ -407,7 +407,7 @@
<td align="left" style="width: 180px;">
@foreach($img_thumb as $img)
@if($img->ProductId == $item->ProductId)
<img style="height: 200px; overflow: hidden; object-fit: contain;" src="{{ config('site_config.images_url') }}/{{ $img->Image }}">
<img style="height: 200px; overflow: hidden; object-fit: contain;" src="{{ minio_url('images/' . $img->Image) }}">
@endif
@endforeach
</td>

View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test Email CREW Sportswear</title>
</head>
<body style="font-family: Arial, sans-serif; color: #333; padding: 20px;">
<h2 style="color: #d9534f;">CREW Sportswear Test Email</h2>
<p>This is a test email to verify that the mail configuration is working correctly.</p>
<p>Sent to: <strong>{{ $recipient }}</strong></p>
<hr>
<p style="font-size: 12px; color: #777;">
<strong>Mail Config Used:</strong><br>
Driver: {{ $config['driver'] }}<br>
Host: {{ $config['host'] }}<br>
Port: {{ $config['port'] }}<br>
Username: {{ $config['username'] }}<br>
Encryption: {{ $config['encryption'] }}
</p>
<hr>
<p style="font-size: 12px; color: #aaa;">This is an automated test message from CREW Sportswear.</p>
</body>
</html>

View File

@@ -122,13 +122,13 @@
</div>
<div style="border: 1px solid #e2e2e2; padding: 10px;">
<a @if($getSubtotal <= 0 ) disabled @endif href="{{ url('getCheckout') }}" class="btn btn-primary btn-block" style="background-color: #ffc300; border-color: #e2ad00; text-align: -webkit-center;" ><img src="{{asset('/public/images/paypal1.png')}}" class="img img-responsive" style="height:30px;"></a><br>
<a @if($getSubtotal <= 0 ) disabled @endif href="{{ url('getCheckout') }}" class="btn btn-primary btn-block" style="background-color: #ffc300; border-color: #e2ad00; text-align: -webkit-center;" ><img src="{{asset('/images/paypal1.png')}}" class="img img-responsive" style="height:30px;"></a><br>
<a href="{{ url('teamstore') . '/' . $store_array[0]->StoreUrl }}" class="btn btn-default btn-block" type="submit">Continue Shopping</a>
</div>
</div>
<div class="col-md-8 col-md-pull-4">
<div style="border: 1px solid #e2e2e2; padding: 10px;">
<h4><img height="30px" class="store-logo" src="{{ config('site_config.uploads') . 'teamstore/'. $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreLogo }}"> {{ $store_array[0]->StoreName }}</h4>
<h4><img height="30px" class="store-logo" src="{{ minio_url('uploads/images/teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreLogo) }}"> {{ $store_array[0]->StoreName }}</h4>
</div>
@foreach($item_group as $item)
@if($item->VoucherId == null)
@@ -138,7 +138,7 @@
<div class="text-center">
@foreach($img_thumb as $img)
@if($img->ProductId == $item->ProductId)
<img class="previewImage" src="{{ config('site_config.images_url') }}/{{ $img->Image }}">
<img class="previewImage" src="{{ minio_url('images/' . $img->Image) }}">
@endif
@endforeach
</div>

View File

@@ -64,7 +64,7 @@
<table class="table">
<tr>
<td rowspan="2" class="text-center"><img class="previewImage" src="http://{{ config('site_config.images_url') }}/{{ $item->Image }} "></td>
<td rowspan="2" class="text-center"><img class="previewImage" src="{{ minio_url('images/' . $item->Image) }}"></td>
<td colspan="5">
<h4>{{ $item->ProductName }} {{ $itemOrder }} <br>Price: ${{ $item->Price }}</h4>
</td>

View File

@@ -19,7 +19,7 @@
<div class="col-md-3 col-sm-6 col-xs-12 list-sport">
<div class="thumb-border">
<a href="{{ url() }}/{{ Request::path() }}/{{ $r->Id }}">
<img src="{{ config('site_config.uploads') . 'sports-category/' . $r->Thumbnail }}" alt="{{ $r->Category }}" class="image" />
<img src="{{ minio_url('uploads/images/sports-category/' . $r->Thumbnail) }}" alt="{{ $r->Category }}" class="image" />
</a>
</div>
<div class="text-center">

View File

@@ -24,7 +24,7 @@
<div class="thumb-border" style="border:1px solid #e2e2e2; padding: 5px;">
<a href="{{ url('/designer') }}/{{ md5($r->TemplateCode) }}">
<img src="{{ config('site_config.uploads') . $r->Thumbnail}}" alt="" class="image" />
<img src="{{ minio_url('uploads/images/' . $r->Thumbnail) }}" alt="" class="image" />
</a>
<!-- <div class="overlay">
<div class="text" style="font-family:Academic M54;"><a href="">{{$r->TemplateName}}</a></div>

View File

@@ -86,9 +86,9 @@
padding-top: 20px;
padding-bottom: 20px;
@if($store_array[0]->StoreBanner == null)
background-image: url("{{ config('site_config.uploads') . 'teamstore/store-banner-dark.png' }}");
background-image: url("{{ minio_url('uploads/images/teamstore/store-banner-dark.png') }}");
@else
background-image: url("{{ config('site_config.uploads') . 'teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreBanner }}");
background-image: url("{{ minio_url('uploads/images/teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreBanner) }}");
@endif
background-color: #f3f3f3;
background-position: center;
@@ -127,6 +127,126 @@
overflow: hidden;
text-overflow: ellipsis;
}
/* ── Category nav ──────────────────────────────────────────────────────── */
.cat-nav {
background: #f8f8f8;
border-bottom: 2px solid #e0e0e0;
padding: 0;
margin-bottom: 24px;
}
.cat-nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
}
.cat-nav > ul > li {
position: relative;
}
.cat-nav > ul > li > a {
display: block;
padding: 14px 20px;
font-weight: 700;
font-size: 13px;
text-transform: uppercase;
color: #222;
text-decoration: none;
letter-spacing: .5px;
border-bottom: 3px solid transparent;
transition: border-color .2s, color .2s;
}
.cat-nav > ul > li > a:hover,
.cat-nav > ul > li > a.active {
color: #4B8E4B;
border-bottom-color: #4B8E4B;
}
/* sub-category dropdown */
.cat-nav .sub-menu {
display: none;
position: absolute;
top: 100%;
left: 0;
min-width: 200px;
background: #fff;
border: 1px solid #ddd;
border-top: 3px solid #4B8E4B;
box-shadow: 0 4px 12px rgba(0,0,0,.12);
z-index: 999;
list-style: none;
margin: 0;
padding: 6px 0;
}
.cat-nav > ul > li:hover .sub-menu {
display: block;
}
.cat-nav .sub-menu li a {
display: block;
padding: 9px 18px;
font-size: 13px;
color: #333;
text-decoration: none;
white-space: nowrap;
}
.cat-nav .sub-menu li a:hover,
.cat-nav .sub-menu li a.active {
background: #f0f9f0;
color: #4B8E4B;
}
.cat-count {
display: inline-block;
background: #ddd;
border-radius: 10px;
font-size: 11px;
padding: 1px 7px;
margin-left: 4px;
vertical-align: middle;
}
/* ── League / conference pill filter (sub-sub-category) ─────────────────── */
.league-filter {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 10px 0 14px;
margin-bottom: 18px;
border-bottom: 1px solid #e8e8e8;
align-items: center;
}
.league-filter .lf-label {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
color: #888;
letter-spacing: .5px;
margin-right: 4px;
white-space: nowrap;
}
.league-filter a {
display: inline-block;
padding: 5px 14px;
border-radius: 20px;
background: #f0f0f0;
color: #333;
font-size: 12px;
font-weight: 600;
text-decoration: none;
white-space: nowrap;
border: 1px solid #ddd;
transition: background .2s, color .2s, border-color .2s;
}
.league-filter a:hover {
background: #e0f2e0;
color: #4B8E4B;
border-color: #4B8E4B;
}
.league-filter a.active {
background: #4B8E4B;
color: #fff;
border-color: #4B8E4B;
}
[v-cloak] { display: none; }
</style>
<div class="container">
@@ -150,80 +270,277 @@
<h2>FEATURED PRODUCTS</h2>
</div>
</div>
<div class="row">
{{-- ── Vue category + product grid ─────────────────────────────────────── --}}
<script>
window._tsProducts = {!! json_encode(
collect($product_array)
->where('PrivacyStatus', 'public')
->map(function($p) use ($thumbnails) {
$thumbList = isset($thumbnails) ? $thumbnails : [];
$thumb = collect($thumbList)->filter(function($t) use ($p) {
return $t['product_id'] == $p->Id;
})->first();
return [
'id' => $p->Id,
'name' => $p->ProductName,
'price' => $p->ProductPrice,
'url' => $p->ProductURL,
'img' => $thumb ? $thumb['thumb'] : 'product-image-placeholder.png',
'folder'=> $thumb ? $thumb['folder'] : '',
];
})->values()->toArray(),
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT
) !!};
window._tsStore = {
url : {!! json_encode($store_array[0]->StoreUrl, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) !!},
currency : {!! json_encode($store_array[0]->StoreCurrency, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) !!},
minoBase : {!! json_encode(rtrim(config('filesystems.disks.minio.url', ''), '/') . '/' . env('MINIO_BUCKET', 'crewsportswear') . '/', JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) !!},
};
</script>
<div id="ts-app" v-cloak>
{{-- ── Category nav ── --}}
<nav class="cat-nav" v-if="categories.length > 0">
<ul>
<li>
<a href="#" :class="{active: activeCategory===null && activeSubCategory===null}"
@click.prevent="activeCategory=null; activeSubCategory=null">
All
<span class="cat-count">@{{ totalPublic }}</span>
</a>
</li>
<li v-for="cat in categories" :key="cat.name">
<a href="#"
:class="{active: activeCategory===cat.name}"
@click.prevent="selectCategory(cat.name)">
@{{ cat.name }}
<span class="cat-count">@{{ cat.count }}</span>
</a>
<ul class="sub-menu" v-if="cat.subs.length > 0">
<li v-for="sub in cat.subs" :key="sub.name">
<a href="#"
:class="{active: activeCategory===cat.name && activeSubCategory===sub.name}"
@click.prevent="selectSub(cat.name, sub.name)">
@{{ sub.name }}
<span class="cat-count">@{{ sub.count }}</span>
</a>
</li>
</ul>
</li>
</ul>
</nav>
{{-- ── League / conference pill filter ── --}}
<div class="league-filter" v-if="isLeagueStore && activeCategory !== null && leagues.length > 0">
<span class="lf-label">League / Conf:</span>
<a href="#"
:class="{active: activeLeague === null}"
@click.prevent="activeLeague = null">All</a>
<a href="#"
v-for="lg in leagues" :key="lg.name"
:class="{active: activeLeague === lg.name}"
@click.prevent="activeLeague = lg.name">
@{{ lg.name }}
<span class="cat-count">@{{ lg.count }}</span>
</a>
</div>
{{-- ── Announcements (kept outside loop) ── --}}
@if ($announcement->IsActive)
<div class="row">
<div class="col-md-12">
<div class="alert alert-info">
<p><b>Shop Announcements:</b></p>
{!! nl2br(e($announcement->Announcement)) !!}
</div>
</div>
</div>
</div>
@endif
@if($store_array[0]->Id == 174 || $store_array[0]->Id == 175 || $store_array[0]->Id == 178 || $store_array[0]->Id == 179 || $store_array[0]->Id == 177 || $store_array[0]->Id == 189 || $store_array[0]->Id == 176 || $store_array[0]->Id == 190 || $store_array[0]->Id == 191 || $store_array[0]->Id == 192 || $store_array[0]->Id == 194)
<div class="col-md-12">
<div class="alert alert-warning">
<p><b>Please read:</b></p>
1. All orders will be batch shipped to your school for pick up.<br>
2. Orders will be batch processed on a weekly basis, please allow 2-3 weeks for delivery.<br>
3. Masks and gaiters sold on Crew are not intended for medical use. Crew does not make any medical or health claims.<br>
4. Refunds and exchanges are not allowed due to the hygenic nature of the product.<br>
@if($store_array[0]->Id == 175)
5. $1 from every item sold will benefit the 2020-2021 Maine South Schoolwide Fundraiser.
@endif
</div>
</div>
@else
<div class="col-md-12">
<div class="alert alert-warning">
@if($store_array[0]->Id == 174 || $store_array[0]->Id == 175 || $store_array[0]->Id == 178 || $store_array[0]->Id == 179 || $store_array[0]->Id == 177 || $store_array[0]->Id == 189 || $store_array[0]->Id == 176 || $store_array[0]->Id == 190 || $store_array[0]->Id == 191 || $store_array[0]->Id == 192 || $store_array[0]->Id == 194)
<div class="row">
<div class="col-md-12">
<div class="alert alert-warning">
<p><b>Please read:</b></p>
1. Items purchased are made on demand. Orders will be shipped based on dates set by your store administrator.<br>
2. Store payments are processed through PayPal. A PayPal account is not required to make a purchase.<br>
@if($store_array[0]->Id == 222)
3. Orders will be batch processed on a monthly basis, please allow 4-6 weeks for delivery.<br>
@else
3. Orders will be batch processed on a weekly basis, please allow 2-3 weeks for delivery.<br>
1. All orders will be batch shipped to your school for pick up.<br>
2. Orders will be batch processed on a weekly basis, please allow 2-3 weeks for delivery.<br>
3. Masks and gaiters sold on Crew are not intended for medical use. Crew does not make any medical or health claims.<br>
4. Refunds and exchanges are not allowed due to the hygenic nature of the product.<br>
@if($store_array[0]->Id == 175)
5. $1 from every item sold will benefit the 2020-2021 Maine South Schoolwide Fundraiser.
@endif
4. We are currently only shipping to US locations. For international orders, please contact <b>orders@crewsportswear.com</b> if you'd like to place an order.<br>
5. Expect shipping delays due to COVID-19.<br>
6. All sales are final. No returns or exchanges will be accepted.<br><br>
<b>DISCLAIMER:</b> Masks and gaiters sold by Crew Sportswear are not intended for medical use. Crew Sportswear does not make any medical or health claims.
</div>
</div>
@endif
<!-- BEGIN PRODUCTS -->
@foreach($product_array as $i => $product)
@if($product->PrivacyStatus == "public")
@foreach($thumbnails as $t => $thumb)
@if($thumb['product_id'] == $product->Id)
@define $storeFolder = $thumb['folder']
@define $filename = $thumb['thumb']
@endif
@endforeach
<div class="col-md-3 col-sm-6">
<span class="thumbnail">
<a href="{{ url('teamstore') }}/{{ $store_array[0]->StoreUrl }}/product/{{ $product->ProductURL }}">
<img style="height: 201.84px;" src="{{ config('site_config.images_url') }}/{{ $filename }}" alt="{{ $product->ProductName }}" >
</a>
<h4 class="text-center product-name-holder">{{ $product->ProductName }}</h4>
<hr class="line">
<div class="row">
<div class="col-md-7 col-sm-7">
<p class="price">{{ $product->ProductPrice }} <small style="font-size: 15px;"> {{ $store_array[0]->StoreCurrency }}</small></p>
</div>
<div class="col-md-5 col-sm-5">
<a href="{{ url('teamstore') }}/{{ $store_array[0]->StoreUrl }}/product/{{ $product->ProductURL }}" class="btn btn-success right" > View Details</a>
</div>
</div>
</span>
</div>
@endif
@endforeach
<!-- END PRODUCTS -->
</div>
</div> <!-- cotainer -->
</div>
</div>
@endif
{{-- ── Product grid ── --}}
<div class="row">
<div class="col-md-12 text-center" v-if="filtered.length === 0">
<p style="margin:40px 0;color:#888;">No products found in this category.</p>
</div>
<div class="col-md-3 col-sm-6" v-for="p in filtered" :key="p.id">
<span class="thumbnail">
<a :href="productUrl(p)">
<img style="height:201.84px;" :src="imgUrl(p)" :alt="p.name">
</a>
<h4 class="text-center product-name-holder">@{{ p.name }}</h4>
<hr class="line">
<div class="row">
<div class="col-md-7 col-sm-7">
<p class="price">@{{ p.price }} <small style="font-size:15px;">@{{ store.currency }}</small></p>
</div>
<div class="col-md-5 col-sm-5">
<a :href="productUrl(p)" class="btn btn-success right">View Details</a>
</div>
</div>
</span>
</div>
</div>
</div>{{-- /ts-app --}}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script>
(function () {
// ── sport & item-type keyword maps ──────────────────────────────────
const SPORTS = [
'Basketball','Football','Soccer','Baseball','Softball',
'Volleyball','Hockey','Lacrosse','Wrestling','Tennis',
'Swimming','Track','Cross Country','Golf','Cheerleading',
'Dance','Rugby','Bowling','Gymnastics','Cycling',
];
const ITEMS = [
'Jersey','T-Shirt','Tee','Hoodie','Sweatshirt','Jacket',
'Shorts','Pants','Tank','Top','Pullover','Zip-Up',
'Hat','Cap','Beanie','Polo','Uniform','Warmup','Pinnie',
];
// ── league / conference keyword map ──────────────────────────────────
// Order matters: more specific phrases first
const LEAGUES = [
{ key: 'NBA', terms: ['nba'] },
{ key: 'NFL', terms: ['nfl'] },
{ key: 'MLB', terms: ['mlb'] },
{ key: 'NHL', terms: ['nhl'] },
{ key: 'MLS', terms: ['mls'] },
{ key: 'WNBA', terms: ['wnba'] },
{ key: 'Big Ten', terms: ['big ten','big10','big 10'] },
{ key: 'ACC', terms: ['acc'] },
{ key: 'SEC', terms: ['sec'] },
{ key: 'Big 12', terms: ['big 12','big12'] },
{ key: 'Pac-12', terms: ['pac-12','pac12','pac 12'] },
{ key: 'AAC', terms: ['aac'] },
{ key: 'CUSA', terms: ['cusa','c-usa'] },
{ key: 'MAC', terms: ['\bmac\b'] },
{ key: 'Sun Belt',terms: ['sun belt'] },
{ key: 'Mountain West', terms: ['mountain west','mwc'] },
];
function classify(name) {
const n = name.toLowerCase();
const sport = SPORTS.find(s => n.includes(s.toLowerCase())) || 'Other';
const item = ITEMS.find(i => n.includes(i.toLowerCase())) || 'Other';
let league = null;
for (const lg of LEAGUES) {
if (lg.terms.some(t => {
try { return new RegExp(t, 'i').test(n); } catch(e) { return n.includes(t); }
})) {
league = lg.key;
break;
}
}
return { sport, item, league };
}
const { createApp } = Vue;
const store = window._tsStore || { url:'', currency:'', minoBase:'' };
const allProducts = Array.isArray(window._tsProducts) ? window._tsProducts : [];
createApp({
data() {
return {
products : allProducts,
store : store,
activeCategory : null,
activeSubCategory: null,
activeLeague : null,
};
},
computed: {
totalPublic() {
return this.products.length;
},
isLeagueStore() {
return this.store.url === 'hi-five-franchise-store';
},
// Build [ { name:'Basketball', count:N, subs:[{name:'Jersey',count:N},...] }, ... ]
categories() {
const map = {};
this.products.forEach(p => {
const { sport, item } = classify(p.name);
if (!map[sport]) map[sport] = {};
map[sport][item] = (map[sport][item] || 0) + 1;
});
return Object.entries(map)
.sort((a,b) => a[0].localeCompare(b[0]))
.map(([name, subs]) => ({
name,
count: Object.values(subs).reduce((a,b) => a+b, 0),
subs: Object.entries(subs)
.sort((a,b) => a[0].localeCompare(b[0]))
.map(([s, count]) => ({ name: s, count }))
.filter(s => s.name !== 'Other' || Object.keys(subs).length === 1),
}));
},
// Available leagues for the currently active category (+ optional sub)
// Only computed for hi-five-franchise-store
leagues() {
if (!this.isLeagueStore) return [];
const map = {};
this.products.forEach(p => {
const { sport, item, league } = classify(p.name);
if (!league) return;
if (this.activeCategory && sport !== this.activeCategory) return;
if (this.activeSubCategory && item !== this.activeSubCategory) return;
map[league] = (map[league] || 0) + 1;
});
return Object.entries(map)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([name, count]) => ({ name, count }));
},
filtered() {
if (!this.activeCategory && !this.activeLeague) return this.products;
return this.products.filter(p => {
const { sport, item, league } = classify(p.name);
if (this.activeCategory && sport !== this.activeCategory) return false;
if (this.activeSubCategory && item !== this.activeSubCategory) return false;
if (this.isLeagueStore && this.activeLeague && league !== this.activeLeague) return false;
return true;
});
},
},
methods: {
selectCategory(cat) {
this.activeCategory = cat;
this.activeSubCategory = null;
this.activeLeague = null;
},
selectSub(cat, sub) {
this.activeCategory = cat;
this.activeSubCategory = sub;
this.activeLeague = null;
},
productUrl(p) {
return '/teamstore/' + store.url + '/product/' + p.url;
},
imgUrl(p) {
return store.minoBase + 'images/' + p.img;
},
},
}).mount('#ts-app');
})();
</script>
</div>{{-- /container --}}
@endsection

View File

@@ -234,13 +234,13 @@
@if($thumbnail->ImageClass == 'active')
<div class="active item text-center" data-slide-number="{{ $i }}">
<span class="zoom img-zoom">
<img style="height:400px;" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image }}">
<img style="height:400px;" src="{{ minio_url('images/' . $thumbnail->Image) }}">
</span>
</div>
@else
<div class="item text-center" data-slide-number="{{ $i }}">
<span class="zoom img-zoom">
<img style="height:400px;" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image }}">
<img style="height:400px;" src="{{ minio_url('images/' . $thumbnail->Image) }}">
</span>
</div>
@endif
@@ -269,7 +269,7 @@
@foreach($thumbnails_array as $thumbnail)
<li class="col-sm-3 col-xs-3">
<a class="thumbnail a_thumbnail {{ $thumbnail->ImageClass }}" id="carousel-selector-{{ $j }}">
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image }}"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $thumbnail->Image) }}"/>
</a>
</li>
@define $j++

View File

@@ -82,12 +82,12 @@
<div style="border: 1px solid #dddddd; padding: 5px;">
@if($store->Password != null )
<a class="thumbnail password-protected" href="#" data-store-id="{{ $store->Id }}" data-store-url="{{ $store->StoreUrl }}">
<img class="store-logo" src="{{ config('site_config.uploads') . 'teamstore/'. $store->ImageFolder . '/' . $store->StoreLogo }}">
<img class="store-logo" src="{{ minio_url('uploads/images/teamstore/' . $store->ImageFolder . '/' . $store->StoreLogo) }}">
</a>
<h4 style="border-top: 1px solid #dddddd; padding: 10px; font-size: 16px; font-weight: bold; text-transform: uppercase;" class="text-center">{{ $store->StoreName }} <i class="fa fa-lock" title="This store is password protected."></i></h4>
@else
<a class="thumbnail" href="{{ url('teamstore') . '/' . $store->StoreUrl }}">
<img class="store-logo" src="{{ config('site_config.uploads') . 'teamstore/' . $store->ImageFolder . '/' . $store->StoreLogo }}">
<img class="store-logo" src="{{ minio_url('uploads/images/teamstore/' . $store->ImageFolder . '/' . $store->StoreLogo) }}">
</a>
<h4 style="border-top: 1px solid #dddddd; padding: 10px; font-size: 16px; font-weight: bold; text-transform: uppercase;" class="text-center">{{ $store->StoreName }}</h4>
@endif

View File

@@ -0,0 +1,56 @@
@extends('layout.main')
@section('content')
<div class="row">
<div class="col-md-6 col-md-offset-3" style="margin-top: 40px; margin-bottom: 40px;">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong>Send Test Email</strong></h3>
</div>
<div class="panel-body">
@if (session('message'))
<div class="alert alert-{{ session('status') }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{{ session('message') }}
</div>
@endif
<!-- Mail Config Info -->
<div class="well well-sm" style="font-size: 12px;">
<strong>Current Mail Config</strong><br>
Driver: <code>{{ config('mail.driver') ?: '(not set)' }}</code><br>
Host: <code>{{ config('mail.host') ?: '(not set)' }}</code><br>
Port: <code>{{ config('mail.port') ?: '(not set)' }}</code><br>
Username: <code>{{ config('mail.username') ?: '(not set)' }}</code><br>
Encryption: <code>{{ config('mail.encryption') ?: '(not set)' }}</code>
</div>
<form method="POST" action="{{ url('test-email/send') }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="token" value="{{ $token }}">
<div class="form-group{{ $errors->has('recipient') ? ' has-error' : '' }}">
<label for="recipient">Recipient Email</label>
<input type="email"
name="recipient"
id="recipient"
class="form-control"
placeholder="you@example.com"
value="{{ old('recipient') }}"
required>
@if ($errors->has('recipient'))
<span class="help-block">{{ $errors->first('recipient') }}</span>
@endif
</div>
<button type="submit" class="btn btn-primary btn-block">
<i class="fa fa-envelope"></i> Send Test Email
</button>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -42,7 +42,7 @@
@foreach($array_client_designs as $row)
@foreach($array_template_paths as $key => $row1)
@if($key == 0)
<img src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-front-thumbnail.png" alt="{{ $row->DesignName }}" id="main-thumbnail" class="img img-responsive">
<img src="{{ minio_url('images/' . $row->DesignCode . '-front-thumbnail.png') }}" alt="{{ $row->DesignName }}" id="main-thumbnail" class="img img-responsive">
@endif
@endforeach
@endforeach
@@ -56,7 +56,7 @@
@if($key == 0)
<li class="col-sm-3 col-xs-3">
<a class="thumbnail a_thumbnail active">
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-front-thumbnail.png"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $row->DesignCode . '-front-thumbnail.png') }}"/>
</a>
<!-- <p>Select Default Thumbnail:</p>
<div class="text-center">
@@ -66,7 +66,7 @@
@else
<li class="col-sm-3 col-xs-3">
<a class="thumbnail a_thumbnail">
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-{{ strtolower($row1->Side) }}-thumbnail.png"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $row->DesignCode . '-' . strtolower($row1->Side) . '-thumbnail.png') }}"/>
</a>
<!-- <p>&nbsp;</p>
<div class="text-center">

View File

@@ -18,7 +18,7 @@
<!-- Control Sidebar Toggle Button -->
<li class="user user-menu">
<a href="#">
<img src="{{ config('site_config.uploads') . 'user/default-user.png' }}" class="user-image" alt="User Image">
<img src="{{ minio_url('uploads/images/user/default-user.png') }}" class="user-image" alt="User Image">
<span class="hidden-xs">{{ Auth::user()->username }}</span>
</a>
</li>

View File

@@ -32,7 +32,7 @@
@foreach($array_client_designs as $row)
<div class="col-md-3 col-sm-6">
<span class="thumbnail">
<img src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-front-thumbnail.png" alt="{{ $row->DesignName }}" >
<img src="{{ minio_url('images/' . $row->DesignCode . '-front-thumbnail.png') }}" alt="{{ $row->DesignName }}" >
<h4 class="design-name-holder">{{ $row->DesignName }}</h4>
<small>{{ date('F j, Y g:i a', strtotime($row->DateCreated)) }}</small>
<hr class="line">

View File

@@ -33,7 +33,7 @@
<div class="row">
<div class="col-md-2">
<div class="text-center">
<img class="previewImage" id="active_thumbnail" src="{{ config('site_config.images_url') . '/images/' . $array_thumbnail_display[0]->Image }}">
<img class="previewImage" id="active_thumbnail" src="{{ minio_url('images/' . $array_thumbnail_display[0]->Image) }}">
</div>
</div>
<div class="col-md-10">

View File

@@ -93,7 +93,7 @@
<div class="text-center">
@foreach($img_thumb as $img)
@if($img->ProductId == $item->ProductId)
<img class="previewImage" src="{{ config('site_config.images_url') }}/{{ $img->Image }}">
<img class="previewImage" src="{{ minio_url('images/' . $img->Image) }}">
@endif
@endforeach
</div>

View File

@@ -42,7 +42,7 @@
@foreach($array_client_designs as $row)
@foreach($array_template_paths as $key => $row1)
@if($key == 0)
<img src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-front-thumbnail.png" alt="{{ $row->DesignName }}" id="main-thumbnail" class="img img-responsive">
<img src="{{ minio_url('images/' . $row->DesignCode . '-front-thumbnail.png') }}" alt="{{ $row->DesignName }}" id="main-thumbnail" class="img img-responsive">
@endif
@endforeach
@endforeach
@@ -56,7 +56,7 @@
@if($key == 0)
<li class="col-sm-3 col-xs-3">
<a class="thumbnail a_thumbnail active">
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-front-thumbnail.png"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $row->DesignCode . '-front-thumbnail.png') }}"/>
</a>
<!-- <p>Select Default Thumbnail:</p>
<div class="text-center">
@@ -66,7 +66,7 @@
@else
<li class="col-sm-3 col-xs-3">
<a class="thumbnail a_thumbnail">
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-{{ strtolower($row1->Side) }}-thumbnail.png"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $row->DesignCode . '-' . strtolower($row1->Side) . '-thumbnail.png') }}"/>
</a>
<!-- <p>&nbsp;</p>
<div class="text-center">

View File

@@ -4,7 +4,7 @@
<!-- Sidebar user panel -->
<div class="user-panel">
<div class="pull-left image">
<img src="{{ config('site_config.uploads') . 'user/default-user.png' }}" class="img-circle" alt="User Image">
<img src="{{ minio_url('uploads/images/user/default-user.png') }}" class="img-circle" alt="User Image">
</div>
<div class="pull-left info">
<p>{{ Auth::user()->name }}</p>

View File

@@ -59,7 +59,7 @@
<div class="col-md-3 col-sm-6">
<div class="thumbnail" >
<a href="{{ url('user/store-items/item') }}/{{ $product->ProductURL }}">
<img style="height:200px" src="{{ config('site_config.images_url') }}/{{ $filename . '?t=' . time() }}" alt="{{ $product->ProductName }}" >
<img style="height:200px" src="{{ minio_url('images/' . $filename) . '?t=' . time() }}" alt="{{ $product->ProductName }}" >
</a>
<hr class="line">
<div class="pull-right">

View File

@@ -63,7 +63,7 @@
<div id="{{ 'order_number_' . $product->Id }}">
<div class="thumbnail" >
<a href="#">
<img style="height:200px" src="{{ config('site_config.images_url') }}/{{ $filename . '?t=' . time() }}" alt="{{ $product->ProductName }}" >
<img style="height:200px" src="{{ minio_url('images/' . $filename) . '?t=' . time() }}" alt="{{ $product->ProductName }}" >
</a>
<hr class="line">
<div class="pull-right">

View File

@@ -63,8 +63,8 @@
<div class="col-sm-8">
<p>Store Logo Preview:</p>
<div class="store-logo-holder">
<a href="{{ config('site_config.uploads') . 'teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreLogo }}?v={{ time() }}" class="img_store_logo_href" data-toggle="lightbox">
<img class="img_store_logo_img" id="img_store_logo" src="{{ config('site_config.uploads') . 'teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreLogo }}?v={{ time() }}" style="max-width: 100%; max-height: 100%; ">
<a href="{{ minio_url('uploads/images/teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreLogo) }}?v={{ time() }}" class="img_store_logo_href" data-toggle="lightbox">
<img class="img_store_logo_img" id="img_store_logo" src="{{ minio_url('uploads/images/teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreLogo) }}?v={{ time() }}" style="max-width: 100%; max-height: 100%; ">
</a>
</div>
</div>
@@ -82,8 +82,8 @@
<div class="col-sm-8">
<p>Store Banner Preview:</p>
<div class="store-banner-holder">
<a href="{{ config('site_config.uploads') . 'teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreBanner }}?v={{ time() }}" class="img_store_banner_href" data-toggle="lightbox">
<img class="img_store_banner_img" id="img_store_banner" src="{{ config('site_config.uploads') . 'teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreBanner }}?v={{ time() }}" style="max-width: 100%; max-height: 100%;">
<a href="{{ minio_url('uploads/images/teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreBanner) }}?v={{ time() }}" class="img_store_banner_href" data-toggle="lightbox">
<img class="img_store_banner_img" id="img_store_banner" src="{{ minio_url('uploads/images/teamstore/' . $store_array[0]->ImageFolder . '/' . $store_array[0]->StoreBanner) }}?v={{ time() }}" style="max-width: 100%; max-height: 100%;">
</a>
</div>
</div>

View File

@@ -39,7 +39,7 @@
@foreach($array_client_designs as $row)
@foreach($array_template_paths as $key => $row1)
@if($key == 0)
<img src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-front-thumbnail.png" alt="{{ $row->DesignName }}" id="main-thumbnail" class="img img-responsive">
<img src="{{ minio_url('images/' . $row->DesignCode . '-front-thumbnail.png') }}" alt="{{ $row->DesignName }}" id="main-thumbnail" class="img img-responsive">
@endif
@endforeach
@endforeach
@@ -53,13 +53,13 @@
@if($key == 0)
<li class="col-sm-3 col-xs-3">
<a class="thumbnail a_thumbnail active">
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-front-thumbnail.png"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $row->DesignCode . '-front-thumbnail.png') }}"/>
</a>
</li>
@else
<li class="col-sm-3 col-xs-3">
<a class="thumbnail a_thumbnail">
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $row->DesignCode }}-{{ strtolower($row1->Side) }}-thumbnail.png"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $row->DesignCode . '-' . strtolower($row1->Side) . '-thumbnail.png') }}"/>
</a>
</li>
@endif

View File

@@ -36,7 +36,7 @@
<div class="col-md-12 text-center">
@foreach($thumbnails_array as $thumbnail)
@if($thumbnail->ImageClass == 'active')
<img style="height:400px" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}" id="main-thumbnail">
<img style="height:400px" src="{{ minio_url('images/' . $thumbnail->Image) . '?t=' . time() }}" id="main-thumbnail">
@endif
@endforeach
</div>
@@ -58,7 +58,7 @@
<li class="col-sm-3 col-xs-4">
<a class="thumbnail a_thumbnail {{ $thumbnail->ImageClass }}" style="border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; margin-bottom: -28px;">
<!-- <span class="close">&times;</span> -->
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}"/>
<img class="img img-responsive product-center image-thumbnails" style="height: 59.45px;" src="{{ minio_url('images/' . $thumbnail->Image) . '?t=' . time() }}"/>
</a>
<div class="funkyradio">
<div class="funkyradio-primary">
@@ -200,7 +200,7 @@
<tr id="{{ 'item-' . $thumbnail->Id }}">
<td class="text-center" style="width: 50px"><i class="fa fa-bars"></i></td>
<td><img class="img img-responsive product-center" style="height: 59.45px;" src="{{ config('site_config.images_url') }}/{{ $thumbnail->Image . '?t=' . time() }}"/></td>
<td><img class="img img-responsive product-center" style="height: 59.45px;" src="{{ minio_url('images/' . $thumbnail->Image) . '?t=' . time() }}"/></td>
<td class="text-center">
<!-- <button class="btn btn-default btn-xs btn-edit-clipart" data-id="#"><i class="fa fa-edit"></i></button> -->
<button class="btn btn-default btn-sm btn-delete-item-image" data-id="{{ $thumbnail->Id }}" data-filename="{{ $thumbnail->Image }}" title="Delete Image"><i class="fa fa-trash"></i></button>