Reorganize project part 3

This commit is contained in:
Bernd Bestel 2018-04-12 21:13:38 +02:00
parent 7dcd39f82f
commit 5a1d21ef31
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
86 changed files with 625 additions and 583 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"phpserver.relativePath": "public"
}

View File

@ -3,35 +3,35 @@
use \Psr\Http\Message\ServerRequestInterface as Request; use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response; use \Psr\Http\Message\ResponseInterface as Response;
use Grocy\Middleware\SessionMiddleware; use \Grocy\Middleware\SessionAuthMiddleware;
use Grocy\Middleware\JsonMiddleware; use \Grocy\Middleware\JsonMiddleware;
use Grocy\Middleware\CliMiddleware; use \Grocy\Middleware\CliMiddleware;
use Grocy\Services\ApplicationService; use \Grocy\Services\ApplicationService;
require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/data/config.php'; require_once __DIR__ . '/data/config.php';
require_once __DIR__ . '/extensions.php'; require_once __DIR__ . '/extensions.php';
// Setup base application // Setup base application
$app = new \Slim\App;
if (PHP_SAPI !== 'cli') if (PHP_SAPI !== 'cli')
{ {
$app = new \Slim\App(new \Slim\Container([ $appContainer = new \Slim\Container([
'settings' => [ 'settings' => [
'displayErrorDetails' => true, 'displayErrorDetails' => true,
'determineRouteBeforeAppMiddleware' => true 'determineRouteBeforeAppMiddleware' => true
], ],
])); 'view' => function($container)
$container = $app->getContainer();
$container['view'] = function($container)
{ {
return new \Slim\Views\Blade(__DIR__ . '/views', __DIR__ . '/data/viewcache'); return new \Slim\Views\Blade(__DIR__ . '/views', __DIR__ . '/data/viewcache');
}; }
]);
$app = new \Slim\App($appContainer);
} }
else else
{ {
$app = new \Slim\App();
$app->add(\pavlakis\cli\CliRequest::class); $app->add(\pavlakis\cli\CliRequest::class);
} }
@ -39,7 +39,7 @@ else
$applicationService = new ApplicationService(); $applicationService = new ApplicationService();
if (!$applicationService->IsDemoInstallation()) if (!$applicationService->IsDemoInstallation())
{ {
$app->add(SessionMiddleware::class); $app->add(SessionAuthMiddleware::class);
} }
// Base route // Base route

View File

@ -8,5 +8,6 @@ for /f "tokens=*" %%a in ('type version.txt') do set version=%%a
del "%releasePath%\grocy_%version%.zip" del "%releasePath%\grocy_%version%.zip"
"build_tools\7za.exe" a -r "%releasePath%\grocy_%version%.zip" "%projectPath%\*" -xr!.* -xr!build_tools -xr!build.bat -xr!composer.json -xr!composer.lock -xr!bower.json -xr!publication_assets "build_tools\7za.exe" a -r "%releasePath%\grocy_%version%.zip" "%projectPath%\*" -xr!.* -xr!build_tools -xr!build.bat -xr!composer.json -xr!composer.lock -xr!bower.json -xr!publication_assets
"build_tools\7za.exe" a -r "%releasePath%\grocy_%version%.zip" "%projectPath%\.htaccess" "build_tools\7za.exe" a "%releasePath%\grocy_%version%.zip" "%projectPath%\public\.htaccess"
"build_tools\7za.exe" rn "%releasePath%\grocy_%version%.zip" .htaccess public\.htaccess
"build_tools\7za.exe" d "%releasePath%\grocy_%version%.zip" data\*.* data\sessions data\viewcache\* "build_tools\7za.exe" d "%releasePath%\grocy_%version%.zip" data\*.* data\sessions data\viewcache\*

View File

@ -4,7 +4,7 @@ namespace Grocy\Controllers;
class BaseApiController extends BaseController class BaseApiController extends BaseController
{ {
protected function ApiEncode($response) protected function ApiResponse($response)
{ {
return json_encode($response); return json_encode($response);
} }

View File

@ -2,7 +2,8 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\DatabaseService; use \Grocy\Services\DatabaseService;
use \Grocy\Services\ApplicationService;
class BaseController class BaseController
{ {
@ -11,6 +12,9 @@ class BaseController
$databaseService = new DatabaseService(); $databaseService = new DatabaseService();
$this->Database = $databaseService->GetDbConnection(); $this->Database = $databaseService->GetDbConnection();
$applicationService = new ApplicationService();
$container->view->set('version', $applicationService->GetInstalledVersion());
} }
protected $AppContainer; protected $AppContainer;

View File

@ -2,7 +2,7 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\BatteriesService; use \Grocy\Services\BatteriesService;
class BatteriesApiController extends BaseApiController class BatteriesApiController extends BaseApiController
{ {
@ -14,7 +14,7 @@ class BatteriesApiController extends BaseApiController
protected $BatteriesService; protected $BatteriesService;
public function TrackChargeCycle($request, $response, $args) public function TrackChargeCycle(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$trackedTime = date('Y-m-d H:i:s'); $trackedTime = date('Y-m-d H:i:s');
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time'])) if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']))
@ -22,11 +22,11 @@ class BatteriesApiController extends BaseApiController
$trackedTime = $request->getQueryParams()['tracked_time']; $trackedTime = $request->getQueryParams()['tracked_time'];
} }
return $this->ApiEncode(array('success' => $this->BatteriesService->TrackChargeCycle($args['batteryId'], $trackedTime))); return $this->ApiResponse(array('success' => $this->BatteriesService->TrackChargeCycle($args['batteryId'], $trackedTime)));
} }
public function BatteryDetails($request, $response, $args) public function BatteryDetails(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->ApiEncode($this->BatteriesService->GetBatteryDetails($args['batteryId'])); return $this->ApiResponse($this->BatteriesService->GetBatteryDetails($args['batteryId']));
} }
} }

View File

@ -2,7 +2,7 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\BatteriesService; use \Grocy\Services\BatteriesService;
class BatteriesController extends BaseController class BatteriesController extends BaseController
{ {
@ -14,49 +14,46 @@ class BatteriesController extends BaseController
protected $BatteriesService; protected $BatteriesService;
public function Overview($request, $response, $args) public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$nextChargeTimes = array();
foreach($this->Database->batteries() as $battery)
{
$nextChargeTimes[$battery->id] = $this->BatteriesService->GetNextChargeTime($battery->id);
}
return $this->AppContainer->view->render($response, 'batteriesoverview', [ return $this->AppContainer->view->render($response, 'batteriesoverview', [
'title' => 'Batteries overview',
'contentPage' => 'batteriesoverview.php',
'batteries' => $this->Database->batteries(), 'batteries' => $this->Database->batteries(),
'current' => $this->BatteriesService->GetCurrent(), 'current' => $this->BatteriesService->GetCurrent(),
'nextChargeTimes' => $nextChargeTimes
]); ]);
} }
public function TrackChargeCycle($request, $response, $args) public function TrackChargeCycle(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'batterytracking', [ return $this->AppContainer->view->render($response, 'batterytracking', [
'title' => 'Battery tracking',
'contentPage' => 'batterytracking.php',
'batteries' => $this->Database->batteries() 'batteries' => $this->Database->batteries()
]); ]);
} }
public function BatteriesList($request, $response, $args) public function BatteriesList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'batteries', [ return $this->AppContainer->view->render($response, 'batteries', [
'title' => 'Batteries',
'contentPage' => 'batteries.php',
'batteries' => $this->Database->batteries() 'batteries' => $this->Database->batteries()
]); ]);
} }
public function BatteryEditForm($request, $response, $args) public function BatteryEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
if ($args['batteryId'] == 'new') if ($args['batteryId'] == 'new')
{ {
return $this->AppContainer->view->render($response, 'batteryform', [ return $this->AppContainer->view->render($response, 'batteryform', [
'title' => 'Create battery',
'contentPage' => 'batteryform.php',
'mode' => 'create' 'mode' => 'create'
]); ]);
} }
else else
{ {
return $this->AppContainer->view->render($response, 'batteryform', [ return $this->AppContainer->view->render($response, 'batteryform', [
'title' => 'Edit battery',
'contentPage' => 'batteryform.php',
'battery' => $this->Database->batteries($args['batteryId']), 'battery' => $this->Database->batteries($args['batteryId']),
'mode' => 'edit' 'mode' => 'edit'
]); ]);

View File

@ -2,12 +2,12 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\ApplicationService; use \Grocy\Services\ApplicationService;
use Grocy\Services\DatabaseMigrationService; use \Grocy\Services\DatabaseMigrationService;
class CliController extends BaseController class CliController extends BaseController
{ {
public function RecreateDemo($request, $response, $args) public function RecreateDemo(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$applicationService = new ApplicationService(); $applicationService = new ApplicationService();
if ($applicationService->IsDemoInstallation()) if ($applicationService->IsDemoInstallation())

View File

@ -4,37 +4,37 @@ namespace Grocy\Controllers;
class GenericEntityApiController extends BaseApiController class GenericEntityApiController extends BaseApiController
{ {
public function GetObjects($request, $response, $args) public function GetObjects(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->ApiEncode($this->Database->{$args['entity']}()); return $this->ApiResponse($this->Database->{$args['entity']}());
} }
public function GetObject($request, $response, $args) public function GetObject(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->ApiEncode($this->Database->{$args['entity']}($args['objectId'])); return $this->ApiResponse($this->Database->{$args['entity']}($args['objectId']));
} }
public function AddObject($request, $response, $args) public function AddObject(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$newRow = $this->Database->{$args['entity']}()->createRow($request->getParsedBody()); $newRow = $this->Database->{$args['entity']}()->createRow($request->getParsedBody());
$newRow->save(); $newRow->save();
$success = $newRow->isClean(); $success = $newRow->isClean();
return $this->ApiEncode(array('success' => $success)); return $this->ApiResponse(array('success' => $success));
} }
public function EditObject($request, $response, $args) public function EditObject(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$row = $this->Database->{$args['entity']}($args['objectId']); $row = $this->Database->{$args['entity']}($args['objectId']);
$row->update($request->getParsedBody()); $row->update($request->getParsedBody());
$success = $row->isClean(); $success = $row->isClean();
return $this->ApiEncode(array('success' => $success)); return $this->ApiResponse(array('success' => $success));
} }
public function DeleteObject($request, $response, $args) public function DeleteObject(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$row = $this->Database->{$args['entity']}($args['objectId']); $row = $this->Database->{$args['entity']}($args['objectId']);
$row->delete(); $row->delete();
$success = $row->isClean(); $success = $row->isClean();
return $this->ApiEncode(array('success' => $success)); return $this->ApiResponse(array('success' => $success));
} }
} }

View File

@ -2,7 +2,7 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\HabitsService; use \Grocy\Services\HabitsService;
class HabitsApiController extends BaseApiController class HabitsApiController extends BaseApiController
{ {
@ -14,7 +14,7 @@ class HabitsApiController extends BaseApiController
protected $HabitsService; protected $HabitsService;
public function TrackHabitExecution($request, $response, $args) public function TrackHabitExecution(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$trackedTime = date('Y-m-d H:i:s'); $trackedTime = date('Y-m-d H:i:s');
if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time'])) if (isset($request->getQueryParams()['tracked_time']) && !empty($request->getQueryParams()['tracked_time']))
@ -22,11 +22,11 @@ class HabitsApiController extends BaseApiController
$trackedTime = $request->getQueryParams()['tracked_time']; $trackedTime = $request->getQueryParams()['tracked_time'];
} }
return $this->ApiEncode(array('success' => $this->HabitsService->TrackHabit($args['habitId'], $trackedTime))); return $this->ApiResponse(array('success' => $this->HabitsService->TrackHabit($args['habitId'], $trackedTime)));
} }
public function HabitDetails($request, $response, $args) public function HabitDetails(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->ApiEncode($this->HabitsService->GetHabitDetails($args['habitId'])); return $this->ApiResponse($this->HabitsService->GetHabitDetails($args['habitId']));
} }
} }

View File

@ -2,7 +2,7 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\HabitsService; use \Grocy\Services\HabitsService;
class HabitsController extends BaseController class HabitsController extends BaseController
{ {
@ -14,52 +14,49 @@ class HabitsController extends BaseController
protected $HabitsService; protected $HabitsService;
public function Overview($request, $response, $args) public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$nextHabitTimes = array();
foreach($this->Database->habits() as $habit)
{
$nextHabitTimes[$habit->id] = $this->HabitsService->GetNextHabitTime($habit->id);
}
return $this->AppContainer->view->render($response, 'habitsoverview', [ return $this->AppContainer->view->render($response, 'habitsoverview', [
'title' => 'Habits overview',
'contentPage' => 'habitsoverview.php',
'habits' => $this->Database->habits(), 'habits' => $this->Database->habits(),
'currentHabits' => $this->HabitsService->GetCurrentHabits(), 'currentHabits' => $this->HabitsService->GetCurrentHabits(),
'nextHabitTimes' => $nextHabitTimes
]); ]);
} }
public function TrackHabitExecution($request, $response, $args) public function TrackHabitExecution(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'habittracking', [ return $this->AppContainer->view->render($response, 'habittracking', [
'title' => 'Habit tracking',
'contentPage' => 'habittracking.php',
'habits' => $this->Database->habits() 'habits' => $this->Database->habits()
]); ]);
} }
public function HabitsList($request, $response, $args) public function HabitsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'habits', [ return $this->AppContainer->view->render($response, 'habits', [
'title' => 'Habits',
'contentPage' => 'habits.php',
'habits' => $this->Database->habits() 'habits' => $this->Database->habits()
]); ]);
} }
public function HabitEditForm($request, $response, $args) public function HabitEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
if ($args['habitId'] == 'new') if ($args['habitId'] == 'new')
{ {
return $this->AppContainer->view->render($response, 'habitform', [ return $this->AppContainer->view->render($response, 'habitform', [
'title' => 'Create habit', 'periodTypes' => GetClassConstants('\Grocy\Services\HabitsService'),
'contentPage' => 'habitform.php',
'periodTypes' => GetClassConstants('Grocy\Services\HabitsService'),
'mode' => 'create' 'mode' => 'create'
]); ]);
} }
else else
{ {
return $this->AppContainer->view->render($response, 'habitform', [ return $this->AppContainer->view->render($response, 'habitform', [
'title' => 'Edit habit',
'contentPage' => 'habitform.php',
'habit' => $this->Database->habits($args['habitId']), 'habit' => $this->Database->habits($args['habitId']),
'periodTypes' => GetClassConstants('Grocy\Services\HabitsService'), 'periodTypes' => GetClassConstants('\Grocy\Services\HabitsService'),
'mode' => 'edit' 'mode' => 'edit'
]); ]);
} }

View File

@ -2,11 +2,10 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\SessionService; use \Grocy\Services\SessionService;
use Grocy\Services\DatabaseService; use \Grocy\Services\ApplicationService;
use Grocy\Services\ApplicationService; use \Grocy\Services\DatabaseMigrationService;
use Grocy\Services\DatabaseMigrationService; use \Grocy\Services\DemoDataGeneratorService;
use Grocy\Services\DemoDataGeneratorService;
class LoginController extends BaseController class LoginController extends BaseController
{ {
@ -18,7 +17,7 @@ class LoginController extends BaseController
protected $SessionService; protected $SessionService;
public function ProcessLogin($request, $response, $args) public function ProcessLogin(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$postParams = $request->getParsedBody(); $postParams = $request->getParsedBody();
if (isset($postParams['username']) && isset($postParams['password'])) if (isset($postParams['username']) && isset($postParams['password']))
@ -41,21 +40,18 @@ class LoginController extends BaseController
} }
} }
public function LoginPage($request, $response, $args) public function LoginPage(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'login', [ return $this->AppContainer->view->render($response, 'login');
'title' => 'Login',
'contentPage' => 'login.php'
]);
} }
public function Logout($request, $response, $args) public function Logout(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$this->SessionService->RemoveSession($_COOKIE['grocy_session']); $this->SessionService->RemoveSession($_COOKIE['grocy_session']);
return $response->withRedirect('/'); return $response->withRedirect('/');
} }
public function Root($request, $response, $args) public function Root(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
// Schema migration is done here // Schema migration is done here
$databaseMigrationService = new DatabaseMigrationService(); $databaseMigrationService = new DatabaseMigrationService();

View File

@ -2,7 +2,7 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\StockService; use \Grocy\Services\StockService;
class StockApiController extends BaseApiController class StockApiController extends BaseApiController
{ {
@ -14,12 +14,12 @@ class StockApiController extends BaseApiController
protected $StockService; protected $StockService;
public function ProductDetails($request, $response, $args) public function ProductDetails(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->ApiEncode($this->StockService->GetProductDetails($args['productId'])); return $this->ApiResponse($this->StockService->GetProductDetails($args['productId']));
} }
public function AddProduct($request, $response, $args) public function AddProduct(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$bestBeforeDate = date('Y-m-d'); $bestBeforeDate = date('Y-m-d');
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate'])) if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']))
@ -33,10 +33,10 @@ class StockApiController extends BaseApiController
$transactionType = $request->getQueryParams()['transactiontype']; $transactionType = $request->getQueryParams()['transactiontype'];
} }
return $this->ApiEncode(array('success' => $this->StockService->AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType))); return $this->ApiResponse(array('success' => $this->StockService->AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType)));
} }
public function ConsumeProduct($request, $response, $args) public function ConsumeProduct(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$spoiled = false; $spoiled = false;
if (isset($request->getQueryParams()['spoiled']) && !empty($request->getQueryParams()['spoiled']) && $request->getQueryParams()['spoiled'] == '1') if (isset($request->getQueryParams()['spoiled']) && !empty($request->getQueryParams()['spoiled']) && $request->getQueryParams()['spoiled'] == '1')
@ -50,10 +50,10 @@ class StockApiController extends BaseApiController
$transactionType = $request->getQueryParams()['transactiontype']; $transactionType = $request->getQueryParams()['transactiontype'];
} }
return $this->ApiEncode(array('success' => $this->StockService->ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType))); return $this->ApiResponse(array('success' => $this->StockService->ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType)));
} }
public function InventoryProduct($request, $response, $args) public function InventoryProduct(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$bestBeforeDate = date('Y-m-d'); $bestBeforeDate = date('Y-m-d');
if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate'])) if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate']))
@ -61,17 +61,17 @@ class StockApiController extends BaseApiController
$bestBeforeDate = $request->getQueryParams()['bestbeforedate']; $bestBeforeDate = $request->getQueryParams()['bestbeforedate'];
} }
return $this->ApiEncode(array('success' => $this->StockService->InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate))); return $this->ApiResponse(array('success' => $this->StockService->InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate)));
} }
public function CurrentStock($request, $response, $args) public function CurrentStock(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->ApiEncode($this->StockService->GetCurrentStock()); return $this->ApiResponse($this->StockService->GetCurrentStock());
} }
public function AddmissingProductsToShoppingList($request, $response, $args) public function AddmissingProductsToShoppingList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
$this->StockService->AddMissingProductsToShoppingList(); $this->StockService->AddMissingProductsToShoppingList();
return $this->ApiEncode(array('success' => true)); return $this->ApiResponse(array('success' => true));
} }
} }

View File

@ -2,7 +2,7 @@
namespace Grocy\Controllers; namespace Grocy\Controllers;
use Grocy\Services\StockService; use \Grocy\Services\StockService;
class StockController extends BaseController class StockController extends BaseController
{ {
@ -15,11 +15,9 @@ class StockController extends BaseController
protected $StockService; protected $StockService;
public function Overview($request, $response, $args) public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'stockoverview', [ return $this->AppContainer->view->render($response, 'stockoverview', [
'title' => 'Stock overview',
'contentPage' => 'stockoverview.php',
'products' => $this->Database->products(), 'products' => $this->Database->products(),
'quantityunits' => $this->Database->quantity_units(), 'quantityunits' => $this->Database->quantity_units(),
'currentStock' => $this->StockService->GetCurrentStock(), 'currentStock' => $this->StockService->GetCurrentStock(),
@ -27,38 +25,30 @@ class StockController extends BaseController
]); ]);
} }
public function Purchase($request, $response, $args) public function Purchase(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'purchase', [ return $this->AppContainer->view->render($response, 'purchase', [
'title' => 'Purchase',
'contentPage' => 'purchase.php',
'products' => $this->Database->products() 'products' => $this->Database->products()
]); ]);
} }
public function Consume($request, $response, $args) public function Consume(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'consume', [ return $this->AppContainer->view->render($response, 'consume', [
'title' => 'Consume',
'contentPage' => 'consume.php',
'products' => $this->Database->products() 'products' => $this->Database->products()
]); ]);
} }
public function Inventory($request, $response, $args) public function Inventory(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'inventory', [ return $this->AppContainer->view->render($response, 'inventory', [
'title' => 'Inventory',
'contentPage' => 'inventory.php',
'products' => $this->Database->products() 'products' => $this->Database->products()
]); ]);
} }
public function ShoppingList($request, $response, $args) public function ShoppingList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'shoppinglist', [ return $this->AppContainer->view->render($response, 'shoppinglist', [
'title' => 'Shopping list',
'contentPage' => 'shoppinglist.php',
'listItems' => $this->Database->shopping_list(), 'listItems' => $this->Database->shopping_list(),
'products' => $this->Database->products(), 'products' => $this->Database->products(),
'quantityunits' => $this->Database->quantity_units(), 'quantityunits' => $this->Database->quantity_units(),
@ -66,42 +56,34 @@ class StockController extends BaseController
]); ]);
} }
public function ProductsList($request, $response, $args) public function ProductsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'products', [ return $this->AppContainer->view->render($response, 'products', [
'title' => 'Products',
'contentPage' => 'products.php',
'products' => $this->Database->products(), 'products' => $this->Database->products(),
'locations' => $this->Database->locations(), 'locations' => $this->Database->locations(),
'quantityunits' => $this->Database->quantity_units() 'quantityunits' => $this->Database->quantity_units()
]); ]);
} }
public function LocationsList($request, $response, $args) public function LocationsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'locations', [ return $this->AppContainer->view->render($response, 'locations', [
'title' => 'Locations',
'contentPage' => 'locations.php',
'locations' => $this->Database->locations() 'locations' => $this->Database->locations()
]); ]);
} }
public function QuantityUnitsList($request, $response, $args) public function QuantityUnitsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'quantityunits', [ return $this->AppContainer->view->render($response, 'quantityunits', [
'title' => 'Quantity units',
'contentPage' => 'quantityunits.php',
'quantityunits' => $this->Database->quantity_units() 'quantityunits' => $this->Database->quantity_units()
]); ]);
} }
public function ProductEditForm($request, $response, $args) public function ProductEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
if ($args['productId'] == 'new') if ($args['productId'] == 'new')
{ {
return $this->AppContainer->view->render($response, 'productform', [ return $this->AppContainer->view->render($response, 'productform', [
'title' => 'Create product',
'contentPage' => 'productform.php',
'locations' => $this->Database->locations(), 'locations' => $this->Database->locations(),
'quantityunits' => $this->Database->quantity_units(), 'quantityunits' => $this->Database->quantity_units(),
'mode' => 'create' 'mode' => 'create'
@ -110,8 +92,6 @@ class StockController extends BaseController
else else
{ {
return $this->AppContainer->view->render($response, 'productform', [ return $this->AppContainer->view->render($response, 'productform', [
'title' => 'Edit product',
'contentPage' => 'productform.php',
'product' => $this->Database->products($args['productId']), 'product' => $this->Database->products($args['productId']),
'locations' => $this->Database->locations(), 'locations' => $this->Database->locations(),
'quantityunits' => $this->Database->quantity_units(), 'quantityunits' => $this->Database->quantity_units(),
@ -120,55 +100,45 @@ class StockController extends BaseController
} }
} }
public function LocationEditForm($request, $response, $args) public function LocationEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
if ($args['locationId'] == 'new') if ($args['locationId'] == 'new')
{ {
return $this->AppContainer->view->render($response, 'locationform', [ return $this->AppContainer->view->render($response, 'locationform', [
'title' => 'Create location',
'contentPage' => 'locationform.php',
'mode' => 'create' 'mode' => 'create'
]); ]);
} }
else else
{ {
return $this->AppContainer->view->render($response, 'locationform', [ return $this->AppContainer->view->render($response, 'locationform', [
'title' => 'Edit location',
'contentPage' => 'locationform.php',
'location' => $this->Database->locations($args['locationId']), 'location' => $this->Database->locations($args['locationId']),
'mode' => 'edit' 'mode' => 'edit'
]); ]);
} }
} }
public function QuantityUnitEditForm($request, $response, $args) public function QuantityUnitEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
if ($args['quantityunitId'] == 'new') if ($args['quantityunitId'] == 'new')
{ {
return $this->AppContainer->view->render($response, 'quantityunitform', [ return $this->AppContainer->view->render($response, 'quantityunitform', [
'title' => 'Create quantity unit',
'contentPage' => 'quantityunitform.php',
'mode' => 'create' 'mode' => 'create'
]); ]);
} }
else else
{ {
return $this->AppContainer->view->render($response, 'quantityunitform', [ return $this->AppContainer->view->render($response, 'quantityunitform', [
'title' => 'Edit quantity unit',
'contentPage' => 'quantityunitform.php',
'quantityunit' => $this->Database->quantity_units($args['quantityunitId']), 'quantityunit' => $this->Database->quantity_units($args['quantityunitId']),
'mode' => 'edit' 'mode' => 'edit'
]); ]);
} }
} }
public function ShoppingListItemEditForm($request, $response, $args) public function ShoppingListItemEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
if ($args['itemId'] == 'new') if ($args['itemId'] == 'new')
{ {
return $this->AppContainer->view->render($response, 'shoppinglistform', [ return $this->AppContainer->view->render($response, 'shoppinglistform', [
'title' => 'Add shopping list item',
'contentPage' => 'shoppinglistform.php',
'products' => $this->Database->products(), 'products' => $this->Database->products(),
'mode' => 'create' 'mode' => 'create'
]); ]);
@ -176,8 +146,6 @@ class StockController extends BaseController
else else
{ {
return $this->AppContainer->view->render($response, 'shoppinglistform', [ return $this->AppContainer->view->render($response, 'shoppinglistform', [
'title' => 'Edit shopping list item',
'contentPage' => 'shoppinglistform.php',
'listItem' => $this->Database->shopping_list($args['itemId']), 'listItem' => $this->Database->shopping_list($args['itemId']),
'products' => $this->Database->products(), 'products' => $this->Database->products(),
'mode' => 'edit' 'mode' => 'edit'

View File

@ -12,14 +12,15 @@ class CliMiddleware
public function __invoke(\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next) public function __invoke(\Slim\Http\Request $request, \Slim\Http\Response $response, callable $next)
{ {
$response = $next($request, $response);
if (PHP_SAPI !== 'cli') if (PHP_SAPI !== 'cli')
{ {
$response->write('Please call this only from CLI'); $response->write('Please call this only from CLI');
return $response->withHeader('Content-Type', 'text/plain')->withStatus(400); return $response->withHeader('Content-Type', 'text/plain')->withStatus(400);
} }
else
{
$response = $next($request, $response, $next);
return $response->withHeader('Content-Type', 'text/plain'); return $response->withHeader('Content-Type', 'text/plain');
} }
} }
}

View File

@ -2,9 +2,9 @@
namespace Grocy\Middleware; namespace Grocy\Middleware;
use Grocy\Services\SessionService; use \Grocy\Services\SessionService;
class SessionMiddleware class SessionAuthMiddleware
{ {
public function __construct(\Slim\Container $container) { public function __construct(\Slim\Container $container) {
$this->container = $container; $this->container = $container;

13
migrations/0001.sql Normal file
View File

@ -0,0 +1,13 @@
CREATE TABLE products (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
location_id INTEGER NOT NULL,
qu_id_purchase INTEGER NOT NULL,
qu_id_stock INTEGER NOT NULL,
qu_factor_purchase_to_stock REAL NOT NULL,
barcode TEXT,
min_stock_amount INTEGER NOT NULL DEFAULT 0,
default_best_before_days INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

6
migrations/0002.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE TABLE locations (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

6
migrations/0003.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE TABLE quantity_units (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

9
migrations/0004.sql Normal file
View File

@ -0,0 +1,9 @@
CREATE TABLE stock (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER NOT NULL,
amount INTEGER NOT NULL,
best_before_date DATE,
purchased_date DATE DEFAULT (datetime('now', 'localtime')),
stock_id TEXT NOT NULL,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

12
migrations/0005.sql Normal file
View File

@ -0,0 +1,12 @@
CREATE TABLE stock_log (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER NOT NULL,
amount INTEGER NOT NULL,
best_before_date DATE,
purchased_date DATE,
used_date DATE,
spoiled INTEGER NOT NULL DEFAULT 0,
stock_id TEXT NOT NULL,
transaction_type TEXT NOT NULL,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

19
migrations/0006.sql Normal file
View File

@ -0,0 +1,19 @@
INSERT INTO locations
(name, description)
VALUES
('DefaultLocation', 'This is the first default location, edit or delete it');
INSERT INTO quantity_units
(name, description)
VALUES
('DefaultQuantityUnit', 'This is the first default quantity unit, edit or delete it');
INSERT INTO products
(name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock)
VALUES
('DefaultProduct1', 'This is the first default product, edit or delete it', 1, 1, 1, 1);
INSERT INTO products
(name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock)
VALUES
('DefaultProduct2', 'This is the second default product, edit or delete it', 1, 1, 1, 1);

9
migrations/0007.sql Normal file
View File

@ -0,0 +1,9 @@
CREATE VIEW stock_missing_products
AS
SELECT p.id, MAX(p.name) AS name, p.min_stock_amount - IFNULL(SUM(s.amount), 0) AS amount_missing
FROM products p
LEFT JOIN stock s
ON p.id = s.product_id
WHERE p.min_stock_amount != 0
GROUP BY p.id
HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount

6
migrations/0008.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE VIEW stock_current
AS
SELECT product_id, SUM(amount) AS amount, MIN(best_before_date) AS best_before_date
FROM stock
GROUP BY product_id
ORDER BY MIN(best_before_date) ASC

7
migrations/0009.sql Normal file
View File

@ -0,0 +1,7 @@
CREATE TABLE shopping_list (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER NOT NULL UNIQUE,
amount INTEGER NOT NULL DEFAULT 0,
amount_autoadded INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

8
migrations/0010.sql Normal file
View File

@ -0,0 +1,8 @@
CREATE TABLE habits (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
period_type TEXT NOT NULL,
period_days INTEGER,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

6
migrations/0011.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE TABLE habits_log (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
habit_id INTEGER NOT NULL,
tracked_time DATETIME,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

6
migrations/0012.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE VIEW habits_current
AS
SELECT habit_id, MAX(tracked_time) AS last_tracked_time
FROM habits_log
GROUP BY habit_id
ORDER BY MAX(tracked_time) DESC

8
migrations/0013.sql Normal file
View File

@ -0,0 +1,8 @@
CREATE TABLE batteries (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
used_in TEXT,
charge_interval_days INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

6
migrations/0014.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE TABLE battery_charge_cycles (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
battery_id TEXT NOT NULL,
tracked_time DATETIME,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

6
migrations/0015.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE VIEW batteries_current
AS
SELECT battery_id, MAX(tracked_time) AS last_tracked_time
FROM battery_charge_cycles
GROUP BY battery_id
ORDER BY MAX(tracked_time) DESC

1
migrations/0016.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE shopping_list RENAME TO shopping_list_old

8
migrations/0017.sql Normal file
View File

@ -0,0 +1,8 @@
CREATE TABLE shopping_list (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER,
note TEXT,
amount INTEGER NOT NULL DEFAULT 0,
amount_autoadded INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)

4
migrations/0018.sql Normal file
View File

@ -0,0 +1,4 @@
INSERT INTO shopping_list
(product_id, amount, amount_autoadded, row_created_timestamp)
SELECT product_id, amount, amount_autoadded, row_created_timestamp
FROM shopping_list_old

1
migrations/0019.sql Normal file
View File

@ -0,0 +1 @@
DROP TABLE shopping_list_old

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -22,8 +22,8 @@
padding: 20px; padding: 20px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
background-color: #f5f5f5; background-color: #e5e5e5;
border-right: 1px solid #5e5e5e; border-right: 1px solid #d6d6d6;
min-width: 220px; min-width: 220px;
max-width: 260px; max-width: 260px;
} }
@ -47,8 +47,11 @@
.nav-sidebar > .active > a, .nav-sidebar > .active > a,
.nav-sidebar > .active > a:hover, .nav-sidebar > .active > a:hover,
.nav-sidebar > .active > a:focus { .nav-sidebar > .active > a:focus {
color: #fff; background-color: #d6d6d6;
background-color: #5e5e5e; }
.navbar-default {
background-color: #e5e5e5;
} }
.main { .main {
@ -67,7 +70,7 @@
} }
.nav-copyright { .nav-copyright {
color: #b3b3b1; color: #a7a7a7;
font-size: 11px; font-size: 11px;
text-align: center; text-align: center;
font-family: 'Arial', sans-serif; font-family: 'Arial', sans-serif;
@ -75,21 +78,24 @@
.discrete-link { .discrete-link {
color: inherit; color: inherit;
transition: all 0.3s;
} }
a.discrete-link:hover { a.discrete-link:hover {
color: #5cb85c; color: #337ab7;
text-decoration: none; text-decoration: none;
transition: all 0.3s;
} }
a.discrete-link:focus { a.discrete-link:focus {
color: #337ab7; color: #ab2230;
text-decoration: none; text-decoration: none;
transition: all 0.3s;
} }
.navbar-fixed-top { .navbar-fixed-top {
border-bottom: solid; border-bottom: solid;
border-color: #5e5e5e; border-color: #d6d6d6;
} }
.navbar-brand { .navbar-brand {

View File

@ -2,8 +2,11 @@
$(function() $(function()
{ {
var menuItem = $('.nav').find("[data-nav-for-page='" + Grocy.ContentPage + "']"); if (!Grocy.ActiveNav.isEmpty())
{
var menuItem = $('.nav').find("[data-nav-for-page='" + Grocy.ActiveNav + "']");
menuItem.addClass('active'); menuItem.addClass('active');
}
$.timeago.settings.allowFuture = true; $.timeago.settings.allowFuture = true;
$('time.timeago').timeago(); $('time.timeago').timeago();
@ -81,6 +84,11 @@ String.prototype.contains = function(search)
return this.toLowerCase().indexOf(search.toLowerCase()) !== -1; return this.toLowerCase().indexOf(search.toLowerCase()) !== -1;
}; };
String.prototype.isEmpty = function()
{
return (this.length === 0 || !this.trim());
};
Grocy.GetUriParam = function(key) Grocy.GetUriParam = function(key)
{ {
var currentUri = decodeURIComponent(window.location.search.substring(1)); var currentUri = decodeURIComponent(window.location.search.substring(1));

View File

@ -2,7 +2,7 @@
namespace Grocy\Services; namespace Grocy\Services;
use Grocy\Services\DatabaseService; use \Grocy\Services\DatabaseService;
class BaseService class BaseService
{ {

View File

@ -8,188 +8,18 @@ class DatabaseMigrationService extends BaseService
{ {
$this->DatabaseService->ExecuteDbStatement("CREATE TABLE IF NOT EXISTS migrations (migration INTEGER NOT NULL PRIMARY KEY UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')))"); $this->DatabaseService->ExecuteDbStatement("CREATE TABLE IF NOT EXISTS migrations (migration INTEGER NOT NULL PRIMARY KEY UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')))");
$this->ExecuteMigrationWhenNeeded(1, " $migrationFiles = array();
CREATE TABLE products ( foreach (new \FilesystemIterator(__DIR__ . '/../migrations') as $file)
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, {
name TEXT NOT NULL UNIQUE, $migrationFiles[$file->getBasename('.sql')] = $file->getPathname();
description TEXT, }
location_id INTEGER NOT NULL, ksort($migrationFiles);
qu_id_purchase INTEGER NOT NULL,
qu_id_stock INTEGER NOT NULL,
qu_factor_purchase_to_stock REAL NOT NULL,
barcode TEXT,
min_stock_amount INTEGER NOT NULL DEFAULT 0,
default_best_before_days INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(2, " foreach($migrationFiles as $migrationNumber => $migrationFile)
CREATE TABLE locations ( {
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, $migrationNumber = ltrim($migrationNumber, '0');
name TEXT NOT NULL UNIQUE, $this->ExecuteMigrationWhenNeeded($migrationNumber, file_get_contents($migrationFile));
description TEXT, }
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(3, "
CREATE TABLE quantity_units (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(4, "
CREATE TABLE stock (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER NOT NULL,
amount INTEGER NOT NULL,
best_before_date DATE,
purchased_date DATE DEFAULT (datetime('now', 'localtime')),
stock_id TEXT NOT NULL,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(5, "
CREATE TABLE stock_log (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER NOT NULL,
amount INTEGER NOT NULL,
best_before_date DATE,
purchased_date DATE,
used_date DATE,
spoiled INTEGER NOT NULL DEFAULT 0,
stock_id TEXT NOT NULL,
transaction_type TEXT NOT NULL,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(6, "
INSERT INTO locations (name, description) VALUES ('DefaultLocation', 'This is the first default location, edit or delete it');
INSERT INTO quantity_units (name, description) VALUES ('DefaultQuantityUnit', 'This is the first default quantity unit, edit or delete it');
INSERT INTO products (name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('DefaultProduct1', 'This is the first default product, edit or delete it', 1, 1, 1, 1);
INSERT INTO products (name, description, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('DefaultProduct2', 'This is the second default product, edit or delete it', 1, 1, 1, 1);"
);
$this->ExecuteMigrationWhenNeeded(7, "
CREATE VIEW stock_missing_products
AS
SELECT p.id, MAX(p.name) AS name, p.min_stock_amount - IFNULL(SUM(s.amount), 0) AS amount_missing
FROM products p
LEFT JOIN stock s
ON p.id = s.product_id
WHERE p.min_stock_amount != 0
GROUP BY p.id
HAVING IFNULL(SUM(s.amount), 0) < p.min_stock_amount;"
);
$this->ExecuteMigrationWhenNeeded(8, "
CREATE VIEW stock_current
AS
SELECT product_id, SUM(amount) AS amount, MIN(best_before_date) AS best_before_date
FROM stock
GROUP BY product_id
ORDER BY MIN(best_before_date) ASC;"
);
$this->ExecuteMigrationWhenNeeded(9, "
CREATE TABLE shopping_list (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER NOT NULL UNIQUE,
amount INTEGER NOT NULL DEFAULT 0,
amount_autoadded INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(10, "
CREATE TABLE habits (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
period_type TEXT NOT NULL,
period_days INTEGER,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(11, "
CREATE TABLE habits_log (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
habit_id INTEGER NOT NULL,
tracked_time DATETIME,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(12, "
CREATE VIEW habits_current
AS
SELECT habit_id, MAX(tracked_time) AS last_tracked_time
FROM habits_log
GROUP BY habit_id
ORDER BY MAX(tracked_time) DESC;"
);
$this->ExecuteMigrationWhenNeeded(13, "
CREATE TABLE batteries (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
name TEXT NOT NULL UNIQUE,
description TEXT,
used_in TEXT,
charge_interval_days INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(14, "
CREATE TABLE battery_charge_cycles (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
battery_id TEXT NOT NULL,
tracked_time DATETIME,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(15, "
CREATE VIEW batteries_current
AS
SELECT battery_id, MAX(tracked_time) AS last_tracked_time
FROM battery_charge_cycles
GROUP BY battery_id
ORDER BY MAX(tracked_time) DESC;"
);
$this->ExecuteMigrationWhenNeeded(16, "
ALTER TABLE shopping_list RENAME TO shopping_list_old;"
);
$this->ExecuteMigrationWhenNeeded(17, "
CREATE TABLE shopping_list (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
product_id INTEGER,
note TEXT,
amount INTEGER NOT NULL DEFAULT 0,
amount_autoadded INTEGER NOT NULL DEFAULT 0,
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime'))
)"
);
$this->ExecuteMigrationWhenNeeded(18, "
INSERT INTO shopping_list
(product_id, amount, amount_autoadded, row_created_timestamp)
SELECT product_id, amount, amount_autoadded, row_created_timestamp
FROM shopping_list_old"
);
$this->ExecuteMigrationWhenNeeded(19, "
DROP TABLE shopping_list_old;"
);
} }
private function ExecuteMigrationWhenNeeded(int $migrationId, string $sql) private function ExecuteMigrationWhenNeeded(int $migrationId, string $sql)

View File

@ -2,7 +2,7 @@
namespace Grocy\Services; namespace Grocy\Services;
use Grocy\Services\ApplicationService; use \Grocy\Services\ApplicationService;
class DatabaseService class DatabaseService
{ {

View File

@ -87,7 +87,7 @@ class DemoDataGeneratorService extends BaseService
public function RecreateDemo() public function RecreateDemo()
{ {
unlink(__DIR__ . '/data/grocy.db'); unlink(__DIR__ . '/../data/grocy.db');
$this->PopulateDemoData($this->DatabaseService->GetDbConnectionRaw(true)); $this->PopulateDemoData();
} }
} }

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Batteries')
@section('activeNav', 'batteries')
@section('viewJsName', 'batteries')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -21,27 +25,27 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($batteries as $battery) : ?> @foreach($batteries as $battery)
<tr> <tr>
<td class="fit-content"> <td class="fit-content">
<a class="btn btn-info" href="/battery/<?php echo $battery->id; ?>" role="button"> <a class="btn btn-info" href="/battery/{{ $battery->id }}" role="button">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
<a class="btn btn-danger battery-delete-button" href="#" role="button" data-battery-id="<?php echo $battery->id; ?>" data-battery-name="<?php echo $battery->name; ?>"> <a class="btn btn-danger battery-delete-button" href="#" role="button" data-battery-id="{{ $battery->id }}" data-battery-name="{{ $battery->name }}">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</a> </a>
</td> </td>
<td> <td>
<?php echo $battery->name; ?> {{ $battery->name }}
</td> </td>
<td> <td>
<?php echo $battery->description; ?> {{ $battery->description }}
</td> </td>
<td> <td>
<?php echo $battery->used_in; ?> {{ $battery->used_in }}
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,10 +1,9 @@
<?php
use Grocy\Services\BatteriesService;
$batteriesService = new BatteriesService();
?>
@extends('layout.default') @extends('layout.default')
@section('title', 'Batteries overview')
@section('activeNav', 'batteriesoverview')
@section('viewJsName', 'batteriesoverview')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -20,25 +19,25 @@ $batteriesService = new BatteriesService();
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($current as $curentBatteryEntry) : ?> @foreach($current as $curentBatteryEntry)
<tr class="<?php if (FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0 && $batteriesService->GetNextChargeTime($curentBatteryEntry->battery_id) < date('Y-m-d H:i:s')) echo 'error-bg'; ?>"> <tr class="@if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0 && $nextChargeTimes[$curentBatteryEntry->battery_id] < date('Y-m-d H:i:s')) error-bg @endif">
<td> <td>
<?php echo FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name; ?> {{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}
</td> </td>
<td> <td>
<?php echo $curentBatteryEntry->last_tracked_time; ?> {{ $curentBatteryEntry->last_tracked_time }}
<time class="timeago timeago-contextual" datetime="<?php echo $curentBatteryEntry->last_tracked_time; ?>"></time> <time class="timeago timeago-contextual" datetime="{{ $curentBatteryEntry->last_tracked_time }}"></time>
</td> </td>
<td> <td>
<?php if (FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0): ?> @if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0)
<?php echo $batteriesService->GetNextChargeTime($curentBatteryEntry->battery_id); ?> {{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}
<time class="timeago timeago-contextual" datetime="<?php echo $batteriesService->GetNextChargeTime($curentBatteryEntry->battery_id); ?>"></time> <time class="timeago timeago-contextual" datetime="{{ $nextChargeTimes[$curentBatteryEntry->battery_id] }}"></time>
<?php else: ?> @else
... ...
<?php endif; ?> @endif
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,32 +1,40 @@
@extends('layout.default') @extends('layout.default')
@if($mode == 'edit')
@section('title', 'Edit battery')
@else
@section('title', 'Create battery')
@endif
@section('viewJsName', 'batteryform')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main">
<h1 class="page-header"><?php echo $title; ?></h1> <h1 class="page-header">@yield('title')</h1>
<script>Grocy.EditMode = '<?php echo $mode; ?>';</script> <script>Grocy.EditMode = '{{ $mode }}';</script>
<?php if ($mode == 'edit') : ?> @if($mode == 'edit')
<script>Grocy.EditObjectId = <?php echo $battery->id; ?>;</script> <script>Grocy.EditObjectId = {{ $battery->id }}</script>
<?php endif; ?> @endif
<form id="battery-form"> <form id="battery-form">
<div class="form-group"> <div class="form-group">
<label for="name">Name</label> <label for="name">Name</label>
<input type="text" class="form-control" required id="name" name="name" value="<?php if ($mode == 'edit') echo $battery->name; ?>"> <input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $battery->name }}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="description">Description</label> <label for="description">Description</label>
<input type="text" class="form-control" id="description" name="description" value="<?php if ($mode == 'edit') echo $battery->description; ?>"> <input type="text" class="form-control" id="description" name="description" value="@if($mode == 'edit'){{ $battery->description }}@endif">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="name">Used in</label> <label for="name">Used in</label>
<input type="text" class="form-control" id="used_in" name="used_in" value="<?php if ($mode == 'edit') echo $battery->used_in; ?>"> <input type="text" class="form-control" id="used_in" name="used_in" value="@if($mode == 'edit'){{ $battery->used_in }}@endif">
</div> </div>
<button id="save-battery-button" type="submit" class="btn btn-default">Save</button> <button id="save-battery-button" type="submit" class="btn btn-default">Save</button>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Battery tracking')
@section('activeNav', 'batterytracking')
@section('viewJsName', 'batterytracking')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main">
@ -11,9 +15,9 @@
<label for="battery_id">Battery</label> <label for="battery_id">Battery</label>
<select class="form-control combobox" id="battery_id" name="battery_id" required> <select class="form-control combobox" id="battery_id" name="battery_id" required>
<option value=""></option> <option value=""></option>
<?php foreach ($batteries as $battery) : ?> @foreach($batteries as $battery)
<option value="<?php echo $battery->id; ?>"><?php echo $battery->name; ?></option> <option value="{{ $battery->id }}">{{ $battery->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div id="battery-error" class="help-block with-errors"></div> <div id="battery-error" class="help-block with-errors"></div>
</div> </div>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Consume')
@section('activeNav', 'consume')
@section('viewJsName', 'consume')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main">
@ -11,9 +15,9 @@
<label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i></label> <label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i></label>
<select class="form-control combobox" id="product_id" name="product_id" required> <select class="form-control combobox" id="product_id" name="product_id" required>
<option value=""></option> <option value=""></option>
<?php foreach ($products as $product) : ?> @foreach($products as $product)
<option data-additional-searchdata="<?php echo $product->barcode; ?>" value="<?php echo $product->id; ?>"><?php echo $product->name; ?></option> <option data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div id="product-error" class="help-block with-errors"></div> <div id="product-error" class="help-block with-errors"></div>
</div> </div>

View File

@ -1,42 +1,50 @@
@extends('layout.default') @extends('layout.default')
@if($mode == 'edit')
@section('title', 'Edit habit')
@else
@section('title', 'Create habit')
@endif
@section('viewJsName', 'habitform')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main">
<h1 class="page-header"><?php echo $title; ?></h1> <h1 class="page-header">@yield('title')</h1>
<script>Grocy.EditMode = '<?php echo $mode; ?>';</script> <script>Grocy.EditMode = '{{ $mode }}';</script>
<?php if ($mode == 'edit') : ?> @if($mode == 'edit')
<script>Grocy.EditObjectId = <?php echo $habit->id; ?>;</script> <script>Grocy.EditObjectId = {{ $habit->id }};</script>
<?php endif; ?> @endif
<form id="habit-form"> <form id="habit-form">
<div class="form-group"> <div class="form-group">
<label for="name">Name</label> <label for="name">Name</label>
<input type="text" class="form-control" required id="name" name="name" value="<?php if ($mode == 'edit') echo $habit->name; ?>"> <input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $habit->name }}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="description">Description</label> <label for="description">Description</label>
<textarea class="form-control" rows="2" id="description" name="description"><?php if ($mode == 'edit') echo $habit->description; ?></textarea> <textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $habit->description }}@endif</textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="period_type">Period type</label> <label for="period_type">Period type</label>
<select required class="form-control input-group-habit-period-type" id="period_type" name="period_type"> <select required class="form-control input-group-habit-period-type" id="period_type" name="period_type">
<?php foreach ($periodTypes as $periodType) : ?> @foreach($periodTypes as $periodType)
<option <?php if ($mode == 'edit' && $periodType == $habit->period_type) echo 'selected="selected"'; ?> value="<?php echo $periodType; ?>"><?php echo $periodType; ?></option> <option @if($mode == 'edit' && $periodType == $habit->period_type) selected="selected" @endif value="{{ $periodType }}">{{ $periodType }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="period_days">Period days</label> <label for="period_days">Period days</label>
<input type="number" class="form-control input-group-habit-period-type" id="period_days" name="period_days" value="<?php if ($mode == 'edit') echo $habit->period_days; ?>"> <input type="number" class="form-control input-group-habit-period-type" id="period_days" name="period_days" value="@if($mode == 'edit'){{ $habit->period_days }}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Habits')
@section('activeNav', 'habits')
@section('viewJsName', 'habits')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -22,30 +26,30 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($habits as $habit) : ?> @foreach($habits as $habit)
<tr> <tr>
<td class="fit-content"> <td class="fit-content">
<a class="btn btn-info" href="/habit/<?php echo $habit->id; ?>" role="button"> <a class="btn btn-info" href="/habit/{{ $habit->id }}" role="button">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
<a class="btn btn-danger habit-delete-button" href="#" role="button" data-habit-id="<?php echo $habit->id; ?>" data-habit-name="<?php echo $habit->name; ?>"> <a class="btn btn-danger habit-delete-button" href="#" role="button" data-habit-id="{{ $habit->id }}" data-habit-name="{{ $habit->name }}">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</a> </a>
</td> </td>
<td> <td>
<?php echo $habit->name; ?> {{ $habit->name }}
</td> </td>
<td> <td>
<?php echo $habit->period_type; ?> {{ $habit->period_type }}
</td> </td>
<td> <td>
<?php echo $habit->period_days; ?> {{ $habit->period_days }}
</td> </td>
<td> <td>
<?php echo $habit->description; ?> {{ $habit->description }}
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,10 +1,9 @@
<?php
use Grocy\Services\HabitsService;
$habitsService = new HabitsService();
?>
@extends('layout.default') @extends('layout.default')
@section('title', 'Habits overview')
@section('activeNav', 'habitsoverview')
@section('viewJsName', 'habitsoverview')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -20,25 +19,25 @@ $habitsService = new HabitsService();
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($currentHabits as $curentHabitEntry) : ?> @foreach($currentHabits as $curentHabitEntry)
<tr class="<?php if (FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === HabitsService::HABIT_TYPE_DYNAMIC_REGULAR && $habitsService->GetNextHabitTime($curentHabitEntry->habit_id) < date('Y-m-d H:i:s')) echo 'error-bg'; ?>"> <tr class="@if(FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === \Grocy\Services\HabitsService::HABIT_TYPE_DYNAMIC_REGULAR && $nextHabitTimes[$curentHabitEntry->habit_id] < date('Y-m-d H:i:s')) error-bg @endif">
<td> <td>
<?php echo FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->name; ?> {{ FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->name }}
</td> </td>
<td> <td>
<?php if (FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === HabitsService::HABIT_TYPE_DYNAMIC_REGULAR): ?> @if(FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === \Grocy\Services\HabitsService::HABIT_TYPE_DYNAMIC_REGULAR)
<?php echo $habitsService->GetNextHabitTime($curentHabitEntry->habit_id); ?> {{ $nextHabitTimes[$curentHabitEntry->habit_id] }}
<time class="timeago timeago-contextual" datetime="<?php echo $habitsService->GetNextHabitTime($curentHabitEntry->habit_id); ?>"></time> <time class="timeago timeago-contextual" datetime="{{ $nextHabitTimes[$curentHabitEntry->habit_id] }}"></time>
<?php else: ?> @else
... ...
<?php endif; ?> @endif
</td> </td>
<td> <td>
<?php echo $curentHabitEntry->last_tracked_time; ?> {{ $curentHabitEntry->last_tracked_time }}
<time class="timeago timeago-contextual" datetime="<?php echo $curentHabitEntry->last_tracked_time; ?>"></time> <time class="timeago timeago-contextual" datetime="{{ $curentHabitEntry->last_tracked_time }}"></time>
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Habit tracking')
@section('activeNav', 'habittracking')
@section('viewJsName', 'habittracking')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main">
@ -11,9 +15,9 @@
<label for="habit_id">Habit</label> <label for="habit_id">Habit</label>
<select class="form-control combobox" id="habit_id" name="habit_id" required> <select class="form-control combobox" id="habit_id" name="habit_id" required>
<option value=""></option> <option value=""></option>
<?php foreach ($habits as $habit) : ?> @foreach($habits as $habit)
<option value="<?php echo $habit->id; ?>"><?php echo $habit->name; ?></option> <option value="{{ $habit->id }}">{{ $habit->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div id="product-error" class="help-block with-errors"></div> <div id="product-error" class="help-block with-errors"></div>
</div> </div>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Inventory')
@section('activeNav', 'inventory')
@section('viewJsName', 'inventory')
@section('content') @section('content')
<div class="col-sm-4 col-sm-offset-3 col-md-3 col-md-offset-2 main"> <div class="col-sm-4 col-sm-offset-3 col-md-3 col-md-offset-2 main">
@ -11,9 +15,9 @@
<label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted hide">&nbsp;&nbsp;Barcode lookup is disabled</span></label> <label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted hide">&nbsp;&nbsp;Barcode lookup is disabled</span></label>
<select class="form-control combobox" id="product_id" name="product_id" required> <select class="form-control combobox" id="product_id" name="product_id" required>
<option value=""></option> <option value=""></option>
<?php foreach ($products as $product) : ?> @foreach($products as $product)
<option data-additional-searchdata="<?php echo $product->barcode; ?>" value="<?php echo $product->id; ?>"><?php echo $product->name; ?></option> <option data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
<div id="flow-info-addbarcodetoselection" class="text-muted small hide"><strong><span id="addbarcodetoselection"></span></strong> will be added to the list of barcodes for the selected product on submit.</div> <div id="flow-info-addbarcodetoselection" class="text-muted small hide"><strong><span id="addbarcodetoselection"></span></strong> will be added to the list of barcodes for the selected product on submit.</div>

View File

@ -1,10 +1,3 @@
<?php
use Grocy\Services\ApplicationService;
$applicationService = new ApplicationService();
?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -18,22 +11,23 @@ $applicationService = new ApplicationService();
<meta name="author" content="Bernd Bestel (bernd@berrnd.de)"> <meta name="author" content="Bernd Bestel (bernd@berrnd.de)">
<link rel="icon" type="image/png" sizes="200x200" href="/img/grocy.png"> <link rel="icon" type="image/png" sizes="200x200" href="/img/grocy.png">
<title><?php echo $title; ?> | grocy</title> <title>@yield('title') | grocy</title>
<link href="/bower_components/bootstrap/dist/css/bootstrap.min.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/bootstrap/dist/css/bootstrap.min.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/font-awesome/css/font-awesome.min.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/font-awesome/css/font-awesome.min.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/bootstrap-datepicker/dist/css/bootstrap-datepicker3.min.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/bootstrap-datepicker/dist/css/bootstrap-datepicker3.min.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/bootstrap-combobox/css/bootstrap-combobox.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/bootstrap-combobox/css/bootstrap-combobox.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/datatables.net-responsive-bs/css/responsive.bootstrap.min.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/datatables.net-responsive-bs/css/responsive.bootstrap.min.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/toastr/toastr.min.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/toastr/toastr.min.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/tagmanager/tagmanager.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/tagmanager/tagmanager.css?v={{ $version }}" rel="stylesheet">
<link href="/bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css?v={{ $version }}" rel="stylesheet">
<link href="/vendor_unmanaged/noto-sans-v6-latin/noto-sans-v6-latin.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/components_unmanaged/noto-sans-v6-latin/noto-sans-v6-latin.css?v={{ $version }}" rel="stylesheet">
<link href="/css/grocy.css?v=<?php echo $applicationService->GetInstalledVersion(); ?>" rel="stylesheet"> <link href="/css/grocy.css?v={{ $version }}" rel="stylesheet">
<script src="/bower_components/jquery/dist/jquery.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/jquery/dist/jquery.min.js?v={{ $version }}"></script>
<script src="/js/grocy.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/js/grocy.js?v={{ $version }}"></script>
<script>Grocy.ActiveNav = '@yield('activeNav', '')';</script>
</head> </head>
<body> <body>
@ -59,54 +53,54 @@ $applicationService = new ApplicationService();
<div id="navbar-mobile" class="navbar-collapse collapse"> <div id="navbar-mobile" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li data-nav-for-page="stockoverview.php"> <li data-nav-for-page="stockoverview">
<a class="discrete-link" href="/stockoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Stock overview</a> <a class="discrete-link" href="/stockoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Stock overview</a>
</li> </li>
<li data-nav-for-page="habitsoverview.php"> <li data-nav-for-page="habitsoverview">
<a class="discrete-link" href="/habitsoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Habits overview</a> <a class="discrete-link" href="/habitsoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Habits overview</a>
</li> </li>
<li data-nav-for-page="batteriesoverview.php"> <li data-nav-for-page="batteriesoverview">
<a class="discrete-link" href="/batteriesoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Batteries overview</a> <a class="discrete-link" href="/batteriesoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Batteries overview</a>
</li> </li>
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li class="disabled"><a href="#"><strong>Record data</strong></a></li> <li class="disabled"><a href="#"><strong>Record data</strong></a></li>
<li data-nav-for-page="purchase.php"> <li data-nav-for-page="purchase">
<a class="discrete-link" href="/purchase"><i class="fa fa-shopping-cart fa-fw"></i>&nbsp;Purchase</a> <a class="discrete-link" href="/purchase"><i class="fa fa-shopping-cart fa-fw"></i>&nbsp;Purchase</a>
</li> </li>
<li data-nav-for-page="consume.php"> <li data-nav-for-page="consume">
<a class="discrete-link" href="/consume"><i class="fa fa-cutlery fa-fw"></i>&nbsp;Consume</a> <a class="discrete-link" href="/consume"><i class="fa fa-cutlery fa-fw"></i>&nbsp;Consume</a>
</li> </li>
<li data-nav-for-page="inventory.php"> <li data-nav-for-page="inventory">
<a class="discrete-link" href="/inventory"><i class="fa fa-list fa-fw"></i>&nbsp;Inventory</a> <a class="discrete-link" href="/inventory"><i class="fa fa-list fa-fw"></i>&nbsp;Inventory</a>
</li> </li>
<li data-nav-for-page="shoppinglist.php"> <li data-nav-for-page="shoppinglist">
<a class="discrete-link" href="/shoppinglist"><i class="fa fa-shopping-bag fa-fw"></i>&nbsp;Shopping list</a> <a class="discrete-link" href="/shoppinglist"><i class="fa fa-shopping-bag fa-fw"></i>&nbsp;Shopping list</a>
</li> </li>
<li data-nav-for-page="habittracking.php"> <li data-nav-for-page="habittracking">
<a class="discrete-link" href="/habittracking"><i class="fa fa-play fa-fw"></i>&nbsp;Habit tracking</a> <a class="discrete-link" href="/habittracking"><i class="fa fa-play fa-fw"></i>&nbsp;Habit tracking</a>
</li> </li>
<li data-nav-for-page="batterytracking.php"> <li data-nav-for-page="batterytracking">
<a class="discrete-link" href="/batterytracking"><i class="fa fa-fire fa-fw"></i>&nbsp;Battery tracking</a> <a class="discrete-link" href="/batterytracking"><i class="fa fa-fire fa-fw"></i>&nbsp;Battery tracking</a>
</li> </li>
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li class="disabled"><a href="#"><strong>Manage master data</strong></a></li> <li class="disabled"><a href="#"><strong>Manage master data</strong></a></li>
<li data-nav-for-page="products.php"> <li data-nav-for-page="products">
<a class="discrete-link" href="/products"><i class="fa fa-product-hunt fa-fw"></i>&nbsp;Products</a> <a class="discrete-link" href="/products"><i class="fa fa-product-hunt fa-fw"></i>&nbsp;Products</a>
</li> </li>
<li data-nav-for-page="locations.php"> <li data-nav-for-page="locations">
<a class="discrete-link" href="/locations"><i class="fa fa-map-marker fa-fw"></i>&nbsp;Locations</a> <a class="discrete-link" href="/locations"><i class="fa fa-map-marker fa-fw"></i>&nbsp;Locations</a>
</li> </li>
<li data-nav-for-page="quantityunits.php"> <li data-nav-for-page="quantityunits">
<a class="discrete-link" href="/quantityunits"><i class="fa fa-balance-scale fa-fw"></i>&nbsp;Quantity units</a> <a class="discrete-link" href="/quantityunits"><i class="fa fa-balance-scale fa-fw"></i>&nbsp;Quantity units</a>
</li> </li>
<li data-nav-for-page="habits.php"> <li data-nav-for-page="habits">
<a class="discrete-link" href="/habits"><i class="fa fa-refresh fa-fw"></i>&nbsp;Habits</a> <a class="discrete-link" href="/habits"><i class="fa fa-refresh fa-fw"></i>&nbsp;Habits</a>
</li> </li>
<li data-nav-for-page="batteries.php"> <li data-nav-for-page="batteries">
<a class="discrete-link" href="/batteries"><i class="fa fa-battery-three-quarters fa-fw"></i>&nbsp;Batteries</a> <a class="discrete-link" href="/batteries"><i class="fa fa-battery-three-quarters fa-fw"></i>&nbsp;Batteries</a>
</li> </li>
</ul> </ul>
@ -123,7 +117,7 @@ $applicationService = new ApplicationService();
<br> <br>
Created with passion since 2017 Created with passion since 2017
<br> <br>
Version <?php echo $applicationService->GetInstalledVersion(); ?> Version {{ $version }}
<br> <br>
Life runs on code Life runs on code
<br> <br>
@ -142,54 +136,54 @@ $applicationService = new ApplicationService();
<div class="col-sm-3 col-md-2 sidebar"> <div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar"> <ul class="nav nav-sidebar">
<li data-nav-for-page="stockoverview.php"> <li data-nav-for-page="stockoverview">
<a class="discrete-link" href="/stockoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Stock overview</a> <a class="discrete-link" href="/stockoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Stock overview</a>
</li> </li>
<li data-nav-for-page="habitsoverview.php"> <li data-nav-for-page="habitsoverview">
<a class="discrete-link" href="/habitsoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Habits overview</a> <a class="discrete-link" href="/habitsoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Habits overview</a>
</li> </li>
<li data-nav-for-page="batteriesoverview.php"> <li data-nav-for-page="batteriesoverview">
<a class="discrete-link" href="/batteriesoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Batteries overview</a> <a class="discrete-link" href="/batteriesoverview"><i class="fa fa-tachometer fa-fw"></i>&nbsp;Batteries overview</a>
</li> </li>
</ul> </ul>
<ul class="nav nav-sidebar"> <ul class="nav nav-sidebar">
<li class="disabled"><a href="#"><strong>Record data</strong></a></li> <li class="disabled"><a href="#"><strong>Record data</strong></a></li>
<li data-nav-for-page="purchase.php"> <li data-nav-for-page="purchase">
<a class="discrete-link" href="/purchase"><i class="fa fa-shopping-cart fa-fw"></i>&nbsp;Purchase</a> <a class="discrete-link" href="/purchase"><i class="fa fa-shopping-cart fa-fw"></i>&nbsp;Purchase</a>
</li> </li>
<li data-nav-for-page="consume.php"> <li data-nav-for-page="consume">
<a class="discrete-link" href="/consume"><i class="fa fa-cutlery fa-fw"></i>&nbsp;Consume</a> <a class="discrete-link" href="/consume"><i class="fa fa-cutlery fa-fw"></i>&nbsp;Consume</a>
</li> </li>
<li data-nav-for-page="inventory.php"> <li data-nav-for-page="inventory">
<a class="discrete-link" href="/inventory"><i class="fa fa-list fa-fw"></i>&nbsp;Inventory</a> <a class="discrete-link" href="/inventory"><i class="fa fa-list fa-fw"></i>&nbsp;Inventory</a>
</li> </li>
<li data-nav-for-page="shoppinglist.php"> <li data-nav-for-page="shoppinglist">
<a class="discrete-link" href="/shoppinglist"><i class="fa fa-shopping-bag fa-fw"></i>&nbsp;Shopping list</a> <a class="discrete-link" href="/shoppinglist"><i class="fa fa-shopping-bag fa-fw"></i>&nbsp;Shopping list</a>
</li> </li>
<li data-nav-for-page="habittracking.php"> <li data-nav-for-page="habittracking">
<a class="discrete-link" href="/habittracking"><i class="fa fa-play fa-fw"></i>&nbsp;Habit tracking</a> <a class="discrete-link" href="/habittracking"><i class="fa fa-play fa-fw"></i>&nbsp;Habit tracking</a>
</li> </li>
<li data-nav-for-page="batterytracking.php"> <li data-nav-for-page="batterytracking">
<a class="discrete-link" href="/batterytracking"><i class="fa fa-fire fa-fw"></i>&nbsp;Battery tracking</a> <a class="discrete-link" href="/batterytracking"><i class="fa fa-fire fa-fw"></i>&nbsp;Battery tracking</a>
</li> </li>
</ul> </ul>
<ul class="nav nav-sidebar"> <ul class="nav nav-sidebar">
<li class="disabled"><a href="#"><strong>Manage master data</strong></a></li> <li class="disabled"><a href="#"><strong>Manage master data</strong></a></li>
<li data-nav-for-page="products.php"> <li data-nav-for-page="products">
<a class="discrete-link" href="/products"><i class="fa fa-product-hunt fa-fw"></i>&nbsp;Products</a> <a class="discrete-link" href="/products"><i class="fa fa-product-hunt fa-fw"></i>&nbsp;Products</a>
</li> </li>
<li data-nav-for-page="locations.php"> <li data-nav-for-page="locations">
<a class="discrete-link" href="/locations"><i class="fa fa-map-marker fa-fw"></i>&nbsp;Locations</a> <a class="discrete-link" href="/locations"><i class="fa fa-map-marker fa-fw"></i>&nbsp;Locations</a>
</li> </li>
<li data-nav-for-page="quantityunits.php"> <li data-nav-for-page="quantityunits">
<a class="discrete-link" href="/quantityunits"><i class="fa fa-balance-scale fa-fw"></i>&nbsp;Quantity units</a> <a class="discrete-link" href="/quantityunits"><i class="fa fa-balance-scale fa-fw"></i>&nbsp;Quantity units</a>
</li> </li>
<li data-nav-for-page="habits.php"> <li data-nav-for-page="habits">
<a class="discrete-link" href="/habits"><i class="fa fa-refresh fa-fw"></i>&nbsp;Habits</a> <a class="discrete-link" href="/habits"><i class="fa fa-refresh fa-fw"></i>&nbsp;Habits</a>
</li> </li>
<li data-nav-for-page="batteries.php"> <li data-nav-for-page="batteries">
<a class="discrete-link" href="/batteries"><i class="fa fa-battery-three-quarters fa-fw"></i>&nbsp;Batteries</a> <a class="discrete-link" href="/batteries"><i class="fa fa-battery-three-quarters fa-fw"></i>&nbsp;Batteries</a>
</li> </li>
</ul> </ul>
@ -200,7 +194,7 @@ $applicationService = new ApplicationService();
<br> <br>
Created with passion since 2017 Created with passion since 2017
<br> <br>
Version <?php echo $applicationService->GetInstalledVersion(); ?> Version {{ $version }}
<br> <br>
Life runs on code Life runs on code
<br> <br>
@ -211,33 +205,32 @@ $applicationService = new ApplicationService();
</div> </div>
<script>Grocy.ContentPage = '{{ $contentPage }}';</script>
@section('content') @section('content')
@show @show
</div> </div>
</div> </div>
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/bootstrap/dist/js/bootstrap.min.js?v={{ $version }}"></script>
<script src="/bower_components/bootbox/bootbox.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/bootbox/bootbox.js?v={{ $version }}"></script>
<script src="/bower_components/jquery.serializeJSON/jquery.serializejson.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/jquery.serializeJSON/jquery.serializejson.min.js?v={{ $version }}"></script>
<script src="/bower_components/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js?v={{ $version }}"></script>
<script src="/bower_components/moment/min/moment.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/moment/min/moment.min.js?v={{ $version }}"></script>
<script src="/bower_components/bootstrap-validator/dist/validator.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/bootstrap-validator/dist/validator.min.js?v={{ $version }}"></script>
<script src="/bower_components/bootstrap-combobox/js/bootstrap-combobox.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/bootstrap-combobox/js/bootstrap-combobox.js?v={{ $version }}"></script>
<script src="/bower_components/datatables.net/js/jquery.dataTables.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/datatables.net/js/jquery.dataTables.min.js?v={{ $version }}"></script>
<script src="/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js?v={{ $version }}"></script>
<script src="/bower_components/datatables.net-responsive/js/dataTables.responsive.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/datatables.net-responsive/js/dataTables.responsive.min.js?v={{ $version }}"></script>
<script src="/bower_components/datatables.net-responsive-bs/js/responsive.bootstrap.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/datatables.net-responsive-bs/js/responsive.bootstrap.min.js?v={{ $version }}"></script>
<script src="/bower_components/jquery-timeago/jquery.timeago.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/jquery-timeago/jquery.timeago.js?v={{ $version }}"></script>
<script src="/bower_components/toastr/toastr.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/toastr/toastr.min.js?v={{ $version }}"></script>
<script src="/bower_components/tagmanager/tagmanager.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/tagmanager/tagmanager.js?v={{ $version }}"></script>
<script src="/bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js?v=<?php echo $applicationService->GetInstalledVersion(); ?>"></script> <script src="/bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js?v={{ $version }}"></script>
<?php if (file_exists(__DIR__ . '/../../public/viewjs/' . str_replace('.php', '.js', $contentPage))) : ?> <script src="/viewjs/@yield('viewJsName').js"></script>
<script src="/viewjs/<?php echo str_replace('.php', '.js', $contentPage) . '?v=' . $applicationService->GetInstalledVersion(); ?>"></script>
<?php endif; ?>
<?php if (file_exists(__DIR__ . '/../data/add_before_end_body.html')) include __DIR__ . '/../data/add_before_end_body.html' ?> @if(file_exists(__DIR__ . '/../../data/add_before_end_body.html'))
@php include __DIR__ . '/../../data/add_before_end_body.html' @endphp
@endif
</body> </body>
</html> </html>

View File

@ -1,27 +1,35 @@
@extends('layout.default') @extends('layout.default')
@if($mode == 'edit')
@section('title', 'Edit location')
@else
@section('title', 'Create location')
@endif
@section('viewJsName', 'locationform')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main">
<h1 class="page-header"><?php echo $title; ?></h1> <h1 class="page-header">@yield('title')</h1>
<script>Grocy.EditMode = '<?php echo $mode; ?>';</script> <script>Grocy.EditMode = '{{ $mode }}';</script>
<?php if ($mode == 'edit') : ?> @if($mode == 'edit')
<script>Grocy.EditObjectId = <?php echo $location->id; ?>;</script> <script>Grocy.EditObjectId = {{ $location->id }};</script>
<?php endif; ?> @endif
<form id="location-form"> <form id="location-form">
<div class="form-group"> <div class="form-group">
<label for="name">Name</label> <label for="name">Name</label>
<input type="text" class="form-control" required id="name" name="name" value="<?php if ($mode == 'edit') echo $location->name; ?>"> <input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $location->name }}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="description">Description</label> <label for="description">Description</label>
<textarea class="form-control" rows="2" id="description" name="description"><?php if ($mode == 'edit') echo $location->description; ?></textarea> <textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $location->description }}@endif</textarea>
</div> </div>
<button id="save-location-button" type="submit" class="btn btn-default">Save</button> <button id="save-location-button" type="submit" class="btn btn-default">Save</button>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Locations')
@section('activeNav', 'locations')
@section('viewJsName', 'locations')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -20,24 +24,24 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($locations as $location) : ?> @foreach($locations as $location)
<tr> <tr>
<td class="fit-content"> <td class="fit-content">
<a class="btn btn-info" href="/location/<?php echo $location->id; ?>" role="button"> <a class="btn btn-info" href="/location/{{ $location->id }}" role="button">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
<a class="btn btn-danger location-delete-button" href="#" role="button" data-location-id="<?php echo $location->id; ?>" data-location-name="<?php echo $location->name; ?>"> <a class="btn btn-danger location-delete-button" href="#" role="button" data-location-id="{{ $location->id }}" data-location-name="{{ $location->name }}">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</a> </a>
</td> </td>
<td> <td>
<?php echo $location->name; ?> {{ $location->name }}
</td> </td>
<td> <td>
<?php echo $location->description; ?> {{ $location->description }}
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,5 +1,8 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Login')
@section('viewJsName', 'login')
@section('content') @section('content')
<div class="col-md-4 col-md-offset-5 main"> <div class="col-md-4 col-md-offset-5 main">

View File

@ -1,27 +1,35 @@
@extends('layout.default') @extends('layout.default')
@if($mode == 'edit')
@section('title', 'Edit product')
@else
@section('title', 'Create product')
@endif
@section('viewJsName', 'productform')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main">
<h1 class="page-header"><?php echo $title; ?></h1> <h1 class="page-header">@yield('title')</h1>
<script>Grocy.EditMode = '<?php echo $mode; ?>';</script> <script>Grocy.EditMode = '{{ $mode }}';</script>
<?php if ($mode == 'edit') : ?> @if($mode == 'edit')
<script>Grocy.EditObjectId = <?php echo $product->id; ?>;</script> <script>Grocy.EditObjectId = {{ $product->id }};</script>
<?php endif; ?> @endif
<form id="product-form"> <form id="product-form">
<div class="form-group"> <div class="form-group">
<label for="name">Name</label> <label for="name">Name</label>
<input type="text" class="form-control" required id="name" name="name" value="<?php if ($mode == 'edit') echo $product->name; ?>"> <input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $product->name}}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="description">Description</label> <label for="description">Description</label>
<textarea class="form-control" rows="2" id="description" name="description"><?php if ($mode == 'edit') echo $product->description; ?></textarea> <textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $product->description }}@endif</textarea>
</div> </div>
<div class="form-group tm-group"> <div class="form-group tm-group">
@ -33,31 +41,31 @@
<div class="form-group"> <div class="form-group">
<label for="location_id">Location</label> <label for="location_id">Location</label>
<select required class="form-control" id="location_id" name="location_id"> <select required class="form-control" id="location_id" name="location_id">
<?php foreach ($locations as $location) : ?> @foreach($locations as $location)
<option <?php if ($mode == 'edit' && $location->id == $product->location_id) echo 'selected="selected"'; ?> value="<?php echo $location->id; ?>"><?php echo $location->name; ?></option> <option @if($mode == 'edit' && $location->id == $product->location_id) selected="selected" @endif value="{{ $location->id }}">{{ $location->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="min_stock_amount">Minimum stock amount</label> <label for="min_stock_amount">Minimum stock amount</label>
<input required min="0" type="number" class="form-control" id="min_stock_amount" name="min_stock_amount" value="<?php if ($mode == 'edit') echo $product->min_stock_amount; else echo '0'; ?>"> <input required min="0" type="number" class="form-control" id="min_stock_amount" name="min_stock_amount" value="@if($mode == 'edit'){{ $product->min_stock_amount }}@else{{0}}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="default_best_before_days">Default best before days<br><span class="small text-muted">For purchases this amount of days will be added to today for the best before date suggestion</span></label> <label for="default_best_before_days">Default best before days<br><span class="small text-muted">For purchases this amount of days will be added to today for the best before date suggestion</span></label>
<input required min="0" type="number" class="form-control" id="default_best_before_days" name="default_best_before_days" value="<?php if ($mode == 'edit') echo $product->default_best_before_days; else echo '0'; ?>"> <input required min="0" type="number" class="form-control" id="default_best_before_days" name="default_best_before_days" value="@if($mode == 'edit'){{ $product->default_best_before_days }}@else{{0}}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="qu_id_purchase">Quantity unit purchase</label> <label for="qu_id_purchase">Quantity unit purchase</label>
<select required class="form-control input-group-qu" id="qu_id_purchase" name="qu_id_purchase"> <select required class="form-control input-group-qu" id="qu_id_purchase" name="qu_id_purchase">
<?php foreach ($quantityunits as $quantityunit) : ?> @foreach($quantityunits as $quantityunit)
<option <?php if ($mode == 'edit' && $quantityunit->id == $product->qu_id_purchase) echo 'selected="selected"'; ?> value="<?php echo $quantityunit->id; ?>"><?php echo $quantityunit->name; ?></option> <option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_purchase) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
@ -65,16 +73,16 @@
<div class="form-group"> <div class="form-group">
<label for="qu_id_stock">Quantity unit stock</label> <label for="qu_id_stock">Quantity unit stock</label>
<select required class="form-control input-group-qu" id="qu_id_stock" name="qu_id_stock"> <select required class="form-control input-group-qu" id="qu_id_stock" name="qu_id_stock">
<?php foreach ($quantityunits as $quantityunit) : ?> @foreach($quantityunits as $quantityunit)
<option <?php if ($mode == 'edit' && $quantityunit->id == $product->qu_id_stock) echo 'selected="selected"'; ?> value="<?php echo $quantityunit->id; ?>"><?php echo $quantityunit->name; ?></option> <option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_stock) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="qu_factor_purchase_to_stock">Factor purchase to stock quantity unit</label> <label for="qu_factor_purchase_to_stock">Factor purchase to stock quantity unit</label>
<input required min="1" type="number" class="form-control input-group-qu" id="qu_factor_purchase_to_stock" name="qu_factor_purchase_to_stock" value="<?php if ($mode == 'edit') echo $product->qu_factor_purchase_to_stock; else echo '1'; ?>"> <input required min="1" type="number" class="form-control input-group-qu" id="qu_factor_purchase_to_stock" name="qu_factor_purchase_to_stock" value="@if ($mode == 'edit'){{ $product->qu_factor_purchase_to_stock }}@else{{1}}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Products')
@section('activeNav', 'products')
@section('viewJsName', 'products')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -25,39 +29,39 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($products as $product) : ?> @foreach($products as $product)
<tr> <tr>
<td class="fit-content"> <td class="fit-content">
<a class="btn btn-info" href="/product/<?php echo $product->id; ?>" role="button"> <a class="btn btn-info" href="/product/{{ $product->id }}" role="button">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
<a class="btn btn-danger product-delete-button" href="#" role="button" data-product-id="<?php echo $product->id; ?>" data-product-name="<?php echo $product->name; ?>"> <a class="btn btn-danger product-delete-button" href="#" role="button" data-product-id="{{ $product->id }}" data-product-name="{{ $product->name }}">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</a> </a>
</td> </td>
<td> <td>
<?php echo $product->name; ?> {{ $product->name }}
</td> </td>
<td> <td>
<?php echo FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name; ?> {{ FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name }}
</td> </td>
<td> <td>
<?php echo $product->min_stock_amount; ?> {{ $product->min_stock_amount }}
</td> </td>
<td> <td>
<?php echo FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_purchase)->name; ?> {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_purchase)->name }}
</td> </td>
<td> <td>
<?php echo FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_stock)->name; ?> {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', $product->qu_id_stock)->name }}
</td> </td>
<td> <td>
<?php echo $product->qu_factor_purchase_to_stock; ?> {{ $product->qu_factor_purchase_to_stock }}
</td> </td>
<td> <td>
<?php echo $product->description; ?> {{ $product->description }}
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Purchase')
@section('activeNav', 'purchase')
@section('viewJsName', 'purchase')
@section('content') @section('content')
<div class="col-sm-4 col-sm-offset-3 col-md-3 col-md-offset-2 main"> <div class="col-sm-4 col-sm-offset-3 col-md-3 col-md-offset-2 main">
@ -11,9 +15,9 @@
<label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted hide">&nbsp;&nbsp;Barcode lookup is disabled</span></label> <label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i><span id="barcode-lookup-disabled-hint" class="small text-muted hide">&nbsp;&nbsp;Barcode lookup is disabled</span></label>
<select class="form-control combobox" id="product_id" name="product_id" required> <select class="form-control combobox" id="product_id" name="product_id" required>
<option value=""></option> <option value=""></option>
<?php foreach ($products as $product) : ?> @foreach($products as $product)
<option data-additional-searchdata="<?php echo $product->barcode; ?>" value="<?php echo $product->id; ?>"><?php echo $product->name; ?></option> <option data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
<div id="flow-info-addbarcodetoselection" class="text-muted small hide"><strong><span id="addbarcodetoselection"></span></strong> will be added to the list of barcodes for the selected product on submit.</div> <div id="flow-info-addbarcodetoselection" class="text-muted small hide"><strong><span id="addbarcodetoselection"></span></strong> will be added to the list of barcodes for the selected product on submit.</div>

View File

@ -1,27 +1,35 @@
@extends('layout.default') @extends('layout.default')
@if($mode == 'edit')
@section('title', 'Edit quantity unit')
@else
@section('title', 'Create quantity unit')
@endif
@section('viewJsName', 'quantityunitform')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-4 col-md-offset-2 main">
<h1 class="page-header"><?php echo $title; ?></h1> <h1 class="page-header">@yield('title')</h1>
<script>Grocy.EditMode = '<?php echo $mode; ?>';</script> <script>Grocy.EditMode = '{{ $mode }}';</script>
<?php if ($mode == 'edit') : ?> @if($mode == 'edit')
<script>Grocy.EditObjectId = <?php echo $quantityunit->id; ?>;</script> <script>Grocy.EditObjectId = {{ $quantityunit->id }};</script>
<?php endif; ?> @endif
<form id="quantityunit-form"> <form id="quantityunit-form">
<div class="form-group"> <div class="form-group">
<label for="name">Name</label> <label for="name">Name</label>
<input type="text" class="form-control" required id="name" name="name" value="<?php if ($mode == 'edit') echo $quantityunit->name; ?>"> <input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $quantityunit->name }}@endif">
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="description">Description</label> <label for="description">Description</label>
<textarea class="form-control" rows="2" id="description" name="description"><?php if ($mode == 'edit') echo $quantityunit->description; ?></textarea> <textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $quantityunit->description }}@endif</textarea>
</div> </div>
<button id="save-quantityunit-button" type="submit" class="btn btn-default">Save</button> <button id="save-quantityunit-button" type="submit" class="btn btn-default">Save</button>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Quantity units')
@section('activeNav', 'quantityunits')
@section('viewJsName', 'quantityunits')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -20,24 +24,24 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($quantityunits as $quantityunit) : ?> @foreach($quantityunits as $quantityunit)
<tr> <tr>
<td class="fit-content"> <td class="fit-content">
<a class="btn btn-info" href="/quantityunit/<?php echo $quantityunit->id; ?>" role="button"> <a class="btn btn-info" href="/quantityunit/{{ $quantityunit->id }}" role="button">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
<a class="btn btn-danger quantityunit-delete-button" href="#" role="button" data-quantityunit-id="<?php echo $quantityunit->id; ?>" data-quantityunit-name="<?php echo $quantityunit->name; ?>"> <a class="btn btn-danger quantityunit-delete-button" href="#" role="button" data-quantityunit-id="{{ $quantityunit->id }}" data-quantityunit-name="{{ $quantityunit->name }}">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</a> </a>
</td> </td>
<td> <td>
<?php echo $quantityunit->name; ?> {{ $quantityunit->name }}
</td> </td>
<td> <td>
<?php echo $quantityunit->description; ?> {{ $quantityunit->description }}
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,5 +1,9 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Shopping list')
@section('activeNav', 'shoppinglist')
@section('viewJsName', 'shoppinglist')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
@ -23,24 +27,24 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($listItems as $listItem) : ?> @foreach($listItems as $listItem)
<tr class="<?php if ($listItem->amount_autoadded > 0) echo 'info-bg'; ?>"> <tr class="@if($listItem->amount_autoadded > 0) info-bg @endif">
<td class="fit-content"> <td class="fit-content">
<a class="btn btn-info" href="/shoppinglistitem/<?php echo $listItem->id; ?>" role="button"> <a class="btn btn-info" href="/shoppinglistitem/{{ $listItem->id }}" role="button">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
<a class="btn btn-danger shoppinglist-delete-button" href="#" role="button" data-shoppinglist-id="<?php echo $listItem->id; ?>"> <a class="btn btn-danger shoppinglist-delete-button" href="#" role="button" data-shoppinglist-id="{{ $listItem->id }}">
<i class="fa fa-trash"></i> <i class="fa fa-trash"></i>
</a> </a>
</td> </td>
<td> <td>
<?php if (!empty($listItem->product_id)) echo FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name . '<br>'; ?><em><?php echo $listItem->note; ?></em> @if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name }}<br>@endif<em>{{ $listItem->note }}</em>
</td> </td>
<td> <td>
<?php echo $listItem->amount + $listItem->amount_autoadded; if (!empty($listItem->product_id)) echo ' ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name; ?> {{ $listItem->amount + $listItem->amount_autoadded }} @if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name }}@endif
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,38 +1,46 @@
@extends('layout.default') @extends('layout.default')
@if($mode == 'edit')
@section('title', 'Edit shopping list item')
@else
@section('title', 'Create shopping list item')
@endif
@section('viewJsName', 'shoppinglistform')
@section('content') @section('content')
<div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main"> <div class="col-sm-3 col-sm-offset-3 col-md-3 col-md-offset-2 main">
<h1 class="page-header"><?php echo $title; ?></h1> <h1 class="page-header">@yield('title')</h1>
<script>Grocy.EditMode = '<?php echo $mode; ?>';</script> <script>Grocy.EditMode = '{{ $mode }}';</script>
<?php if ($mode == 'edit') : ?> @if($mode == 'edit')
<script>Grocy.EditObjectId = <?php echo $listItem->id; ?>;</script> <script>Grocy.EditObjectId = {{ $listItem->id }};</script>
<?php endif; ?> @endif
<form id="shoppinglist-form"> <form id="shoppinglist-form">
<div class="form-group"> <div class="form-group">
<label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i></label> <label for="product_id">Product&nbsp;&nbsp;<i class="fa fa-barcode"></i></label>
<select class="form-control combobox" id="product_id" name="product_id" value="<?php if ($mode == 'edit') echo $listItem->product_id; ?>"> <select class="form-control combobox" id="product_id" name="product_id" value="@if($mode == 'edit') {{ $listItem->product_id }} @endif">
<option value=""></option> <option value=""></option>
<?php foreach ($products as $product) : ?> @foreach($products as $product)
<option <?php if ($mode == 'edit' && $product->id == $listItem->product_id) echo 'selected="selected"'; ?> data-additional-searchdata="<?php echo $product->barcode; ?>" value="<?php echo $product->id; ?>"><?php echo $product->name; ?></option> <option @if($mode == 'edit' && $product->id == $listItem->product_id) selected="selected" @endif data-additional-searchdata="{{ $product->barcode }}" value="{{ $product->id }}">{{ $product->name }}</option>
<?php endforeach; ?> @endforeach
</select> </select>
<div id="product-error" class="help-block with-errors"></div> <div id="product-error" class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="amount">Amount&nbsp;&nbsp;<span id="amount_qu_unit" class="small text-muted"></span><br><span class="small text-warning"><?php if ($mode == 'edit' && $listItem->amount_autoadded > 0) echo $listItem->amount_autoadded . " units were automatically added and will apply in addition to the amount entered here."; ?></span></label> <label for="amount">Amount&nbsp;&nbsp;<span id="amount_qu_unit" class="small text-muted"></span><br><span class="small text-warning">@if($mode == 'edit' && $listItem->amount_autoadded > 0){{ $listItem->amount_autoadded }} units were automatically added and will apply in addition to the amount entered here.@endif</span></label>
<input type="number" class="form-control" id="amount" name="amount" value="<?php if ($mode == 'edit') echo $listItem->amount; else echo '1'; ?>" min="0" required> <input type="number" class="form-control" id="amount" name="amount" value="@if($mode == 'edit'){{ $listItem->amount }}@else{{1}}@endif" min="0" required>
<div class="help-block with-errors"></div> <div class="help-block with-errors"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="note">Note</label> <label for="note">Note</label>
<textarea class="form-control" rows="2" id="note" name="note"><?php if ($mode == 'edit') echo $listItem->note; ?></textarea> <textarea class="form-control" rows="2" id="note" name="note">@if($mode == 'edit'){{ $listItem->note }}@endif</textarea>
</div> </div>
<button id="save-shoppinglist-button" type="submit" class="btn btn-default">Save</button> <button id="save-shoppinglist-button" type="submit" class="btn btn-default">Save</button>

View File

@ -1,15 +1,19 @@
@extends('layout.default') @extends('layout.default')
@section('title', 'Stock overview')
@section('activeNav', 'stockoverview')
@section('viewJsName', 'stockoverview')
@section('content') @section('content')
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header">Stock overview <span class="text-muded small"><strong><?php echo count($currentStock) ?></strong> products with <strong><?php echo SumArrayValue($currentStock, 'amount'); ?></strong> units in stock</span></h1> <h1 class="page-header">Stock overview <span class="text-muded small"><strong>{{ count($currentStock) }}</strong> products with <strong>{{ SumArrayValue($currentStock, 'amount') }}</strong> units in stock</span></h1>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<p class="btn btn-lg btn-warning no-real-button"><strong><?php echo count(FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d', strtotime('+5 days')), '<')); ?></strong> products expiring within the next 5 days</p> <p class="btn btn-lg btn-warning no-real-button"><strong>{{ count(FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d', strtotime('+5 days')), '<')) }}</strong> products expiring within the next 5 days</p>
<p class="btn btn-lg btn-danger no-real-button"><strong><?php echo count(FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d', strtotime('-1 days')), '<')); ?></strong> products are already expired</p> <p class="btn btn-lg btn-danger no-real-button"><strong>{{ count(FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d', strtotime('-1 days')), '<')) }}</strong> products are already expired</p>
<p class="btn btn-lg btn-info no-real-button"><strong><?php echo count($missingProducts); ?></strong> products are below defined min. stock amount</p> <p class="btn btn-lg btn-info no-real-button"><strong>{{ count($missingProducts) }}</strong> products are below defined min. stock amount</p>
</div> </div>
</div> </div>
@ -25,20 +29,20 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($currentStock as $currentStockEntry) : ?> @foreach($currentStock as $currentStockEntry)
<tr class="<?php if ($currentStockEntry->best_before_date < date('Y-m-d', strtotime('-1 days'))) echo 'error-bg'; else if ($currentStockEntry->best_before_date < date('Y-m-d', strtotime('+5 days'))) echo 'warning-bg'; else if (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) echo 'info-bg'; ?>"> <tr class="@if($currentStockEntry->best_before_date < date('Y-m-d', strtotime('-1 days'))) error-bg @elseif($currentStockEntry->best_before_date < date('Y-m-d', strtotime('+5 days'))) warning-bg @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) info-bg @endif">
<td> <td>
<?php echo FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name; ?> {{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}
</td> </td>
<td> <td>
<?php echo $currentStockEntry->amount . ' ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name; ?> {{ $currentStockEntry->amount . ' ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}
</td> </td>
<td> <td>
<?php echo $currentStockEntry->best_before_date; ?> {{ $currentStockEntry->best_before_date }}
<time class="timeago timeago-contextual" datetime="<?php echo $currentStockEntry->best_before_date; ?>"></time> <time class="timeago timeago-contextual" datetime="{{ $currentStockEntry->best_before_date }}"></time>
</td> </td>
</tr> </tr>
<?php endforeach; ?> @endforeach
</tbody> </tbody>
</table> </table>
</div> </div>