save
This commit is contained in:
parent
662394d7c3
commit
a2d5494f15
|
@ -4,6 +4,7 @@
|
||||||
//
|
//
|
||||||
use app\app;
|
use app\app;
|
||||||
use app\controllers\account;
|
use app\controllers\account;
|
||||||
|
use app\controllers\address;
|
||||||
use app\controllers\admin;
|
use app\controllers\admin;
|
||||||
use app\controllers\cart;
|
use app\controllers\cart;
|
||||||
use app\controllers\category;
|
use app\controllers\category;
|
||||||
|
@ -14,6 +15,7 @@ use app\controllers\lost;
|
||||||
use app\controllers\magic_link;
|
use app\controllers\magic_link;
|
||||||
use app\controllers\support;
|
use app\controllers\support;
|
||||||
use app\controllers\transaction;
|
use app\controllers\transaction;
|
||||||
|
use app\models\user_settings;
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
@ -36,17 +38,25 @@ if (! isset($_SESSION['fingerprint'])) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// these will be available to use in all twig templates
|
// these will be available to use in all twig templates
|
||||||
|
$user_settings = isset($_SESSION['user_id']) ? user_settings::getByUserId($_SESSION['user_id']) : null;
|
||||||
|
$theme = 'light';
|
||||||
|
if (isset($_SESSION['user_id']) && $user_settings !== null && isset($user_settings['dark_theme'])) {
|
||||||
|
$theme = $user_settings['dark_theme'] ? 'dark' : 'light';
|
||||||
|
} elseif (isset($_COOKIE["theme"])) {
|
||||||
|
$theme = $_COOKIE["theme"];
|
||||||
|
}
|
||||||
$defaults = [
|
$defaults = [
|
||||||
'copyright_year' => date('Y'),
|
'copyright_year' => date('Y'),
|
||||||
'session' => $_SESSION,
|
'session' => $_SESSION,
|
||||||
'http_host' => $_SERVER['HTTP_HOST'],
|
'http_host' => $_SERVER['HTTP_HOST'],
|
||||||
'env' => $_ENV,
|
'env' => $_ENV,
|
||||||
'is_user' => isset($_SESSION['user_id']),
|
'is_user' => isset($_SESSION['user_id']),
|
||||||
|
'user_settings' => $user_settings,
|
||||||
'is_admin' => isset($_SESSION['user_id']) && $_SESSION['user_id'] == 1,
|
'is_admin' => isset($_SESSION['user_id']) && $_SESSION['user_id'] == 1,
|
||||||
// uses cookie-js to get the client's preferred theme
|
// uses cookie-js to get the client's preferred theme
|
||||||
// used to conditionally deliver image assets
|
// used to conditionally deliver image assets
|
||||||
// or styles based on theme
|
// or styles based on theme
|
||||||
'theme' => isset($_COOKIE["theme"]) ? $_COOKIE["theme"] : 'light',
|
'theme' => $theme,
|
||||||
// set your tailwind colors here for app themeing
|
// set your tailwind colors here for app themeing
|
||||||
// the idea is to avoid using colors in your templates
|
// the idea is to avoid using colors in your templates
|
||||||
'colors' => require dirname(__DIR__) . '/src/colors.php',
|
'colors' => require dirname(__DIR__) . '/src/colors.php',
|
||||||
|
@ -64,10 +74,12 @@ if (str_starts_with(haystack: $route, needle: '/.well-known/lnurlp/')) {
|
||||||
$route = '/lnurlp';
|
$route = '/lnurlp';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combined regex to match multiple dynamic routes in one go
|
// Use this controller for routes that include a model ID
|
||||||
if (preg_match('/^\/(transaction|user|order|product)\/([\w-]+)$/', $route, $matches)) {
|
if (preg_match('/^\/(address(?:\/edit|\/delete)?|transaction|user|order|quote|product|subscription|cart)\/([\w-]+)$/', $route, $matches)) {
|
||||||
[$full, $type, $id] = $matches;
|
[$full, $type, $id] = $matches;
|
||||||
$controllers = [
|
$controller = [
|
||||||
|
'address/edit' => fn($id) => address::edit($defaults, $id),
|
||||||
|
'address/delete' => fn($id) => address::delete($defaults, $id),
|
||||||
'transaction' => fn($id) => transaction::view($defaults, $id),
|
'transaction' => fn($id) => transaction::view($defaults, $id),
|
||||||
'user' => fn($id) => users::view($id),
|
'user' => fn($id) => users::view($id),
|
||||||
'order' => fn($id) => orders::view($id),
|
'order' => fn($id) => orders::view($id),
|
||||||
|
@ -77,10 +89,10 @@ if (preg_match('/^\/(transaction|user|order|product)\/([\w-]+)$/', $route, $matc
|
||||||
'cart' => fn($id) => cart::index($id),
|
'cart' => fn($id) => cart::index($id),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isset($controllers[$type])) {
|
if (isset($controller[$type])) {
|
||||||
$controller = $controllers[$type]($id);
|
$controller = $controller[$type]($id);
|
||||||
}
|
}
|
||||||
} else {
|
} else { // Use this controller for static routes
|
||||||
$controller = match ($route) {
|
$controller = match ($route) {
|
||||||
'/' => home::index($defaults),
|
'/' => home::index($defaults),
|
||||||
'/account/login' => account::login($defaults),
|
'/account/login' => account::login($defaults),
|
||||||
|
@ -95,7 +107,8 @@ if (preg_match('/^\/(transaction|user|order|product)\/([\w-]+)$/', $route, $matc
|
||||||
'/account/orders' => $defaults['is_user'] ? account::orders($defaults) : header('Location: /account/login'),
|
'/account/orders' => $defaults['is_user'] ? account::orders($defaults) : header('Location: /account/login'),
|
||||||
'/account/shipping' => $defaults['is_user'] ? account::shipping($defaults) : header('Location: /account/login'),
|
'/account/shipping' => $defaults['is_user'] ? account::shipping($defaults) : header('Location: /account/login'),
|
||||||
'/account/address/edit' => $defaults['is_user'] ? account::address_edit($defaults) : header('Location: /account/login'),
|
'/account/address/edit' => $defaults['is_user'] ? account::address_edit($defaults) : header('Location: /account/login'),
|
||||||
'/account/address/confirm' => $defaults['is_user'] ? account::address_confirm($defaults) : header('Location: /account/login'),
|
'/account/address/set-default-shipping' => $defaults['is_user'] ? account::set_default_shipping($defaults) : header('Location: /account/login'),
|
||||||
|
'/account/address/set-default-billing' => $defaults['is_user'] ? account::set_default_billing($defaults) : header('Location: /account/login'),
|
||||||
'/admin' => $defaults['is_admin'] ? admin::index($defaults) : lost::index($defaults),
|
'/admin' => $defaults['is_admin'] ? admin::index($defaults) : lost::index($defaults),
|
||||||
'/admin/users' => $defaults['is_admin'] ? admin::users($defaults) : lost::index($defaults),
|
'/admin/users' => $defaults['is_admin'] ? admin::users($defaults) : lost::index($defaults),
|
||||||
'/admin/orders' => $defaults['is_admin'] ? admin::orders($defaults) : lost::index($defaults),
|
'/admin/orders' => $defaults['is_admin'] ? admin::orders($defaults) : lost::index($defaults),
|
||||||
|
|
|
@ -12,14 +12,12 @@ class account
|
||||||
{
|
{
|
||||||
$user = users::getById($_SESSION['user_id']);
|
$user = users::getById($_SESSION['user_id']);
|
||||||
$addresses = addresses::getByUserId($_SESSION['user_id']);
|
$addresses = addresses::getByUserId($_SESSION['user_id']);
|
||||||
$user_settings = user_settings::getByUserId($_SESSION['user_id']);
|
|
||||||
|
|
||||||
echo $GLOBALS['twig']->render('lib/pages/index.twig', array_merge($defaults, [
|
echo $GLOBALS['twig']->render('lib/pages/index.twig', array_merge($defaults, [
|
||||||
'child_template' => 'account/index.twig',
|
'child_template' => 'account/index.twig',
|
||||||
'page_title' => 'Manage Account - ' . $_ENV['APP_NAME'],
|
'page_title' => 'Manage Account - ' . $_ENV['APP_NAME'],
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
'addresses' => $addresses,
|
'addresses' => $addresses,
|
||||||
'user_settings' => $user_settings,
|
|
||||||
'breadcrumbs' => [
|
'breadcrumbs' => [
|
||||||
[
|
[
|
||||||
'url' => null,
|
'url' => null,
|
||||||
|
@ -46,7 +44,6 @@ class account
|
||||||
$bill['state'],
|
$bill['state'],
|
||||||
$bill['zip'],
|
$bill['zip'],
|
||||||
$bill['phone'],
|
$bill['phone'],
|
||||||
$bill['hash']
|
|
||||||
);
|
);
|
||||||
$_SESSION['success'] = "Billing address saved!";
|
$_SESSION['success'] = "Billing address saved!";
|
||||||
header('Location: /account/billing');
|
header('Location: /account/billing');
|
||||||
|
@ -75,6 +72,8 @@ class account
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
users::updateProfileById($_SESSION['user_id'], $_POST);
|
users::updateProfileById($_SESSION['user_id'], $_POST);
|
||||||
|
$dark_theme = $_POST['dark_theme'] ?? false;
|
||||||
|
user_settings::update($_SESSION['user_id'], ['dark_theme' => $dark_theme]);
|
||||||
header('Location: /account');
|
header('Location: /account');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,42 +139,6 @@ class account
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function address_edit($defaults)
|
|
||||||
{
|
|
||||||
echo $GLOBALS['twig']->render('lib/pages/index.twig', array_merge($defaults, [
|
|
||||||
'child_template' => 'account/address/edit.twig',
|
|
||||||
'page_title' => 'Edit Address - ' . $_ENV['APP_NAME'],
|
|
||||||
'breadcrumbs' => [
|
|
||||||
[
|
|
||||||
'url' => '/account',
|
|
||||||
'title' => 'My Account',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'url' => null,
|
|
||||||
'title' => 'Edit Address',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function address_confirm($defaults)
|
|
||||||
{
|
|
||||||
echo $GLOBALS['twig']->render('lib/pages/index.twig', array_merge($defaults, [
|
|
||||||
'child_template' => 'account/address/confirm.twig',
|
|
||||||
'page_title' => 'Confirm Address - ' . $_ENV['APP_NAME'],
|
|
||||||
'breadcrumbs' => [
|
|
||||||
[
|
|
||||||
'url' => '/account',
|
|
||||||
'title' => 'My Account',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'url' => null,
|
|
||||||
'title' => 'Confirm Address',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function login($defaults)
|
public static function login($defaults)
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
@ -264,7 +227,6 @@ class account
|
||||||
$ship['state'],
|
$ship['state'],
|
||||||
$ship['zip'],
|
$ship['zip'],
|
||||||
$ship['phone'],
|
$ship['phone'],
|
||||||
$ship['hash']
|
|
||||||
);
|
);
|
||||||
$_SESSION['success'] = "Shipping address saved!";
|
$_SESSION['success'] = "Shipping address saved!";
|
||||||
header('Location: /account/shipping');
|
header('Location: /account/shipping');
|
||||||
|
@ -289,6 +251,33 @@ class account
|
||||||
],
|
],
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
public static function set_default_shipping($defaults)
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
$address_id = $_POST['address_id'] ?? null;
|
||||||
|
if ($address_id) {
|
||||||
|
users::setDefaultShipping($_SESSION['user_id'], $address_id);
|
||||||
|
$_SESSION['success'] = "Default shipping address set successfully!";
|
||||||
|
} else {
|
||||||
|
$_SESSION['error'] = "Failed to set default shipping address.";
|
||||||
|
}
|
||||||
|
header('Location: /account/shipping');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function set_default_billing($defaults)
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
$address_id = $_POST['address_id'] ?? null;
|
||||||
|
if ($address_id) {
|
||||||
|
users::setDefaultBilling($_SESSION['user_id'], $address_id);
|
||||||
|
$_SESSION['success'] = "Default billing address set successfully!";
|
||||||
|
} else {
|
||||||
|
$_SESSION['error'] = "Failed to set default billing address.";
|
||||||
|
}
|
||||||
|
header('Location: /account/billing');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static function signup($defaults)
|
public static function signup($defaults)
|
||||||
{
|
{
|
||||||
|
@ -333,7 +322,6 @@ class account
|
||||||
$ship['state'],
|
$ship['state'],
|
||||||
$ship['zip'],
|
$ship['zip'],
|
||||||
$ship['phone'],
|
$ship['phone'],
|
||||||
$ship['hash']
|
|
||||||
);
|
);
|
||||||
$bill_id = $ship_id;
|
$bill_id = $ship_id;
|
||||||
if (! $useShipping) {
|
if (! $useShipping) {
|
||||||
|
@ -347,7 +335,6 @@ class account
|
||||||
$bill['state'],
|
$bill['state'],
|
||||||
$bill['zip'],
|
$bill['zip'],
|
||||||
$bill['phone'],
|
$bill['phone'],
|
||||||
$bill['hash']
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$opt_in_promotional = $_POST['opt_in_promotional'] ?? false;
|
$opt_in_promotional = $_POST['opt_in_promotional'] ?? false;
|
||||||
|
|
73
src/controllers/address.php
Normal file
73
src/controllers/address.php
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
namespace app\controllers;
|
||||||
|
|
||||||
|
use app\models\addresses;
|
||||||
|
use app\models\users;
|
||||||
|
|
||||||
|
class address
|
||||||
|
{
|
||||||
|
public static function edit($defaults, $address_id)
|
||||||
|
{
|
||||||
|
$address = addresses::getById($address_id);
|
||||||
|
if ($_SESSION['user_id'] != $address['user_id']) {
|
||||||
|
http_response_code(403);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
$address = addresses::validatePost();
|
||||||
|
if (! isset($address['error'])) {
|
||||||
|
addresses::updateById(
|
||||||
|
$address_id,
|
||||||
|
$address['name'],
|
||||||
|
$address['company'],
|
||||||
|
$address['addressLine1'],
|
||||||
|
$address['addressLine2'],
|
||||||
|
$address['city'],
|
||||||
|
$address['state'],
|
||||||
|
$address['zip'],
|
||||||
|
$address['phone']
|
||||||
|
);
|
||||||
|
$_SESSION['success'] = "Address was updated successfully";
|
||||||
|
}
|
||||||
|
header('Location: /address/edit/' . $address_id);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $GLOBALS['twig']->render('lib/pages/index.twig', array_merge($defaults, [
|
||||||
|
'child_template' => 'address/edit.twig',
|
||||||
|
'page_title' => 'Edit Address - ' . $_ENV['APP_NAME'],
|
||||||
|
'address' => $address,
|
||||||
|
'breadcrumbs' => [
|
||||||
|
[
|
||||||
|
'url' => '/account',
|
||||||
|
'title' => 'My Account',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => null,
|
||||||
|
'title' => 'Edit Address',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function delete($defaults, $address_id)
|
||||||
|
{
|
||||||
|
$address = addresses::getById($address_id);
|
||||||
|
if ($_SESSION['user_id'] != $address['user_id']) {
|
||||||
|
http_response_code(403);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
$user = users::getById($address['user_id']);
|
||||||
|
if ($address_id == $user['shipping_address_id'] || $address_id == $user['billing_address_id']) {
|
||||||
|
$_SESSION['error'] = "Cannot delete default address.";
|
||||||
|
header('Location: ' . $_GET['redirect']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
addresses::deleteById($address_id);
|
||||||
|
$_SESSION['success'] = "Address successfully deleted!";
|
||||||
|
header('Location: ' . $_GET['redirect']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,6 @@ class addresses
|
||||||
state TEXT NOT NULL,
|
state TEXT NOT NULL,
|
||||||
zip TEXT NOT NULL,
|
zip TEXT NOT NULL,
|
||||||
phone TEXT,
|
phone TEXT,
|
||||||
hash TEXT NOT NULL,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
@ -103,12 +102,6 @@ class addresses
|
||||||
$_SESSION['error'] = $error_message;
|
$_SESSION['error'] = $error_message;
|
||||||
return ["error" => $error_message];
|
return ["error" => $error_message];
|
||||||
}
|
}
|
||||||
$result['hash'] = hash("sha256", json_encode($result));
|
|
||||||
$existing = self::getByHash($result['hash']);
|
|
||||||
if ($existing) {
|
|
||||||
$_SESSION['error'] = "The address already exists.";
|
|
||||||
return ["error" => $_SESSION['error']];
|
|
||||||
}
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,15 +114,6 @@ class addresses
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getByHash($hash)
|
|
||||||
{
|
|
||||||
$query = "SELECT * FROM addresses WHERE hash = :hash";
|
|
||||||
$stmt = app::$db->prepare($query);
|
|
||||||
$stmt->bindParam(':hash', $hash);
|
|
||||||
$stmt->execute();
|
|
||||||
return $stmt->fetch(\PDO::FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getByUserId($user_id)
|
public static function getByUserId($user_id)
|
||||||
{
|
{
|
||||||
$query = "SELECT * FROM addresses WHERE user_id = :user_id";
|
$query = "SELECT * FROM addresses WHERE user_id = :user_id";
|
||||||
|
@ -139,7 +123,49 @@ class addresses
|
||||||
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function add($user_id, $name, $company, $addressLine1, $addressLine2, $city, $state, $zip, $phone, $hash)
|
public static function getById($id)
|
||||||
|
{
|
||||||
|
$query = "SELECT * FROM addresses WHERE id = :id";
|
||||||
|
$stmt = app::$db->prepare($query);
|
||||||
|
$stmt->bindParam(':id', $id);
|
||||||
|
$stmt->execute();
|
||||||
|
return $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
public static function updateById($id, $name, $company, $addressLine1, $addressLine2, $city, $state, $zip, $phone)
|
||||||
|
{
|
||||||
|
$query = "UPDATE addresses SET
|
||||||
|
name = :name,
|
||||||
|
company = :company,
|
||||||
|
addressLine1 = :addressLine1,
|
||||||
|
addressLine2 = :addressLine2,
|
||||||
|
city = :city,
|
||||||
|
state = :state,
|
||||||
|
zip = :zip,
|
||||||
|
phone = :phone
|
||||||
|
WHERE id = :id";
|
||||||
|
|
||||||
|
$stmt = app::$db->prepare($query);
|
||||||
|
$stmt->bindParam(':id', $id);
|
||||||
|
$stmt->bindParam(':name', $name);
|
||||||
|
$stmt->bindParam(':company', $company);
|
||||||
|
$stmt->bindParam(':addressLine1', $addressLine1);
|
||||||
|
$stmt->bindParam(':addressLine2', $addressLine2);
|
||||||
|
$stmt->bindParam(':city', $city);
|
||||||
|
$stmt->bindParam(':state', $state);
|
||||||
|
$stmt->bindParam(':zip', $zip);
|
||||||
|
$stmt->bindParam(':phone', $phone);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function deleteById($id)
|
||||||
|
{
|
||||||
|
$query = "DELETE FROM addresses WHERE id = :id";
|
||||||
|
$stmt = app::$db->prepare($query);
|
||||||
|
$stmt->bindParam(':id', $id);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function add($user_id, $name, $company, $addressLine1, $addressLine2, $city, $state, $zip, $phone)
|
||||||
{
|
{
|
||||||
$query = "INSERT INTO addresses (
|
$query = "INSERT INTO addresses (
|
||||||
user_id,
|
user_id,
|
||||||
|
@ -150,8 +176,7 @@ class addresses
|
||||||
city,
|
city,
|
||||||
state,
|
state,
|
||||||
zip,
|
zip,
|
||||||
phone,
|
phone
|
||||||
hash
|
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:user_id,
|
:user_id,
|
||||||
:name,
|
:name,
|
||||||
|
@ -161,8 +186,7 @@ class addresses
|
||||||
:city,
|
:city,
|
||||||
:state,
|
:state,
|
||||||
:zip,
|
:zip,
|
||||||
:phone,
|
:phone
|
||||||
:hash
|
|
||||||
)";
|
)";
|
||||||
$stmt = app::$db->prepare($query);
|
$stmt = app::$db->prepare($query);
|
||||||
$stmt->bindParam(':user_id', $user_id);
|
$stmt->bindParam(':user_id', $user_id);
|
||||||
|
@ -174,7 +198,6 @@ class addresses
|
||||||
$stmt->bindParam(':state', $state);
|
$stmt->bindParam(':state', $state);
|
||||||
$stmt->bindParam(':zip', $zip);
|
$stmt->bindParam(':zip', $zip);
|
||||||
$stmt->bindParam(':phone', $phone);
|
$stmt->bindParam(':phone', $phone);
|
||||||
$stmt->bindParam(':hash', $hash);
|
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
return app::$db->lastInsertId();
|
return app::$db->lastInsertId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,23 @@ class users
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
public static function setDefaultShipping($user_id, $shipping_address_id)
|
||||||
|
{
|
||||||
|
$query = "UPDATE users SET shipping_address_id = :shipping_address_id WHERE id = :user_id";
|
||||||
|
$stmt = app::$db->prepare($query);
|
||||||
|
$stmt->bindParam(':shipping_address_id', $shipping_address_id, \PDO::PARAM_INT);
|
||||||
|
$stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function setDefaultBilling($user_id, $billing_address_id)
|
||||||
|
{
|
||||||
|
$query = "UPDATE users SET billing_address_id = :billing_address_id WHERE id = :user_id";
|
||||||
|
$stmt = app::$db->prepare($query);
|
||||||
|
$stmt->bindParam(':billing_address_id', $billing_address_id, \PDO::PARAM_INT);
|
||||||
|
$stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
public static function updateReplaceEmailTokenById($user_id, $replace_token)
|
public static function updateReplaceEmailTokenById($user_id, $replace_token)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
confirm the address
|
|
|
@ -1 +0,0 @@
|
||||||
edit the address
|
|
|
@ -1,5 +1,5 @@
|
||||||
<section>
|
<section>
|
||||||
|
{% include 'lib/alert.twig' %}
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
|
@ -24,15 +24,16 @@
|
||||||
{% if address.id == user.billing_address_id %}
|
{% if address.id == user.billing_address_id %}
|
||||||
{% include 'lib/address.twig' with {
|
{% include 'lib/address.twig' with {
|
||||||
address: address,
|
address: address,
|
||||||
edit_url: '/account/billing/edit/' ~ address.id,
|
edit: true,
|
||||||
delete_url: '/account/billing/delete/' ~ address.id
|
delete: true,
|
||||||
|
redirect: '/account/billing'
|
||||||
} %}
|
} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<form action="/account/billing" method="post" class="flex flex-col gap-2">
|
<form action="/account/billing" method="post" class="flex flex-col gap-2">
|
||||||
{% include 'lib/forms/address.twig' with {
|
{% include 'lib/forms/address.twig' with {
|
||||||
action: 'billing'
|
type: 'billing_'
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/button.twig' with {
|
||||||
label: 'Add Address',
|
label: 'Add Address',
|
||||||
|
@ -44,11 +45,15 @@
|
||||||
text: 'OR'
|
text: 'OR'
|
||||||
} %}
|
} %}
|
||||||
{% for address in addresses %}
|
{% for address in addresses %}
|
||||||
|
{% if address.id != user.shipping_address_id %}
|
||||||
{% include 'lib/address.twig' with {
|
{% include 'lib/address.twig' with {
|
||||||
address: address,
|
address: address,
|
||||||
edit_url: '/account/billing/edit/' ~ address.id,
|
edit: true,
|
||||||
delete_url: '/account/billing/delete/' ~ address.id
|
delete: true,
|
||||||
|
redirect: '/account/billing',
|
||||||
|
set_default: 'billing'
|
||||||
} %}
|
} %}
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
name: user.name,
|
name: user.name,
|
||||||
company_name: user.company_name,
|
company_name: user.company_name,
|
||||||
company_type: user.company_type,
|
company_type: user.company_type,
|
||||||
company_size: user.company_size
|
company_size: user.company_size,
|
||||||
|
dark_theme: defaults.user_settings.dark_theme
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/button.twig' with {
|
||||||
label: 'Save Profile',
|
label: 'Save Profile',
|
||||||
|
@ -52,8 +53,6 @@
|
||||||
{% if address.id == user.shipping_address_id %}
|
{% if address.id == user.shipping_address_id %}
|
||||||
{% include 'lib/address.twig' with {
|
{% include 'lib/address.twig' with {
|
||||||
address: address,
|
address: address,
|
||||||
edit_url: '/account/shipping/edit/' ~ address.id,
|
|
||||||
delete_url: '/account/shipping/delete/' ~ address.id
|
|
||||||
} %}
|
} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -72,8 +71,6 @@
|
||||||
{% if address.id == user.billing_address_id %}
|
{% if address.id == user.billing_address_id %}
|
||||||
{% include 'lib/address.twig' with {
|
{% include 'lib/address.twig' with {
|
||||||
address: address,
|
address: address,
|
||||||
edit_url: '/account/billing/edit/' ~ address.id,
|
|
||||||
delete_url: '/account/billing/delete/' ~ address.id
|
|
||||||
} %}
|
} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -138,7 +135,7 @@
|
||||||
{% include 'lib/inputs/toggle.twig' with {
|
{% include 'lib/inputs/toggle.twig' with {
|
||||||
label: 'Recieve coupons & more',
|
label: 'Recieve coupons & more',
|
||||||
name: 'opt_in_promotional',
|
name: 'opt_in_promotional',
|
||||||
on: user_settings.opt_in_promotional
|
on: defailts.user_settings.opt_in_promotional
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/button.twig' with {
|
||||||
label: 'Save',
|
label: 'Save',
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<section class="flex flex-col gap-4">
|
<section class="flex flex-col gap-4">
|
||||||
|
{% include 'lib/alert.twig' %}
|
||||||
<div>
|
<div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
|
@ -13,15 +14,16 @@
|
||||||
{% if address.id == user.shipping_address_id %}
|
{% if address.id == user.shipping_address_id %}
|
||||||
{% include 'lib/address.twig' with {
|
{% include 'lib/address.twig' with {
|
||||||
address: address,
|
address: address,
|
||||||
edit_url: '/account/shipping/edit/' ~ address.id,
|
edit: true,
|
||||||
delete_url: '/account/shipping/delete/' ~ address.id
|
delete: true,
|
||||||
|
redirect: '/account/shipping'
|
||||||
} %}
|
} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<form action="/account/shipping" method="post" class="flex flex-col gap-2">
|
<form action="/account/shipping" method="post" class="flex flex-col gap-2">
|
||||||
{% include 'lib/forms/address.twig' with {
|
{% include 'lib/forms/address.twig' with {
|
||||||
action: 'shipping'
|
type: 'shipping_'
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/button.twig' with {
|
||||||
label: 'Add Address',
|
label: 'Add Address',
|
||||||
|
@ -33,12 +35,15 @@
|
||||||
text: 'OR'
|
text: 'OR'
|
||||||
} %}
|
} %}
|
||||||
{% for address in addresses %}
|
{% for address in addresses %}
|
||||||
|
{% if address.id != user.shipping_address_id %}
|
||||||
{% include 'lib/address.twig' with {
|
{% include 'lib/address.twig' with {
|
||||||
address: address,
|
address: address,
|
||||||
edit_url: '/account/billing/edit/' ~ address.id,
|
edit: true,
|
||||||
delete_url: '/account/billing/delete/' ~ address.id
|
delete: true,
|
||||||
|
redirect: '/account/shipping',
|
||||||
|
set_default: 'shipping'
|
||||||
} %}
|
} %}
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% include 'lib/forms/address.twig' with {
|
{% include 'lib/forms/address.twig' with {
|
||||||
action: 'shipping',
|
type: 'shipping_',
|
||||||
name: session.last_post.shipping_name,
|
name: session.last_post.shipping_name,
|
||||||
addressLine1: session.last_post.shipping_addressLine1,
|
addressLine1: session.last_post.shipping_addressLine1,
|
||||||
company: session.last_post.shipping_company,
|
company: session.last_post.shipping_company,
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="billing-address" style="display: none;">
|
<div id="billing-address" style="display: none;">
|
||||||
{% include 'lib/forms/address.twig' with {
|
{% include 'lib/forms/address.twig' with {
|
||||||
action: 'billing',
|
type: 'billing_',
|
||||||
name: session.last_post.billing_name,
|
name: session.last_post.billing_name,
|
||||||
addressLine1: session.last_post.billing_addressLine1,
|
addressLine1: session.last_post.billing_addressLine1,
|
||||||
company: session.last_post.billing_company,
|
company: session.last_post.billing_company,
|
||||||
|
|
19
src/views/address/edit.twig
Normal file
19
src/views/address/edit.twig
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{% include 'lib/alert.twig' %}
|
||||||
|
|
||||||
|
<form action="/address/edit/{{ address.id }}" method="post" class="flex flex-col gap-2">
|
||||||
|
{% include 'lib/forms/address.twig' with {
|
||||||
|
type: '',
|
||||||
|
name: address.name,
|
||||||
|
addressLine1: address.addressLine1,
|
||||||
|
company: address.company,
|
||||||
|
addressLine2: address.addressLine2,
|
||||||
|
city: address.city,
|
||||||
|
state: address.state,
|
||||||
|
zip: address.zip,
|
||||||
|
phone: address.phone,
|
||||||
|
} %}
|
||||||
|
{% include 'lib/button.twig' with {
|
||||||
|
label: 'Save Address',
|
||||||
|
onclick: 'this.parentNode.submit()'
|
||||||
|
} %}
|
||||||
|
</form>
|
|
@ -20,23 +20,33 @@
|
||||||
<span>
|
<span>
|
||||||
{{ address.phone }}
|
{{ address.phone }}
|
||||||
</span>
|
</span>
|
||||||
{% if edit_url is not null %}
|
{% if edit %}
|
||||||
<a href="{{ edit_url }}" onclick="event.preventDefault(); document.getElementById('edit-form-{{ address.id }}').submit();">
|
<a href="/address/edit/{{ address.id }}">
|
||||||
Edit
|
Edit
|
||||||
</a>
|
</a>
|
||||||
<form id="edit-form-{{ address.id }}" action="{{ edit_url }}" method="post" style="display: none;">
|
<form id="edit-form-{{ address.id }}" action="{{ edit_url }}" method="post" style="display: none;">
|
||||||
<input type="hidden" name="address_id" value="{{ address.id }}" />
|
<input type="hidden" name="address_id" value="{{ address.id }}" />
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if delete_url is not null %}
|
{% if delete %}
|
||||||
<a href="#delete-modal-{{ address.id }}">
|
<a href="#delete-modal-{{ address.id }}">
|
||||||
Delete
|
Delete
|
||||||
</a>
|
</a>
|
||||||
{% include 'lib/modal.twig' with {
|
{% include 'lib/modal.twig' with {
|
||||||
id: 'delete-modal-' ~ address.id,
|
id: 'delete-modal-' ~ address.id,
|
||||||
content: 'lib/modals/confirm_delete_address.twig',
|
content: 'lib/modals/confirm_delete_address.twig',
|
||||||
|
okText: 'Yes, delete',
|
||||||
|
okURL: '/address/delete/' ~ address.id ~ '?redirect=' ~ redirect
|
||||||
} %}
|
} %}
|
||||||
<form id="delete-form-{{ address.id }}" action="{{ delete_url }}" method="post" style="display: none;" />
|
<form id="delete-form-{{ address.id }}" action="{{ delete_url }}" method="post" style="display: none;" />
|
||||||
<input type="hidden" name="address_id" value="{{ address.id }}"></form>
|
<input type="hidden" name="address_id" value="{{ address.id }}"></form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if set_default %}
|
||||||
|
<form id="set-default-form-{{ address.id }}" action="/account/address/set-default-{{ set_default }}" method="post">
|
||||||
|
<input type="hidden" name="address_id" value="{{ address.id }}" />
|
||||||
|
<button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
|
||||||
|
Set Default
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
<div class="flex flex-col gap-4 mb-4">
|
<div class="flex flex-col gap-4 mb-4">
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_name',
|
name: type ~ 'name',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
value: name
|
value: name
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_company',
|
name: type ~ 'company',
|
||||||
label: 'Company',
|
label: 'Company',
|
||||||
optional: true,
|
optional: true,
|
||||||
value: company
|
value: company
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_addressLine1',
|
name: type ~ 'addressLine1',
|
||||||
label: 'Address Line 1',
|
label: 'Address Line 1',
|
||||||
value: addressLine1
|
value: addressLine1
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_addressLine2',
|
name: type ~ 'addressLine2',
|
||||||
label: 'Address Line 2',
|
label: 'Address Line 2',
|
||||||
optional: true,
|
optional: true,
|
||||||
value: addressLine2
|
value: addressLine2
|
||||||
|
@ -28,26 +28,26 @@
|
||||||
<div class="flex gap-4">
|
<div class="flex gap-4">
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_city',
|
name: type ~ 'city',
|
||||||
label: 'City',
|
label: 'City',
|
||||||
value: city
|
value: city
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_state',
|
name: type ~ 'state',
|
||||||
label: 'State',
|
label: 'State',
|
||||||
value: state
|
value: state
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_zip',
|
name: type ~ 'zip',
|
||||||
label: 'Zip',
|
label: 'Zip',
|
||||||
value: zip
|
value: zip
|
||||||
} %}
|
} %}
|
||||||
</div>
|
</div>
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: action ~ '_phone',
|
name: type ~ 'phone',
|
||||||
label: 'Phone',
|
label: 'Phone',
|
||||||
value: phone
|
value: phone
|
||||||
} %}
|
} %}
|
||||||
|
|
|
@ -3,31 +3,31 @@
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
value: user.name
|
value: name
|
||||||
} %}
|
} %}
|
||||||
<div class="flex gap-4">
|
<div class="flex gap-4">
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'company_name',
|
name: 'company_name',
|
||||||
label: 'Company Name',
|
label: 'Company Name',
|
||||||
value: user.company_name
|
value: company_name
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'company_type',
|
name: 'company_type',
|
||||||
label: 'Company Type',
|
label: 'Company Type',
|
||||||
value: user.company_type
|
value: company_type
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'company_size',
|
name: 'company_size',
|
||||||
label: 'Company Size',
|
label: 'Company Size',
|
||||||
value: user.company_size
|
value: company_size
|
||||||
} %}
|
} %}
|
||||||
</div>
|
</div>
|
||||||
{% include 'lib/inputs/toggle.twig' with {
|
{% include 'lib/inputs/toggle.twig' with {
|
||||||
name: 'dark_theme',
|
name: 'dark_theme',
|
||||||
label: 'Use dark theme',
|
label: 'Use dark theme',
|
||||||
on: user_settings.dark_theme
|
on: dark_theme
|
||||||
} %}
|
} %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,6 +8,20 @@
|
||||||
<div id="hide-{{ id }}">
|
<div id="hide-{{ id }}">
|
||||||
<div class="{{ colors.modal.content }} p-8 border rounded relative">
|
<div class="{{ colors.modal.content }} p-8 border rounded relative">
|
||||||
{% include content %}
|
{% include content %}
|
||||||
|
{% if okURL is defined %}
|
||||||
|
<div class="flex justify-end mt-4">
|
||||||
|
<a href="#hide-{{ id }}" class="mr-4 no-underline">
|
||||||
|
<button class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
<form action="{{ okURL }}" method="post" class="inline">
|
||||||
|
<button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded no-underline">
|
||||||
|
{{ okText is defined ? okText : 'OK' }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<a href="#hide-{{ id }}" class="absolute top-2 right-2 no-underline">
|
<a href="#hide-{{ id }}" class="absolute top-2 right-2 no-underline">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x">
|
||||||
<path d="M18 6 6 18" />
|
<path d="M18 6 6 18" />
|
||||||
|
|
Loading…
Reference in a new issue