save
This commit is contained in:
parent
a2d5494f15
commit
35971fd696
|
@ -106,6 +106,7 @@ if (preg_match('/^\/(address(?:\/edit|\/delete)?|transaction|user|order|quote|pr
|
||||||
'/account/billing' => $defaults['is_user'] ? account::billing($defaults) : header('Location: /account/login'),
|
'/account/billing' => $defaults['is_user'] ? account::billing($defaults) : header('Location: /account/login'),
|
||||||
'/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/notifications' => $defaults['is_user'] ? account::notifications($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/set-default-shipping' => $defaults['is_user'] ? account::set_default_shipping($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'),
|
'/account/address/set-default-billing' => $defaults['is_user'] ? account::set_default_billing($defaults) : header('Location: /account/login'),
|
||||||
|
|
178
src/colors.php
178
src/colors.php
|
@ -1,58 +1,174 @@
|
||||||
<?php
|
<?php
|
||||||
return [
|
$colors = [
|
||||||
'header' => [
|
'header' => [
|
||||||
'banner' => 'bg-gray-100 dark:bg-gray-600 text-gray-200 dark:text-gray-200',
|
'banner' => [
|
||||||
|
'light' => 'bg-gray-100 text-gray-200',
|
||||||
|
'dark' => 'bg-gray-600 text-gray-200',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'anchor' => [
|
'anchor' => [
|
||||||
'primary' => 'text-blue-400 dark:text-blue-200',
|
'primary' => [
|
||||||
|
'light' => 'text-blue-400',
|
||||||
|
'dark' => 'text-blue-200',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'body' => [
|
||||||
|
'light' => 'bg-white text-gray-600',
|
||||||
|
'dark' => 'bg-gray-800 text-gray-300',
|
||||||
],
|
],
|
||||||
'body' => 'bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-300',
|
|
||||||
'button' => [
|
'button' => [
|
||||||
'primary' => 'border-blue-400 dark:border-blue-600 dark:hover:border-blue-800 bg-blue-400 dark:bg-blue-600 hover:bg-blue-600 hover:dark:bg-blue-800 text-white dark:text-white',
|
'primary' => [
|
||||||
'default' => 'hover:bg-gray-50 dark:hover:bg-gray-900',
|
'light' => 'border-blue-400 bg-blue-400 hover:bg-blue-600 text-white',
|
||||||
|
'dark' => 'border-blue-600 hover:border-blue-800 bg-blue-600 hover:bg-blue-800 text-white',
|
||||||
],
|
],
|
||||||
'breadcrumb' => [
|
'default' => [
|
||||||
'parent' => 'text-gray-300 dark:text-gray-400 hover:text-gray-400 dark:hover:text-gray-500',
|
'light' => 'bg-gray-200 hover:bg-gray-300 text-gray-800',
|
||||||
'seperator' => 'text-gray-200 dark:text-gray-200',
|
'dark' => 'bg-gray-200 hover:bg-gray-300 text-gray-800',
|
||||||
'child' => 'text-gray-200 dark:text-gray-300',
|
],
|
||||||
|
'danger' => [
|
||||||
|
'light' => 'border-red-400 bg-red-400 hover:bg-red-600 text-white',
|
||||||
|
'dark' => 'border-red-600 hover:border-red-800 bg-red-600 hover:bg-red-800 text-white',
|
||||||
],
|
],
|
||||||
'dropdown' => [
|
'dropdown' => [
|
||||||
'list' => 'bg-white dark:bg-blue-900 border-gray-600 dark:border-gray-300',
|
'light' => 'hover:bg-gray-50',
|
||||||
'item' => 'hover:bg-gray-200 dark:hover:bg-gray-900',
|
'dark' => 'hover:bg-gray-900',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'breadcrumb' => [
|
||||||
|
'parent' => [
|
||||||
|
'light' => 'text-gray-300 hover:text-gray-400',
|
||||||
|
'dark' => 'text-gray-400 hover:text-gray-500',
|
||||||
|
],
|
||||||
|
'seperator' => [
|
||||||
|
'light' => 'text-gray-200',
|
||||||
|
'dark' => 'text-gray-200',
|
||||||
|
],
|
||||||
|
'child' => [
|
||||||
|
'light' => 'text-gray-200',
|
||||||
|
'dark' => 'text-gray-300',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'dropdown' => [
|
||||||
|
'list' => [
|
||||||
|
'light' => 'bg-white border-gray-600',
|
||||||
|
'dark' => 'bg-blue-900 border-gray-300',
|
||||||
|
],
|
||||||
|
'item' => [
|
||||||
|
'light' => 'hover:bg-gray-200',
|
||||||
|
'dark' => 'hover:bg-gray-900',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'input' => [
|
||||||
|
'light' => 'text-gray-800 bg-white border-gray-300 focus:ring-blue-500',
|
||||||
|
'dark' => 'text-gray-300 bg-gray-800 border-gray-500 focus:ring-blue-500',
|
||||||
],
|
],
|
||||||
'input' => 'text-gray-800 dark:text-gray-300 bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-500 focus:ring-blue-500',
|
|
||||||
'error' => [
|
'error' => [
|
||||||
'text' => 'text-red-600',
|
'text' => [
|
||||||
'alert' => 'bg-red-100 text-gray-800 border-red-600',
|
'light' => 'text-red-600',
|
||||||
|
'dark' => 'text-red-600',
|
||||||
|
],
|
||||||
|
'alert' => [
|
||||||
|
'light' => 'bg-red-100 text-gray-800 border-red-600',
|
||||||
|
'dark' => 'bg-red-100 text-gray-800 border-red-600',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'warning' => [
|
'warning' => [
|
||||||
'text' => 'text-yellow-400',
|
'text' => [
|
||||||
'alert' => 'bg-yellow-100 text-gray-800 border-yellow-400',
|
'light' => 'text-yellow-400',
|
||||||
|
'dark' => 'text-yellow-400',
|
||||||
|
],
|
||||||
|
'alert' => [
|
||||||
|
'light' => 'bg-yellow-100 text-gray-800 border-yellow-400',
|
||||||
|
'dark' => 'bg-yellow-100 text-gray-800 border-yellow-400',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'success' => [
|
'success' => [
|
||||||
'text' => 'text-green-600',
|
'text' => [
|
||||||
'alert' => 'bg-green-100 text-gray-800 border-green-600',
|
'light' => 'text-green-600',
|
||||||
|
'dark' => 'text-green-600',
|
||||||
|
],
|
||||||
|
'alert' => [
|
||||||
|
'light' => 'bg-green-100 text-gray-800 border-green-600',
|
||||||
|
'dark' => 'bg-green-100 text-gray-800 border-green-600',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'info' => [
|
'info' => [
|
||||||
'text' => 'text-blue-400',
|
'text' => [
|
||||||
'alert' => 'bg-blue-200 text-gray-800 border-blue-400',
|
'light' => 'text-blue-400',
|
||||||
|
'dark' => 'text-blue-400',
|
||||||
|
],
|
||||||
|
'alert' => [
|
||||||
|
'light' => 'bg-blue-200 text-gray-800 border-blue-400',
|
||||||
|
'dark' => 'bg-blue-200 text-gray-800 border-blue-400',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'modal' => [
|
'modal' => [
|
||||||
'content' => 'bg-white dark:bg-blue-900 border-gray-600 dark:border-gray-300',
|
'content' => [
|
||||||
'shadow' => 'bg-black/70',
|
'light' => 'bg-white border-gray-600',
|
||||||
|
'dark' => 'bg-blue-900 border-gray-300',
|
||||||
|
],
|
||||||
|
'shadow' => [
|
||||||
|
'light' => 'bg-black/70',
|
||||||
|
'dark' => 'bg-black/70',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'nav' => [
|
'nav' => [
|
||||||
'bar' => 'bg-blue-400 dark:bg-blue-600 text-gray-200 dark:text-gray-200',
|
'bar' => [
|
||||||
'item' => 'hover:bg-blue-600 dark:hover:bg-blue-800 hover:text-gray-200 dark:hover:text-gray-300 text-white border-blue-400 dark:border-blue-600',
|
'light' => 'bg-blue-400 text-gray-200',
|
||||||
'hovercontent' => 'bg-white dark:bg-slate-700 text-gray-800 dark:text-gray-300',
|
'dark' => 'bg-blue-600 text-gray-200',
|
||||||
|
],
|
||||||
|
'item' => [
|
||||||
|
'light' => 'hover:bg-blue-600 hover:text-gray-200 text-white border-blue-400',
|
||||||
|
'dark' => 'hover:bg-blue-800 hover:text-gray-300 text-white border-blue-600',
|
||||||
|
],
|
||||||
|
'hovercontent' => [
|
||||||
|
'light' => 'bg-white text-gray-800',
|
||||||
|
'dark' => 'bg-slate-700 text-gray-300',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'rule' => [
|
||||||
|
'light' => 'border-gray-400',
|
||||||
|
'dark' => 'border-gray-400',
|
||||||
],
|
],
|
||||||
'rule' => 'border-gray-400 dark:border-gray-400',
|
|
||||||
'text' => [
|
'text' => [
|
||||||
'muted' => 'text-gray-400 dark:text-gray-300',
|
'muted' => [
|
||||||
|
'light' => 'text-gray-400',
|
||||||
|
'dark' => 'text-gray-300',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'toggle' => [
|
||||||
|
'light' => "bg-gray-300 peer-checked:bg-green-400 after:bg-white",
|
||||||
|
'dark' => "bg-gray-300 peer-checked:bg-green-400 after:bg-white",
|
||||||
],
|
],
|
||||||
'toggle' => "bg-gray-300 peer-checked:bg-green-400 after:bg-white",
|
|
||||||
'footer' => [
|
'footer' => [
|
||||||
"primary" => "bg-gray-200 dark:bg-slate-600 text-gray-500 dark:text-gray-300",
|
'primary' => [
|
||||||
"policy" => "bg-slate-400 dark:bg-slate-800 text-gray-200 dark:text-gray-400",
|
'light' => "bg-gray-200 text-gray-500",
|
||||||
|
'dark' => "bg-slate-600 text-gray-300",
|
||||||
|
],
|
||||||
|
'policy' => [
|
||||||
|
'light' => "bg-slate-400 text-gray-200",
|
||||||
|
'dark' => "bg-slate-800 text-gray-400",
|
||||||
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
function lightDarkify($colors, $level = 0)
|
||||||
|
{
|
||||||
|
$result = ['light' => [], 'dark' => []];
|
||||||
|
if ($level >= 3) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
foreach ($colors as $key => $value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$subResult = lightDarkify($value, $level + 1);
|
||||||
|
foreach ($subResult as $theme => $subValue) {
|
||||||
|
if (isset($result[$theme])) {
|
||||||
|
$result[$theme][$key] = $subValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($key == 'light' || $key == 'dark') {
|
||||||
|
$result[$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
return lightDarkify($colors)[$theme];
|
||||||
|
|
|
@ -3,6 +3,7 @@ namespace app\controllers;
|
||||||
|
|
||||||
use app\models\addresses;
|
use app\models\addresses;
|
||||||
use app\models\magic_links;
|
use app\models\magic_links;
|
||||||
|
use app\models\transactions;
|
||||||
use app\models\users;
|
use app\models\users;
|
||||||
use app\models\user_settings;
|
use app\models\user_settings;
|
||||||
|
|
||||||
|
@ -10,14 +11,12 @@ class account
|
||||||
{
|
{
|
||||||
public static function index($defaults): void
|
public static function index($defaults): void
|
||||||
{
|
{
|
||||||
$user = users::getById($_SESSION['user_id']);
|
|
||||||
$addresses = addresses::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' => users::getById($_SESSION['user_id']),
|
||||||
'addresses' => $addresses,
|
'addresses' => addresses::getByUserId($_SESSION['user_id']),
|
||||||
|
'balance' => transactions::getUserBalance($_SESSION['user_id']),
|
||||||
'breadcrumbs' => [
|
'breadcrumbs' => [
|
||||||
[
|
[
|
||||||
'url' => null,
|
'url' => null,
|
||||||
|
@ -33,6 +32,7 @@ class account
|
||||||
$bill = addresses::validatePost("billing_");
|
$bill = addresses::validatePost("billing_");
|
||||||
if (isset($bill['error'])) {
|
if (isset($bill['error'])) {
|
||||||
header('Location: /account/billing');
|
header('Location: /account/billing');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
$bill_id = addresses::add(
|
$bill_id = addresses::add(
|
||||||
$_SESSION['user_id'],
|
$_SESSION['user_id'],
|
||||||
|
@ -47,15 +47,13 @@ class account
|
||||||
);
|
);
|
||||||
$_SESSION['success'] = "Billing address saved!";
|
$_SESSION['success'] = "Billing address saved!";
|
||||||
header('Location: /account/billing');
|
header('Location: /account/billing');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
$user = users::getById($_SESSION['user_id']);
|
|
||||||
$addresses = addresses::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/billing.twig',
|
'child_template' => 'account/billing.twig',
|
||||||
'page_title' => 'Billing Information - ' . $_ENV['APP_NAME'],
|
'page_title' => 'Billing Information - ' . $_ENV['APP_NAME'],
|
||||||
'user' => $user,
|
'user' => users::getById($_SESSION['user_id']),
|
||||||
'addresses' => $addresses,
|
'addresses' => addresses::getByUserId($_SESSION['user_id']),
|
||||||
'breadcrumbs' => [
|
'breadcrumbs' => [
|
||||||
[
|
[
|
||||||
'url' => '/account',
|
'url' => '/account',
|
||||||
|
@ -74,7 +72,9 @@ class account
|
||||||
users::updateProfileById($_SESSION['user_id'], $_POST);
|
users::updateProfileById($_SESSION['user_id'], $_POST);
|
||||||
$dark_theme = $_POST['dark_theme'] ?? false;
|
$dark_theme = $_POST['dark_theme'] ?? false;
|
||||||
user_settings::update($_SESSION['user_id'], ['dark_theme' => $dark_theme]);
|
user_settings::update($_SESSION['user_id'], ['dark_theme' => $dark_theme]);
|
||||||
|
$_SESSION['success'] = 'Profile information updated sucessfully!';
|
||||||
header('Location: /account');
|
header('Location: /account');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,6 @@ class account
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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/verify.twig',
|
'child_template' => 'account/verify.twig',
|
||||||
'page_title' => $_ENV['APP_NAME'],
|
'page_title' => $_ENV['APP_NAME'],
|
||||||
|
@ -155,6 +154,7 @@ class account
|
||||||
}
|
}
|
||||||
if (isset($_SESSION['user_id'])) {
|
if (isset($_SESSION['user_id'])) {
|
||||||
header('Location: /account');
|
header('Location: /account');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
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/login.twig',
|
'child_template' => 'account/login.twig',
|
||||||
|
@ -168,6 +168,19 @@ class account
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function notifications($defaults)
|
||||||
|
{
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
$opt_in_promotional = isset($_POST['opt_in_promotional']) ? (bool) $_POST['opt_in_promotional'] : false;
|
||||||
|
$opt_in_subscription = isset($_POST['opt_in_subscription']) ? (bool) $_POST['opt_in_subscription'] : false;
|
||||||
|
$opt_in_order = isset($_POST['opt_in_order']) ? (bool) $_POST['opt_in_order'] : false;
|
||||||
|
users::updateOptIn($_SESSION['user_id'], $opt_in_promotional, $opt_in_subscription, $opt_in_order);
|
||||||
|
$_SESSION['success'] = "Notification preferences updated successfully.";
|
||||||
|
header('Location: /account');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static function logout()
|
public static function logout()
|
||||||
{
|
{
|
||||||
session_unset();
|
session_unset();
|
||||||
|
@ -216,6 +229,7 @@ class account
|
||||||
$ship = addresses::validatePost("shipping_");
|
$ship = addresses::validatePost("shipping_");
|
||||||
if (isset($ship['error'])) {
|
if (isset($ship['error'])) {
|
||||||
header('Location: /account/shipping');
|
header('Location: /account/shipping');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
$ship_id = addresses::add(
|
$ship_id = addresses::add(
|
||||||
$_SESSION['user_id'],
|
$_SESSION['user_id'],
|
||||||
|
@ -230,15 +244,14 @@ class account
|
||||||
);
|
);
|
||||||
$_SESSION['success'] = "Shipping address saved!";
|
$_SESSION['success'] = "Shipping address saved!";
|
||||||
header('Location: /account/shipping');
|
header('Location: /account/shipping');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
$user = users::getById($_SESSION['user_id']);
|
|
||||||
$addresses = addresses::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/shipping.twig',
|
'child_template' => 'account/shipping.twig',
|
||||||
'page_title' => $_ENV['APP_NAME'] . ' Shipping',
|
'page_title' => $_ENV['APP_NAME'] . ' Shipping',
|
||||||
'user' => $user,
|
'user' => users::getById($_SESSION['user_id']),
|
||||||
'addresses' => $addresses,
|
'addresses' => addresses::getByUserId($_SESSION['user_id']),
|
||||||
'breadcrumbs' => [
|
'breadcrumbs' => [
|
||||||
[
|
[
|
||||||
'url' => '/account',
|
'url' => '/account',
|
||||||
|
@ -262,6 +275,7 @@ class account
|
||||||
$_SESSION['error'] = "Failed to set default shipping address.";
|
$_SESSION['error'] = "Failed to set default shipping address.";
|
||||||
}
|
}
|
||||||
header('Location: /account/shipping');
|
header('Location: /account/shipping');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +290,7 @@ class account
|
||||||
$_SESSION['error'] = "Failed to set default billing address.";
|
$_SESSION['error'] = "Failed to set default billing address.";
|
||||||
}
|
}
|
||||||
header('Location: /account/billing');
|
header('Location: /account/billing');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,6 +314,7 @@ class account
|
||||||
$_SESSION['error'] = "Shipping address verification failed. " . $_SESSION['error'];
|
$_SESSION['error'] = "Shipping address verification failed. " . $_SESSION['error'];
|
||||||
$_SESSION['last_post'] = $_POST;
|
$_SESSION['last_post'] = $_POST;
|
||||||
header('Location: /account/signup');
|
header('Location: /account/signup');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
if (! $useShipping) {
|
if (! $useShipping) {
|
||||||
$bill = addresses::validatePost("billing_");
|
$bill = addresses::validatePost("billing_");
|
||||||
|
@ -306,11 +322,13 @@ class account
|
||||||
$_SESSION['error'] = "Billing address verification failed. " . $_SESSION['error'];
|
$_SESSION['error'] = "Billing address verification failed. " . $_SESSION['error'];
|
||||||
$_SESSION['last_post'] = $_POST;
|
$_SESSION['last_post'] = $_POST;
|
||||||
header('Location: /account/signup');
|
header('Location: /account/signup');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($_SESSION['error'])) {
|
if (isset($_SESSION['error'])) {
|
||||||
$_SESSION['last_post'] = $_POST;
|
$_SESSION['last_post'] = $_POST;
|
||||||
header('Location: /account/signup');
|
header('Location: /account/signup');
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
$ship_id = addresses::add(
|
$ship_id = addresses::add(
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -13,12 +13,11 @@ class transaction
|
||||||
if (! $tx) {
|
if (! $tx) {
|
||||||
lost::index($defaults);
|
lost::index($defaults);
|
||||||
}
|
}
|
||||||
$user = users::getById($tx['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' => 'transaction.twig',
|
'child_template' => 'transaction.twig',
|
||||||
'page_title' => 'Transaction Reciept #' . $txid,
|
'page_title' => 'Transaction Reciept #' . $txid,
|
||||||
'tx' => $tx,
|
'tx' => $tx,
|
||||||
'user' => $user,
|
'user' => users::getById($tx['user_id']),
|
||||||
'breadcrumbs' => [
|
'breadcrumbs' => [
|
||||||
[
|
[
|
||||||
'url' => "/transaction/" . $txid,
|
'url' => "/transaction/" . $txid,
|
||||||
|
|
|
@ -54,7 +54,7 @@ class transactions
|
||||||
|
|
||||||
public static function getUserBalance($user_id)
|
public static function getUserBalance($user_id)
|
||||||
{
|
{
|
||||||
$query = "SELECT COALESCE(SUM(cents), 0) AS total_cents, COALESCE(SUM(sats), 0) AS total_sats FROM transactions WHERE user_id = :user_id";
|
$query = "SELECT COALESCE(SUM(cents), 0) AS cents, COALESCE(SUM(sats), 0) AS sats FROM transactions WHERE user_id = :user_id";
|
||||||
$stmt = app::$db->prepare($query);
|
$stmt = app::$db->prepare($query);
|
||||||
$stmt->bindParam(':user_id', $user_id);
|
$stmt->bindParam(':user_id', $user_id);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
|
@ -20,8 +20,8 @@ class user_settings
|
||||||
|
|
||||||
public static function add($user_id, $opt_in_promotional, $dark_theme)
|
public static function add($user_id, $opt_in_promotional, $dark_theme)
|
||||||
{
|
{
|
||||||
$query = "INSERT INTO user_settings (user_id, opt_in_promotional, opt_in_subscription, opt_in_order, dark_theme)
|
$query = "INSERT INTO user_settings (user_id, opt_in_promotional, dark_theme)
|
||||||
VALUES (:user_id, :opt_in_promotional, :opt_in_subscription, :opt_in_orders, :dark_theme)";
|
VALUES (:user_id, :opt_in_promotional, :dark_theme)";
|
||||||
$stmt = app::$db->prepare($query);
|
$stmt = app::$db->prepare($query);
|
||||||
$stmt->bindParam(':user_id', $user_id);
|
$stmt->bindParam(':user_id', $user_id);
|
||||||
$stmt->bindParam(':opt_in_promotional', $opt_in_promotional);
|
$stmt->bindParam(':opt_in_promotional', $opt_in_promotional);
|
||||||
|
|
|
@ -21,7 +21,6 @@ class users
|
||||||
verified BOOLEAN NOT NULL,
|
verified BOOLEAN NOT NULL,
|
||||||
nsec TEXT,
|
nsec TEXT,
|
||||||
npub TEXT NOT NULL,
|
npub TEXT NOT NULL,
|
||||||
attached_lightning_address TEXT,
|
|
||||||
replace_email_token TEXT,
|
replace_email_token TEXT,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
company_name TEXT,
|
company_name TEXT,
|
||||||
|
@ -38,6 +37,20 @@ class users
|
||||||
$stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
|
$stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
|
public static function updateOptIn($user_id, $opt_in_promotional, $opt_in_subscription, $opt_in_order)
|
||||||
|
{
|
||||||
|
$query = "UPDATE user_settings SET
|
||||||
|
opt_in_promotional = :opt_in_promotional,
|
||||||
|
opt_in_subscription = :opt_in_subscription,
|
||||||
|
opt_in_order = :opt_in_order
|
||||||
|
WHERE user_id = :user_id";
|
||||||
|
$stmt = app::$db->prepare($query);
|
||||||
|
$stmt->bindParam(':opt_in_promotional', $opt_in_promotional, \PDO::PARAM_BOOL);
|
||||||
|
$stmt->bindParam(':opt_in_subscription', $opt_in_subscription, \PDO::PARAM_BOOL);
|
||||||
|
$stmt->bindParam(':opt_in_order', $opt_in_order, \PDO::PARAM_BOOL);
|
||||||
|
$stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
public static function setDefaultBilling($user_id, $billing_address_id)
|
public static function setDefaultBilling($user_id, $billing_address_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,9 +35,8 @@
|
||||||
{% include 'lib/forms/address.twig' with {
|
{% include 'lib/forms/address.twig' with {
|
||||||
type: 'billing_'
|
type: 'billing_'
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
label: 'Add Address',
|
label: 'Add Address',
|
||||||
onclick: 'this.parentNode.submit()',
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
{% if addresses|length > 1 %}
|
{% if addresses|length > 1 %}
|
||||||
|
|
|
@ -11,11 +11,10 @@
|
||||||
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
|
dark_theme: user_settings.dark_theme
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/primary.twig' with {
|
||||||
label: 'Save Profile',
|
label: 'Save Profile',
|
||||||
onclick: 'this.parentNode.submit()',
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,9 +32,8 @@
|
||||||
Verified:
|
Verified:
|
||||||
{{ user.verified ? 'Yes' : 'No' }}
|
{{ user.verified ? 'Yes' : 'No' }}
|
||||||
</h4>
|
</h4>
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/primary.twig' with {
|
||||||
label: 'Save Email',
|
label: 'Save Email',
|
||||||
onclick: 'this.parentNode.submit()',
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,7 +99,7 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
$0.00
|
{{ '$' ~ (balance.cents / 100) | number_format(2, '.', ',') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% include 'lib/rule.twig' %}
|
{% include 'lib/rule.twig' %}
|
||||||
|
@ -121,25 +119,36 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
0
|
{{ balance.sats | number_format(0, '', ',') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% include 'lib/rule.twig' %}
|
{% include 'lib/rule.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">
|
||||||
Marketing
|
Email Notifications
|
||||||
</h3>
|
</h3>
|
||||||
{% include 'lib/rule.twig' %}
|
{% include 'lib/rule.twig' %}
|
||||||
<form action="/account/promotionals" method="post" class="flex flex-col gap-4">
|
<form action="/account/notifications" method="post">
|
||||||
|
<div class="flex flex-col gap-4 mb-4">
|
||||||
{% 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: defailts.user_settings.opt_in_promotional
|
on: user_settings.opt_in_promotional
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/inputs/toggle.twig' with {
|
||||||
|
label: 'Recieve subscription reminders',
|
||||||
|
name: 'opt_in_subscription',
|
||||||
|
on: user_settings.opt_in_subscription
|
||||||
|
} %}
|
||||||
|
{% include 'lib/inputs/toggle.twig' with {
|
||||||
|
label: 'Recieve order updates',
|
||||||
|
name: 'opt_in_order',
|
||||||
|
on: user_settings.opt_in_order
|
||||||
|
} %}
|
||||||
|
</div>
|
||||||
|
{% include 'lib/buttons/primary.twig' with {
|
||||||
label: 'Save',
|
label: 'Save',
|
||||||
onclick: 'this.parentNode.submit()',
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
subtext: 'Get a one-time link sent to your email. No passwords!',
|
subtext: 'Get a one-time link sent to your email. No passwords!',
|
||||||
placeholder: 'Enter your e-mail'
|
placeholder: 'Enter your e-mail'
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
label: 'Get login link',
|
label: 'Get login link',
|
||||||
onclick: 'this.parentNode.submit()',
|
|
||||||
captcha: true
|
captcha: true
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -25,9 +25,8 @@
|
||||||
{% include 'lib/forms/address.twig' with {
|
{% include 'lib/forms/address.twig' with {
|
||||||
type: 'shipping_'
|
type: 'shipping_'
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
label: 'Add Address',
|
label: 'Add Address',
|
||||||
onclick: 'this.parentNode.submit()'
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
{% if addresses|length > 1 %}
|
{% if addresses|length > 1 %}
|
||||||
|
|
|
@ -85,9 +85,8 @@
|
||||||
} %}
|
} %}
|
||||||
</div>
|
</div>
|
||||||
{% include 'lib/rule.twig' with { text: 'ALL DONE!' } %}
|
{% include 'lib/rule.twig' with { text: 'ALL DONE!' } %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
label: 'Register',
|
label: 'Register',
|
||||||
onclick: 'this.parentNode.submit()',
|
|
||||||
captcha: true
|
captcha: true
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -10,66 +10,20 @@
|
||||||
{% include 'lib/rule.twig' %}
|
{% include 'lib/rule.twig' %}
|
||||||
</div>
|
</div>
|
||||||
{% include 'lib/alert.twig' %}
|
{% include 'lib/alert.twig' %}
|
||||||
<style>
|
|
||||||
.code-input {
|
|
||||||
font-size: 24px;
|
|
||||||
font-family: monospace;
|
|
||||||
text-align: left;
|
|
||||||
letter-spacing: 1.15em;
|
|
||||||
border: 2px solid #000;
|
|
||||||
padding: 10px;
|
|
||||||
width: 250px;
|
|
||||||
outline: none;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
white 0, white 36px, /* Box width */
|
|
||||||
black 36px, black 38px /* Border between boxes */
|
|
||||||
);
|
|
||||||
background-size: 42px 100%; /* Adjust size to fit each character in a cell */
|
|
||||||
background-clip: padding-box;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<form action="/account/verify" method="post" class="flex flex-col items-center gap-4">
|
<form action="/account/verify" method="post" class="flex flex-col items-center gap-4">
|
||||||
<input type="tel" name="code" placeholder="******" class="code-input" maxlength="6" inputmode="numeric" pattern="[0-9]*">
|
{% include 'lib/inputs/text.twig' with {
|
||||||
<script>
|
type: 'tel',
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
name: 'code',
|
||||||
const input = document.querySelector(".code-input");
|
placeholder: '******',
|
||||||
|
class: 'code-input',
|
||||||
input.addEventListener("input", function (e) {
|
maxlength: 6,
|
||||||
// Remove any non-digit characters immediately
|
inputmode: 'numeric',
|
||||||
this.value = this.value.replace(/\D/g, "");
|
pattern: '[0-9]*'
|
||||||
// Move the cursor back one space then blur when the 6th digit is entered
|
} %}
|
||||||
if (this.value.length === 6) {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
this.setSelectionRange(this.value.length - 1, this.value.length - 1);
|
|
||||||
this.blur();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addEventListener("paste", function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
let pastedData = e.clipboardData.getData("text").replace(/\D/g, ""); // Allow only digits
|
|
||||||
this.value = pastedData.substring(0, this.maxLength);
|
|
||||||
// Clear focus if pasted data fills the input
|
|
||||||
if (this.value.length === 6) {
|
|
||||||
this.blur();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addEventListener("keypress", function (e) {
|
|
||||||
if (!/[0-9]/.test(e.key)) {
|
|
||||||
e.preventDefault(); // Block non-numeric input
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% include 'lib/button.twig' with {
|
|
||||||
label: 'Verify Code',
|
label: 'Verify Code',
|
||||||
onclick: 'this.parentNode.submit()',
|
|
||||||
captcha: true
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
zip: address.zip,
|
zip: address.zip,
|
||||||
phone: address.phone,
|
phone: address.phone,
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
label: 'Save Address',
|
label: 'Save Address',
|
||||||
onclick: 'this.parentNode.submit()'
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
Recently Sent Emails
|
Recently Sent Emails
|
||||||
</h3>
|
</h3>
|
||||||
<table class="min-w-full bg-white">
|
<table class="min-w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="py-2">
|
<th class="py-2">
|
||||||
|
|
|
@ -52,16 +52,16 @@
|
||||||
value: session.last_post.user_identifier
|
value: session.last_post.user_identifier
|
||||||
} %}
|
} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
label: 'Submit',
|
label: 'Submit',
|
||||||
onclick: 'this.parentNode.submit()'
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
{% if session.last_post %}
|
{% if session.last_post %}
|
||||||
{% include 'lib/button.twig' with {
|
<a href="/admin/transactions/reset">
|
||||||
label: 'Cancel',
|
{% include 'lib/buttons/default.twig' with {
|
||||||
href: '/admin/transactions/reset'
|
label: 'Cancel'
|
||||||
} %}
|
} %}
|
||||||
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -17,16 +17,15 @@
|
||||||
],
|
],
|
||||||
required: true
|
required: true
|
||||||
} %}
|
} %}
|
||||||
{% include 'lib/button.twig' with {
|
{% include 'lib/buttons/submit.twig' with {
|
||||||
label: 'Submit',
|
label: 'Submit',
|
||||||
onclick: 'this.parentNode.submit()'
|
|
||||||
} %}
|
} %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
Liabilities
|
Liabilities
|
||||||
</h3>
|
</h3>
|
||||||
<table class="min-w-full bg-white">
|
<table class="min-w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="py-2">
|
<th class="py-2">
|
||||||
|
@ -59,7 +58,7 @@
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
Sats Transactions
|
Sats Transactions
|
||||||
</h3>
|
</h3>
|
||||||
<table class="min-w-full bg-white">
|
<table class="min-w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="py-2">
|
<th class="py-2">
|
||||||
|
@ -101,7 +100,7 @@
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
Cents Transactions
|
Cents Transactions
|
||||||
</h3>
|
</h3>
|
||||||
<table class="min-w-full bg-white">
|
<table class="min-w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="py-2">
|
<th class="py-2">
|
||||||
|
@ -143,7 +142,7 @@
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
Whales Sats
|
Whales Sats
|
||||||
</h3>
|
</h3>
|
||||||
<table class="min-w-full bg-white">
|
<table class="min-w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="py-2">
|
<th class="py-2">
|
||||||
|
@ -179,7 +178,7 @@
|
||||||
<h3 class="text-2xl font-semibold">
|
<h3 class="text-2xl font-semibold">
|
||||||
Whales Cents
|
Whales Cents
|
||||||
</h3>
|
</h3>
|
||||||
<table class="min-w-full bg-white">
|
<table class="min-w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="py-2">
|
<th class="py-2">
|
||||||
|
|
|
@ -48,14 +48,20 @@
|
||||||
<img src="/img/logo-{{ theme }}.webp" />
|
<img src="/img/logo-{{ theme }}.webp" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<form action="/search" method="post" class="flex-grow max-w-[900px]">
|
<form action="/search" method="post" class="flex w-full max-w-[900px]">
|
||||||
|
<div class='flex-grow w-full'>
|
||||||
{% include 'lib/inputs/text.twig' with {
|
{% include 'lib/inputs/text.twig' with {
|
||||||
name: 'search',
|
name: 'search',
|
||||||
type: 'search',
|
type: 'search',
|
||||||
placeholder: 'What are you looking for?',
|
placeholder: 'What are you looking for?',
|
||||||
submit: true,
|
|
||||||
icon: 'search'
|
|
||||||
} %}
|
} %}
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="px-4 {{ colors.button.primary }} rounded-r">
|
||||||
|
<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-search">
|
||||||
|
<circle cx="11" cy="11" r="8" />
|
||||||
|
<path d="m21 21-4.3-4.3" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="flex flex-1 items-center justify-end gap-4 md:basis-[100px] md:min-w-[280px] md:max-w-[280px] xl:basis-[200px] xl:min-w-[300px] xl:max-w-[300px]">
|
<div class="flex flex-1 items-center justify-end gap-4 md:basis-[100px] md:min-w-[280px] md:max-w-[280px] xl:basis-[200px] xl:min-w-[300px] xl:max-w-[300px]">
|
||||||
<div class="flex gap-1">
|
<div class="flex gap-1">
|
||||||
|
@ -63,7 +69,7 @@
|
||||||
<!-- Hidden checkbox to control the dropdown -->
|
<!-- Hidden checkbox to control the dropdown -->
|
||||||
<input type="checkbox" id="dropdown-toggle" class="hidden peer">
|
<input type="checkbox" id="dropdown-toggle" class="hidden peer">
|
||||||
<!-- Dropdown button -->
|
<!-- Dropdown button -->
|
||||||
<label for="dropdown-toggle" class="{{ colors.button.default }} flex gap-1 items-center cursor-pointer p-1 py-2 rounded-md">
|
<label for="dropdown-toggle" class="{{ colors.button.dropdown }} flex gap-1 items-center cursor-pointer p-1 py-2 rounded-md">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user-round">
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user-round">
|
||||||
<circle cx="12" cy="8" r="5" />
|
<circle cx="12" cy="8" r="5" />
|
||||||
<path d="M20 21a8 8 0 0 0-16 0" />
|
<path d="M20 21a8 8 0 0 0-16 0" />
|
||||||
|
@ -159,7 +165,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<a href="/account/orders" class="{{ colors.button.default }} flex items-center gap-1 p-1 py-2 rounded-md">
|
<a href="/account/orders" class="{{ colors.button.dropdown }} flex items-center gap-1 p-1 py-2 rounded-md">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-box">
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-box">
|
||||||
<path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z" />
|
<path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z" />
|
||||||
<path d="m3.3 7 8.7 5 8.7-5" />
|
<path d="m3.3 7 8.7 5 8.7-5" />
|
||||||
|
|
|
@ -35,8 +35,8 @@
|
||||||
{% 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',
|
dangerText: 'Yes, delete',
|
||||||
okURL: '/address/delete/' ~ address.id ~ '?redirect=' ~ redirect
|
dangerURL: '/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>
|
||||||
|
@ -44,9 +44,9 @@
|
||||||
{% if set_default %}
|
{% if set_default %}
|
||||||
<form id="set-default-form-{{ address.id }}" action="/account/address/set-default-{{ set_default }}" method="post">
|
<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 }}" />
|
<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">
|
{% include 'lib/buttons/primary.twig' with {
|
||||||
Set Default
|
label: 'Set Default'
|
||||||
</button>
|
} %}
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
{% if href is defined %}
|
|
||||||
<a
|
|
||||||
href="{{ href }}" class="cursor-pointer {{ submit is defined ? 'px-4 rounded-l-none' : 'w-full' }} {{ colors.button.primary }} rounded-lg h-[42px] flex items-center justify-center">
|
|
||||||
{% else %}
|
|
||||||
<div onclick="{{ onclick }}" class="cursor-pointer {{ submit is defined ? 'px-4 rounded-l-none' : 'w-full' }} {{ colors.button.primary }} rounded-lg h-[42px] flex items-center justify-center">
|
|
||||||
{% endif %}
|
|
||||||
{% if label is defined %}
|
|
||||||
<span>
|
|
||||||
{{ label }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
{% if icon is defined %}
|
|
||||||
{% if icon == 'search' %}
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<circle cx="11" cy="11" r="8"></circle>
|
|
||||||
<path d="m21 21-4.3-4.3"></path>
|
|
||||||
</svg>
|
|
||||||
{% elseif icon == 'add' %}
|
|
||||||
<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-plus">
|
|
||||||
<path d="M5 12h14" />
|
|
||||||
<path d="M12 5v14" />
|
|
||||||
</svg>
|
|
||||||
{% elseif icon == 'enter' %}
|
|
||||||
<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-arrow-right">
|
|
||||||
<path d="M5 12h14" />
|
|
||||||
<path d="m12 5 7 7-7 7" />
|
|
||||||
</svg>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% if href is defined %}
|
|
||||||
</a>
|
|
||||||
{% else %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if captcha is defined %}
|
|
||||||
<div class="flex justify-center {{ colors.text.muted }}">
|
|
||||||
<p class="w-[250px] text-[10px] text-center">
|
|
||||||
This form is protected by reCAPTCHA and the Google
|
|
||||||
<a class="underline" href="https://policies.google.com/privacy">
|
|
||||||
Privacy Policy
|
|
||||||
</a>
|
|
||||||
and
|
|
||||||
<a class="underline" href="https://policies.google.com/terms">
|
|
||||||
Terms of Service
|
|
||||||
</a>
|
|
||||||
apply.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
3
src/views/lib/buttons/danger.twig
Normal file
3
src/views/lib/buttons/danger.twig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<button type="submit" class="{{ colors.button.danger }} font-bold py-2 px-4 rounded no-underline">
|
||||||
|
{{ label }}
|
||||||
|
</button>
|
3
src/views/lib/buttons/default.twig
Normal file
3
src/views/lib/buttons/default.twig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<button class="{{ colors.button.default }} font-bold py-2 px-4 rounded">
|
||||||
|
Cancel
|
||||||
|
</button>
|
3
src/views/lib/buttons/primary.twig
Normal file
3
src/views/lib/buttons/primary.twig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<button type="submit" class="{{ colors.button.primary }} font-bold py-2 px-4 rounded no-underline">
|
||||||
|
{{ label }}
|
||||||
|
</button>
|
22
src/views/lib/buttons/submit.twig
Normal file
22
src/views/lib/buttons/submit.twig
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<button type="submit" class="{{ colors.button.primary }} w-full rounded-lg h-[42px] flex items-center justify-center">
|
||||||
|
{% if label is defined %}
|
||||||
|
<span>
|
||||||
|
{{ label }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
{% if captcha is defined %}
|
||||||
|
<div class="flex justify-center {{ colors.text.muted }}">
|
||||||
|
<p class="w-[250px] text-[10px] text-center">
|
||||||
|
This form is protected by reCAPTCHA and the Google
|
||||||
|
<a class="underline" href="https://policies.google.com/privacy">
|
||||||
|
Privacy Policy
|
||||||
|
</a>
|
||||||
|
and
|
||||||
|
<a class="underline" href="https://policies.google.com/terms">
|
||||||
|
Terms of Service
|
||||||
|
</a>
|
||||||
|
apply.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
|
@ -1,11 +1,5 @@
|
||||||
<label for="{{ id }}" class="block text-sm font-medium text-gray-700 mt-2">
|
<label for="{{ id }}" class="block text-sm font-medium mt-2">
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</label>
|
</label>
|
||||||
<input type="number" id="{{ id }}" name="{{ name }}" class="border rounded-lg p-2 w-full" {% if required %} required {% endif %} {% if min is defined %} min="{{ min }}" {% endif %} {% if max is defined %} max="{{ max }}" {% endif %} {% if step is defined %} step="{{ step }}" {% endif %} {% if value is defined %} value="{{ value }}" {% endif %} placeholder="{{ placeholder | default('Enter a number') }}">
|
<input type="number" id="{{ id }}" name="{{ name }}" class="border rounded-lg p-2 w-full" {% if required %} required {% endif %} {% if min is defined %} min="{{ min }}" {% endif %} {% if max is defined %} max="{{ max }}" {% endif %} {% if step is defined %} step="{{ step }}" {% endif %} {% if value is defined %} value="{{ value }}" {% endif %} placeholder="{{ placeholder | default('Enter a number') }}">
|
||||||
|
|
||||||
{% if subtext is defined %}
|
|
||||||
<p class="text-xs text-gray-500">
|
|
||||||
{{ subtext }}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<label for="{{ id }}" class="block text-sm font-medium text-gray-700 mt-2">
|
<label for="{{ id }}" class="block text-sm font-medium mt-2">
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</label>
|
</label>
|
||||||
<select id="{{ id }}" name="{{ name }}" class="border rounded-lg p-2 w-full" {% if required %} required {% endif %}>
|
<select id="{{ id }}" name="{{ name }}" class="border rounded-lg p-2 w-full" {% if required %} required {% endif %}>
|
||||||
{% for option in options %}
|
{% for option in options %}
|
||||||
<option value="{{ option.value }}" {% if option.value == value %} selected {% endif %}>{{ option.text }}</option>
|
<option value="{{ option.value }}" {% if option.value == value %} selected {% endif %}>
|
||||||
|
{{ option.text }}
|
||||||
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -21,17 +21,6 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</label>
|
</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if submit is defined %}
|
|
||||||
<div class="flex items-center">
|
<input type="{{ type }}" name="{{ name }}" {% if placeholder %} placeholder="{{ placeholder }}" {% endif %} {% if value is not null %} value="{{ value }}" {% endif %} {% if readonly is not null %} readonly {% endif %} {% if type == 'number' %} {% if min is defined %} min="{{ min }}" {% endif %} {% if max is defined %} max="{{ max }}" {% endif %} {% endif %} class="{{ colors.input }} w-full p-3 h-[42px] border focus:ring-1 focus:outline-none"></div>
|
||||||
{% endif %}
|
|
||||||
<input type="{{ type }}" name="{{ name }}" {% if placeholder %} placeholder="{{ placeholder }}" {% endif %} {% if value is not null %} value="{{ value }}" {% endif %} {% if readonly is not null %} readonly {% endif %} {% if type == 'number' %} {% if min is defined %} min="{{ min }}" {% endif %} {% if max is defined %} max="{{ max }}" {% endif %} {% endif %} class="{{ colors.input }} {{ submit is defined ? 'rounded-l-lg border-r-0' : 'rounded-lg' }} w-full p-3 h-[42px] border focus:ring-1 focus:outline-none">
|
|
||||||
{% if submit is defined %}
|
|
||||||
{% include 'lib/button.twig' with {
|
|
||||||
icon: 'search'
|
|
||||||
} %}
|
|
||||||
{% endif %}
|
|
||||||
{% if submit is defined %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -11,14 +11,28 @@
|
||||||
{% if okURL is defined %}
|
{% if okURL is defined %}
|
||||||
<div class="flex justify-end mt-4">
|
<div class="flex justify-end mt-4">
|
||||||
<a href="#hide-{{ id }}" class="mr-4 no-underline">
|
<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">
|
{% include 'lib/buttons/default.twig' with {
|
||||||
Cancel
|
label: "Cancel"
|
||||||
</button>
|
} %}
|
||||||
</a>
|
</a>
|
||||||
<form action="{{ okURL }}" method="post" class="inline">
|
<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">
|
{% include 'lib/buttons/primary.twig' with {
|
||||||
{{ okText is defined ? okText : 'OK' }}
|
label: okText is defined ? okText : 'OK',
|
||||||
</button>
|
} %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if dangerURL is defined %}
|
||||||
|
<div class="flex justify-end mt-4">
|
||||||
|
<a href="#hide-{{ id }}" class="mr-4 no-underline">
|
||||||
|
{% include 'lib/buttons/default.twig' with {
|
||||||
|
label: "Cancel"
|
||||||
|
} %}
|
||||||
|
</a>
|
||||||
|
<form action="{{ dangerURL }}" method="post" class="inline">
|
||||||
|
{% include 'lib/buttons/danger.twig' with {
|
||||||
|
label: dangerText is defined ? dangerText : 'OK',
|
||||||
|
} %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
<div>
|
<div>
|
||||||
|
<div class="text-xl font-semibold mb-4 text-center">
|
||||||
|
You have
|
||||||
|
<strong>
|
||||||
|
{{ '$' ~ (balance.cents / 100) | number_format(2, '.', ',') }}
|
||||||
|
USD
|
||||||
|
</strong>
|
||||||
|
in store credit
|
||||||
|
</div>
|
||||||
<div class="text-lg font-semibold mb-4">
|
<div class="text-lg font-semibold mb-4">
|
||||||
Why do I have store credit?
|
Why do I have store credit?
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,19 @@
|
||||||
<div>
|
<div>
|
||||||
|
<div class="text-xl font-semibold mb-4 text-center">
|
||||||
|
You have
|
||||||
|
<strong>
|
||||||
|
{{ balance.sats }}
|
||||||
|
</strong>
|
||||||
|
sats!
|
||||||
|
</div>
|
||||||
|
<div class="text-lg font-semibold mb-4">
|
||||||
|
What are sats?
|
||||||
|
</div>
|
||||||
|
<ul class="list-disc pl-6 mb-4">
|
||||||
|
<li>
|
||||||
|
Sats are fractions of a Bitcoin (BTC). There are 100 million sats in one Bitcoin (BTC).
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<div class="text-lg font-semibold mb-4">
|
<div class="text-lg font-semibold mb-4">
|
||||||
Why do I have sats?
|
Why do I have sats?
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,18 +22,19 @@
|
||||||
You may have received sats from a promotional event
|
You may have received sats from a promotional event
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
You may have recieved sats sent to your default generated Lightning Address (LNURL):
|
You may have recieved sats sent to your generated Lightning Address (LNURL):
|
||||||
{{ user.npub }}
|
<br>
|
||||||
@
|
<strong>
|
||||||
{{ http_host }}
|
{{ user.npub ~ '@' ~ http_host }}
|
||||||
|
</string>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="text-lg font-semibold mb-4">
|
<div class="text-lg font-semibold mb-4">
|
||||||
What can I do with sats?
|
What can I do with these sats?
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-disc pl-6">
|
<ul class="list-disc pl-6">
|
||||||
<li>
|
<li>
|
||||||
You may spend sats at checkout
|
You may spend these sats at checkout
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Your subscriptions and recurring purchases can also be paid with sats
|
Your subscriptions and recurring purchases can also be paid with sats
|
||||||
|
@ -28,3 +44,4 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue