kinda working
This commit is contained in:
parent
8b6ea946bf
commit
b3ded91d01
13
README.md
13
README.md
@ -8,6 +8,19 @@
|
|||||||
|
|
||||||
## Start Dev
|
## Start Dev
|
||||||
|
|
||||||
|
### Beim ersten Start
|
||||||
|
|
||||||
|
Config file erstellen bzw kopieren
|
||||||
|
|
||||||
|
1. `cd web/api/inc`
|
||||||
|
2. Datei `example.config.inc.php` umbenennen auf `config.inc.php`
|
||||||
|
3. Gegebenenfalls Werte anpassen in der Config
|
||||||
|
|
||||||
|
Composer sachen holen
|
||||||
|
|
||||||
|
1. `cd web/api/inc`
|
||||||
|
2. `composer install`
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
Erst Tailwind starten
|
Erst Tailwind starten
|
||||||
|
2
web/api/inc/.gitignore
vendored
Normal file
2
web/api/inc/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
vendor
|
||||||
|
config.inc.php
|
113
web/api/inc/classes/Page.class.php
Normal file
113
web/api/inc/classes/Page.class.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page is the Controller Class
|
||||||
|
* which should be extended by any page
|
||||||
|
*
|
||||||
|
* @author Christian Haschek
|
||||||
|
*/
|
||||||
|
class Page
|
||||||
|
{
|
||||||
|
protected $_controller;
|
||||||
|
protected $_action;
|
||||||
|
protected $_template;
|
||||||
|
public $variables;
|
||||||
|
public $params;
|
||||||
|
public $render;
|
||||||
|
public $menu_text;
|
||||||
|
public $menu_image;
|
||||||
|
public $menu_priority;
|
||||||
|
public $submenu;
|
||||||
|
|
||||||
|
function __construct($controller, $action, $r = 1, $params = [])
|
||||||
|
{
|
||||||
|
$this->_controller = $controller;
|
||||||
|
$this->_action = $action;
|
||||||
|
$this->render = $r;
|
||||||
|
$this->submenu = array();
|
||||||
|
$this->setMenu();
|
||||||
|
$this->params = $params;
|
||||||
|
if(is_array($GLOBALS['vars']) && is_array($this->params))
|
||||||
|
$this->params = array_merge($this->params, $GLOBALS['vars']);
|
||||||
|
$this->menu_image = '/css/imgs/empty.png';
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMenu()
|
||||||
|
{
|
||||||
|
$this->menu_text = '';
|
||||||
|
$this->menu_priority = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirect($url)
|
||||||
|
{
|
||||||
|
header("Location: $url");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* override this function to check if a user can use this object
|
||||||
|
* @return true -> user will be able to access
|
||||||
|
* @return false -> user will not be able to access and this page won't
|
||||||
|
* be shown in the menu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function maySeeThisPage()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set($name, $value)
|
||||||
|
{
|
||||||
|
$this->variables[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($name)
|
||||||
|
{
|
||||||
|
return $this->variables[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
function __destruct()
|
||||||
|
{
|
||||||
|
// if($this->render)
|
||||||
|
// $this->_template->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addHelpers($m)
|
||||||
|
{
|
||||||
|
$m->addHelper('case', [
|
||||||
|
'lower' => function($value) { return strtolower((string) $value); },
|
||||||
|
'upper' => function($value) { return strtoupper((string) $value); }
|
||||||
|
]);
|
||||||
|
$m->addHelper('!!', function($value) { return $value . '!!'; });
|
||||||
|
|
||||||
|
return $m;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPagecontent()
|
||||||
|
{
|
||||||
|
$controller_dir = ROOT . DS . 'pages' . DS . $this->_controller . DS;
|
||||||
|
$partials = [];
|
||||||
|
if(is_dir($controller_dir.'partials'))
|
||||||
|
$partials[] = new Mustache_Loader_FilesystemLoader($controller_dir.'partials');
|
||||||
|
$partials[] = new Mustache_Loader_FilesystemLoader(ROOT.DS.'..'.DS.'templates'.DS.'partials');
|
||||||
|
$m = new Mustache_Engine(array(
|
||||||
|
'entity_flags' => ENT_QUOTES,
|
||||||
|
'partials_loader' => new Mustache_Loader_CascadingLoader($partials)
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->variables['translate'] = function($value) { return translate($value); };
|
||||||
|
|
||||||
|
$m = $this->addHelpers($m);
|
||||||
|
|
||||||
|
if($this->variables['template'] && file_exists(ROOT . DS . 'pages' . DS . $this->_controller . DS . $this->variables['template']))
|
||||||
|
$template = file_get_contents(ROOT . DS . 'pages' . DS . $this->_controller . DS . $this->variables['template']);
|
||||||
|
else
|
||||||
|
$template = file_get_contents(ROOT . DS . 'views' . DS . 'defaultcontainer.mustache');
|
||||||
|
|
||||||
|
|
||||||
|
$pagecontent = $m->render($template, $this->variables);
|
||||||
|
|
||||||
|
return $pagecontent;
|
||||||
|
}
|
||||||
|
}
|
5
web/api/inc/composer.json
Normal file
5
web/api/inc/composer.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"mustache/mustache": "^2.14"
|
||||||
|
}
|
||||||
|
}
|
69
web/api/inc/composer.lock
generated
Normal file
69
web/api/inc/composer.lock
generated
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "e982fabf51f3a80b1d9fcbcdb4621616",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "mustache/mustache",
|
||||||
|
"version": "v2.14.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/bobthecow/mustache.php.git",
|
||||||
|
"reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/e62b7c3849d22ec55f3ec425507bf7968193a6cb",
|
||||||
|
"reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.2.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "~1.11",
|
||||||
|
"phpunit/phpunit": "~3.7|~4.0|~5.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Mustache": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Justin Hileman",
|
||||||
|
"email": "justin@justinhileman.info",
|
||||||
|
"homepage": "http://justinhileman.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A Mustache implementation in PHP.",
|
||||||
|
"homepage": "https://github.com/bobthecow/mustache.php",
|
||||||
|
"keywords": [
|
||||||
|
"mustache",
|
||||||
|
"templating"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/bobthecow/mustache.php/issues",
|
||||||
|
"source": "https://github.com/bobthecow/mustache.php/tree/v2.14.2"
|
||||||
|
},
|
||||||
|
"time": "2022-08-23T13:07:01+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.2.0"
|
||||||
|
}
|
72
web/api/inc/core.php
Normal file
72
web/api/inc/core.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
spl_autoload_register('autoload');
|
||||||
|
function autoload($className)
|
||||||
|
{
|
||||||
|
//one of the global classes?
|
||||||
|
if (file_exists(ROOT . DS . 'inc'. DS. 'classes' . DS . $className . '.class.php'))
|
||||||
|
require_once(ROOT . DS . 'inc'. DS. 'classes' . DS . $className . '.class.php');
|
||||||
|
else if (file_exists(ROOT . DS . 'pages' . DS . strtolower($className) . DS . 'controller.php'))
|
||||||
|
require_once(ROOT . DS . 'pages' . DS . strtolower($className) . DS . 'controller.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
function includeManagement()
|
||||||
|
{
|
||||||
|
require_once(ROOT.DS.'inc'.DS.'helpers.php');
|
||||||
|
require_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||||
|
|
||||||
|
//settings from config
|
||||||
|
if(defined('DEV') && DEV===true)
|
||||||
|
ini_set("display_errors", 1);
|
||||||
|
else ini_set("display_errors", 0);
|
||||||
|
|
||||||
|
if(file_exists(ROOT.DS.'inc'.DS.'vendor'.DS.'autoload.php'))
|
||||||
|
require_once(ROOT.DS.'inc'.DS.'vendor'.DS.'autoload.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
function callHook($url)
|
||||||
|
{
|
||||||
|
$queryString = array();
|
||||||
|
|
||||||
|
if (!$url[0]) {
|
||||||
|
$component = 'home';
|
||||||
|
$action = 'index';
|
||||||
|
} else {
|
||||||
|
$urlArray = $url;
|
||||||
|
$component = $urlArray[0];
|
||||||
|
array_shift($urlArray);
|
||||||
|
$params = $urlArray;
|
||||||
|
if (isset($urlArray[0])) {
|
||||||
|
$action = $urlArray[0];
|
||||||
|
array_shift($urlArray);
|
||||||
|
} else
|
||||||
|
$action = 'index'; // Default Action
|
||||||
|
$queryString = $urlArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!file_exists(ROOT . DS . 'pages' . DS . $component . DS . 'controller.php')) {
|
||||||
|
$component = 'err';
|
||||||
|
$action = 'notfound';
|
||||||
|
$queryString = array($url);
|
||||||
|
}
|
||||||
|
|
||||||
|
$componentName = ucfirst($component);
|
||||||
|
|
||||||
|
$dispatch = new $componentName($component, $action, false);
|
||||||
|
|
||||||
|
if (!$dispatch->maySeeThisPage()) {
|
||||||
|
$componentName = 'err';
|
||||||
|
$action = 'notallowed';
|
||||||
|
$dispatch = new $componentName('error', $action, true);
|
||||||
|
} else
|
||||||
|
$dispatch = new $componentName($component, $action, true, $queryString);
|
||||||
|
|
||||||
|
if (method_exists($componentName, $action)) {
|
||||||
|
call_user_func_array(array($dispatch, $action), $queryString);
|
||||||
|
} else if (method_exists($componentName, 'catchAll'))
|
||||||
|
call_user_func_array(array($dispatch, 'catchAll'), array($params));
|
||||||
|
|
||||||
|
return $dispatch->renderPagecontent();
|
||||||
|
}
|
2
web/api/inc/example.config.inc.php
Normal file
2
web/api/inc/example.config.inc.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
|
170
web/api/inc/helpers.php
Normal file
170
web/api/inc/helpers.php
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
function sendMail($rcpt,$subject,$markdown)
|
||||||
|
{
|
||||||
|
$mail = new PHPMailer();
|
||||||
|
$pd = new Parsedown();
|
||||||
|
|
||||||
|
$html = $pd->text($markdown);
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
$mail->CharSet ="UTF-8";
|
||||||
|
$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
|
||||||
|
$mail->isSMTP(); // Send using SMTP
|
||||||
|
$mail->Host = SMTP_HOST; // Set the SMTP server to send through
|
||||||
|
$mail->SMTPAuth = (defined('SMTP_AUTH')?SMTP_AUTH:true); // Enable SMTP authentication
|
||||||
|
$mail->Username = SMTP_USER; // SMTP username
|
||||||
|
$mail->Password = SMTP_PW; // SMTP password
|
||||||
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
|
||||||
|
$mail->Port = (defined('SMTP_PORT')?SMTP_PORT:587); // TCP port to connect to
|
||||||
|
if(defined('SMTP_EHLO_DOMAIN') && SMTP_EHLO_DOMAIN)
|
||||||
|
$mail->Hostname = SMTP_EHLO_DOMAIN;
|
||||||
|
|
||||||
|
//make sure we use ipv4
|
||||||
|
$mail->SMTPOptions = [
|
||||||
|
'socket' => [
|
||||||
|
'bindto' => "0:0",
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
//Recipients
|
||||||
|
$mail->setFrom(EMAIL_FROM_EMAIL, EMAIL_FROM_NAME);
|
||||||
|
$mail->addAddress($rcpt); // Add a recipient
|
||||||
|
|
||||||
|
// Content
|
||||||
|
$mail->isHTML(true); // Set email format to HTML
|
||||||
|
$mail->Subject = $subject;
|
||||||
|
$mail->Body = $html;
|
||||||
|
$mail->AltBody = $markdown;
|
||||||
|
|
||||||
|
$mail->send();
|
||||||
|
|
||||||
|
$output = ob_get_clean();
|
||||||
|
|
||||||
|
addToMailLog($rcpt,$subject,$output);
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// found on https://html-online.com/articles/php-get-ip-cloudflare-proxy/
|
||||||
|
function getUserIP() {
|
||||||
|
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
|
||||||
|
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
|
||||||
|
$_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
|
||||||
|
}
|
||||||
|
$client = @$_SERVER['HTTP_CLIENT_IP'];
|
||||||
|
$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||||
|
$remote = $_SERVER['REMOTE_ADDR'];
|
||||||
|
|
||||||
|
if(filter_var($client, FILTER_VALIDATE_IP)) { $ip = $client; }
|
||||||
|
elseif(filter_var($forward, FILTER_VALIDATE_IP)) { $ip = $forward; }
|
||||||
|
else { $ip = $remote; }
|
||||||
|
|
||||||
|
return $ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// from https://stackoverflow.com/a/834355/1174516
|
||||||
|
function startsWith( $haystack, $needle ) {
|
||||||
|
$length = strlen( $needle );
|
||||||
|
return substr( $haystack, 0, $length ) === $needle;
|
||||||
|
}
|
||||||
|
function endsWith( $haystack, $needle ) {
|
||||||
|
$length = strlen( $needle );
|
||||||
|
if( !$length ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return substr( $haystack, -$length ) === $needle;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_cli()
|
||||||
|
{
|
||||||
|
if ( defined('STDIN') )
|
||||||
|
return true;
|
||||||
|
if ( php_sapi_name() === 'cli' )
|
||||||
|
return true;
|
||||||
|
if ( array_key_exists('SHELL', $_ENV) )
|
||||||
|
return true;
|
||||||
|
if ( empty($_SERVER['REMOTE_ADDR']) and !isset($_SERVER['HTTP_USER_AGENT']) and count($_SERVER['argv']) > 0)
|
||||||
|
return true;
|
||||||
|
if ( !array_key_exists('REQUEST_METHOD', $_SERVER) )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addToLog($text,$module='general')
|
||||||
|
{
|
||||||
|
$fp = fopen(ROOT.DS.'..'.DS.'log'.DS.$module.'.log','a');
|
||||||
|
fwrite($fp,'['.date("y.m.d H:i").']'.$text.PHP_EOL);
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addToMailLog($rcpt,$subject,$response)
|
||||||
|
{
|
||||||
|
$rcpt_esc = str_replace('@','_at_',$rcpt);
|
||||||
|
$dir = ROOT.DS.'..'.DS.'log'.DS.'maillog';
|
||||||
|
if(!is_dir($dir))
|
||||||
|
mkdir($dir);
|
||||||
|
$fp = fopen($dir.DS.$rcpt_esc.'.log','a');
|
||||||
|
fwrite($fp,"========= NEW MAIL ========\n[".date("y.m.d H:i")."] To: $rcpt\nSubject: $subject\n\n$response\n\n");
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function translate($what)
|
||||||
|
{
|
||||||
|
$what = trim($what);
|
||||||
|
return ($GLOBALS['translations'][$what]?:$what);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFilesOfFolder($dir)
|
||||||
|
{
|
||||||
|
return array_diff(scandir($dir), array('.', '..'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dbNeedsToBeUpgraded()
|
||||||
|
{
|
||||||
|
if(DB_TYPE=='sqlite' && !file_exists(ROOT.DS.'..'.DS.'data'.DS.'db.sqlite3'))
|
||||||
|
return true;
|
||||||
|
else if(!file_exists(ROOT.DS.'..'.DS.'log'.DS.'db_version'))
|
||||||
|
return true;
|
||||||
|
else if($GLOBALS['db_version']<getHighestSQLVersion())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHighestSQLVersion()
|
||||||
|
{
|
||||||
|
$dir = ROOT.DS.'..'.DS.'sql'.DS;
|
||||||
|
$files = array_diff(scandir($dir), array('..', '.'));
|
||||||
|
$files = array_map(function($e){
|
||||||
|
return pathinfo($e, PATHINFO_FILENAME);
|
||||||
|
}, $files);
|
||||||
|
|
||||||
|
sort($files);
|
||||||
|
|
||||||
|
return end($files);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gen_uuid() {
|
||||||
|
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||||
|
// 32 bits for "time_low"
|
||||||
|
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
|
||||||
|
|
||||||
|
// 16 bits for "time_mid"
|
||||||
|
mt_rand( 0, 0xffff ),
|
||||||
|
|
||||||
|
// 16 bits for "time_hi_and_version",
|
||||||
|
// four most significant bits holds version number 4
|
||||||
|
mt_rand( 0, 0x0fff ) | 0x4000,
|
||||||
|
|
||||||
|
// 16 bits, 8 bits for "clk_seq_hi_res",
|
||||||
|
// 8 bits for "clk_seq_low",
|
||||||
|
// two most significant bits holds zero and one for variant DCE1.1
|
||||||
|
mt_rand( 0, 0x3fff ) | 0x8000,
|
||||||
|
|
||||||
|
// 48 bits for "node"
|
||||||
|
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
|
||||||
|
);
|
||||||
|
}
|
33
web/api/index.php
Normal file
33
web/api/index.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
define('DS', DIRECTORY_SEPARATOR);
|
||||||
|
define('ROOT', dirname(__FILE__));
|
||||||
|
|
||||||
|
// if(file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||||
|
// include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||||
|
// else die('ERR: no config file found :(');
|
||||||
|
|
||||||
|
include_once(ROOT.DS.'inc'.DS.'core.php');
|
||||||
|
includeManagement();
|
||||||
|
|
||||||
|
if($_GET['url'])
|
||||||
|
$url = explode('/',ltrim(parse_url($_GET['url'], PHP_URL_PATH),'/'));
|
||||||
|
else if($_SERVER['HTTP_HX_CURRENT_URL'])
|
||||||
|
$url = explode('/',ltrim(parse_url($_SERVER['HTTP_HX_CURRENT_URL'], PHP_URL_PATH),'/'));
|
||||||
|
else $url = array_filter(explode('/',ltrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH),'/')));
|
||||||
|
|
||||||
|
if(count($url) > 0 && ($url[0]=='api' || $url[0]=='backend'))
|
||||||
|
array_shift($url);
|
||||||
|
|
||||||
|
//echo print_r(['url'=>$url,'server'=>$_SERVER,'request'=>$_REQUEST,'cookie'=>$_COOKIE,'session'=>$_SESSION],true);
|
||||||
|
|
||||||
|
|
||||||
|
$response = callHook($url);
|
||||||
|
|
||||||
|
if(is_string($response))
|
||||||
|
echo $response;
|
||||||
|
else if(is_array($response))
|
||||||
|
echo json_encode($response);
|
||||||
|
else if(is_object($response))
|
||||||
|
echo json_encode($response);
|
||||||
|
else echo json_encode(['error'=>'unknown response type']);
|
19
web/api/pages/home/controller.php
Normal file
19
web/api/pages/home/controller.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Home extends Page
|
||||||
|
{
|
||||||
|
function setMenu()
|
||||||
|
{
|
||||||
|
$this->menu_text = 'home';
|
||||||
|
$this->menu_image = 'mdi-action-home';
|
||||||
|
$this->menu_priority = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function index()
|
||||||
|
{
|
||||||
|
$this->set('template', "home.mustache");
|
||||||
|
return $this->renderPagecontent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function maySeeThisPage(){return true;}
|
||||||
|
}
|
20
web/api/pages/home/home.mustache
Normal file
20
web/api/pages/home/home.mustache
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<div class="hidden sm:mb-8 sm:flex sm:justify-center">
|
||||||
|
<div
|
||||||
|
class="relative rounded-full px-3 py-1 text-sm leading-6 text-gray-600 ring-1 ring-gray-900/10 hover:ring-gray-900/20">
|
||||||
|
Announcing our next round of funding. <a href="#" class="font-semibold text-indigo-600"><span
|
||||||
|
class="absolute inset-0" aria-hidden="true"></span>Read more <span
|
||||||
|
aria-hidden="true">→</span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">Dogstats - der Agilityhelfer</h1>
|
||||||
|
<p class="mt-6 text-lg leading-8 text-gray-600">Anim aute id magna aliqua ad ad non deserunt sunt.
|
||||||
|
Qui irure qui lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.</p>
|
||||||
|
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||||
|
<a href="#"
|
||||||
|
class="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Get
|
||||||
|
started</a>
|
||||||
|
<a href="#" class="text-sm font-semibold leading-6 text-gray-900">Learn more <span
|
||||||
|
aria-hidden="true">→</span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -534,27 +534,622 @@ video {
|
|||||||
--tw-backdrop-sepia: ;
|
--tw-backdrop-sepia: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed {
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.absolute {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inset-0 {
|
||||||
|
inset: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inset-x-0 {
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inset-y-0 {
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-top-40 {
|
||||||
|
top: -10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-\[calc\(50\%\+3rem\)\] {
|
||||||
|
left: calc(50% + 3rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-\[calc\(50\%-11rem\)\] {
|
||||||
|
left: calc(50% - 11rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-0 {
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-0 {
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-\[calc\(100\%-13rem\)\] {
|
||||||
|
top: calc(100% - 13rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.isolate {
|
||||||
|
isolation: isolate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-z-10 {
|
||||||
|
z-index: -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-50 {
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-m-1 {
|
||||||
|
margin: -0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-m-1\.5 {
|
||||||
|
margin: -0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-m-2 {
|
||||||
|
margin: -0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-m-2\.5 {
|
||||||
|
margin: -0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-auto {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-mx-3 {
|
||||||
|
margin-left: -0.75rem;
|
||||||
|
margin-right: -0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-my-6 {
|
||||||
|
margin-top: -1.5rem;
|
||||||
|
margin-bottom: -1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-10 {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-6 {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-6 {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-3 {
|
||||||
|
margin-left: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-2 {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-flex {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
display: table;
|
display: table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flow-root {
|
||||||
|
display: flow-root;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aspect-\[1155\/678\] {
|
||||||
|
aspect-ratio: 1155/678;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-24 {
|
||||||
|
height: 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-6 {
|
||||||
|
height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-8 {
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-12 {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-4 {
|
||||||
|
height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-5 {
|
||||||
|
height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-24 {
|
||||||
|
width: 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-6 {
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-\[36\.125rem\] {
|
||||||
|
width: 36.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-auto {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-12 {
|
||||||
|
width: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-4 {
|
||||||
|
width: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-8 {
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-2xl {
|
||||||
|
max-width: 42rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-sm {
|
||||||
|
max-width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shrink-0 {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-translate-x-1\/2 {
|
||||||
|
--tw-translate-x: -50%;
|
||||||
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-\[30deg\] {
|
||||||
|
--tw-rotate: 30deg;
|
||||||
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
|
.transform-gpu {
|
||||||
|
transform: translate3d(var(--tw-translate-x), var(--tw-translate-y), 0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-start {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-x-6 {
|
||||||
|
-moz-column-gap: 1.5rem;
|
||||||
|
column-gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
--tw-space-y-reverse: 0;
|
||||||
|
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
|
||||||
|
margin-bottom: calc(1rem * var(--tw-space-y-reverse));
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
--tw-space-y-reverse: 0;
|
||||||
|
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||||
|
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
--tw-space-x-reverse: 0;
|
||||||
|
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
||||||
|
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.divide-y > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
--tw-divide-y-reverse: 0;
|
||||||
|
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
||||||
|
border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
|
||||||
|
}
|
||||||
|
|
||||||
|
.divide-gray-500\/10 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
border-color: rgb(107 114 128 / 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overflow-y-auto {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-full {
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-xl {
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-lg {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-md {
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded {
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border {
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-gray-300 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-slate-100 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(241 245 249 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-indigo-600 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(79 70 229 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gray-50 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gradient-to-tr {
|
||||||
|
background-image: linear-gradient(to top right, var(--tw-gradient-stops));
|
||||||
|
}
|
||||||
|
|
||||||
|
.from-\[\#ff80b5\] {
|
||||||
|
--tw-gradient-from: #ff80b5 var(--tw-gradient-from-position);
|
||||||
|
--tw-gradient-to: rgb(255 128 181 / 0) var(--tw-gradient-to-position);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
||||||
|
}
|
||||||
|
|
||||||
|
.to-\[\#9089fc\] {
|
||||||
|
--tw-gradient-to: #9089fc var(--tw-gradient-to-position);
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-8 {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-1 {
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-1\.5 {
|
||||||
|
padding: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-2 {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-2\.5 {
|
||||||
|
padding: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-6 {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-3 {
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-3\.5 {
|
||||||
|
padding-left: 0.875rem;
|
||||||
|
padding-right: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-6 {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-1 {
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-2 {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-2\.5 {
|
||||||
|
padding-top: 0.625rem;
|
||||||
|
padding-bottom: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-32 {
|
||||||
|
padding-top: 8rem;
|
||||||
|
padding-bottom: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-6 {
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-5 {
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
padding-right: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-8 {
|
||||||
|
padding-top: 2rem;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-5 {
|
||||||
|
padding-top: 1.25rem;
|
||||||
|
padding-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-6 {
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-14 {
|
||||||
|
padding-top: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.text-3xl {
|
.text-3xl {
|
||||||
font-size: 1.875rem;
|
font-size: 1.875rem;
|
||||||
line-height: 2.25rem;
|
line-height: 2.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-lg {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-4xl {
|
||||||
|
font-size: 2.25rem;
|
||||||
|
line-height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-base {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-sm {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-xl {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-2xl {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.font-bold {
|
.font-bold {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-medium {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-semibold {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-light {
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-6 {
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-7 {
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-8 {
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-tight {
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracking-tight {
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-sky-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(14 165 233 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-slate-700 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(51 65 85 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-600 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(75 85 99 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-700 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(55 65 81 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-900 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-indigo-600 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(79 70 229 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-white {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-black {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(0 0 0 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-slate-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(100 116 139 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gray-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(107 114 128 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.underline {
|
.underline {
|
||||||
text-decoration-line: underline;
|
text-decoration-line: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opacity-30 {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-sm {
|
||||||
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-lg {
|
||||||
|
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||||
|
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow {
|
||||||
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||||
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-1 {
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-gray-900\/10 {
|
||||||
|
--tw-ring-color: rgb(17 24 39 / 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur-3xl {
|
||||||
|
--tw-blur: blur(64px);
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
.filter {
|
.filter {
|
||||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
}
|
}
|
||||||
@ -570,3 +1165,269 @@ video {
|
|||||||
.\[a-zA-Z\:\\-\\\.\] {
|
.\[a-zA-Z\:\\-\\\.\] {
|
||||||
a-z-a--z: \-\.;
|
a-z-a--z: \-\.;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:bg-gray-50:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover\:bg-indigo-500:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(99 102 241 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover\:underline:hover {
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover\:ring-gray-900\/20:hover {
|
||||||
|
--tw-ring-color: rgb(17 24 39 / 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus\:outline-none:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus\:ring-4:focus {
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-visible\:outline:focus-visible {
|
||||||
|
outline-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-visible\:outline-2:focus-visible {
|
||||||
|
outline-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-visible\:outline-offset-2:focus-visible {
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-visible\:outline-indigo-600:focus-visible {
|
||||||
|
outline-color: #4f46e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.dark\:border {
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:border-gray-600 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(75 85 99 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:border-gray-700 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(55 65 81 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:bg-slate-800 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(30 41 59 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:bg-gray-700 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:bg-gray-800 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:bg-gray-900 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-sky-400 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(56 189 248 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-slate-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(100 116 139 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-gray-300 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(209 213 219 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-gray-400 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(156 163 175 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-white {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:placeholder-gray-400::-moz-placeholder {
|
||||||
|
--tw-placeholder-opacity: 1;
|
||||||
|
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:placeholder-gray-400::placeholder {
|
||||||
|
--tw-placeholder-opacity: 1;
|
||||||
|
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:ring-offset-gray-800 {
|
||||||
|
--tw-ring-offset-color: #1f2937;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:focus\:border-blue-500:focus {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:focus\:ring-blue-500:focus {
|
||||||
|
--tw-ring-opacity: 1;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sm\:-top-80 {
|
||||||
|
top: -20rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:left-\[calc\(50\%\+36rem\)\] {
|
||||||
|
left: calc(50% + 36rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:left-\[calc\(50\%-30rem\)\] {
|
||||||
|
left: calc(50% - 30rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:top-\[calc\(100\%-30rem\)\] {
|
||||||
|
top: calc(100% - 30rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:mb-8 {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:w-\[72\.1875rem\] {
|
||||||
|
width: 72.1875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:max-w-sm {
|
||||||
|
max-width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:max-w-md {
|
||||||
|
max-width: 28rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:p-8 {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:py-48 {
|
||||||
|
padding-top: 12rem;
|
||||||
|
padding-bottom: 12rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:text-6xl {
|
||||||
|
font-size: 3.75rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:text-sm {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:ring-1 {
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:ring-gray-900\/10 {
|
||||||
|
--tw-ring-color: rgb(17 24 39 / 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.md\:mt-0 {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:h-screen {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
--tw-space-y-reverse: 0;
|
||||||
|
margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||||
|
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:text-2xl {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:flex-1 {
|
||||||
|
flex: 1 1 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:justify-end {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:gap-x-12 {
|
||||||
|
-moz-column-gap: 3rem;
|
||||||
|
column-gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:px-8 {
|
||||||
|
padding-left: 2rem;
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:py-56 {
|
||||||
|
padding-top: 14rem;
|
||||||
|
padding-bottom: 14rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:py-0 {
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
.xl\:p-0 {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
}
|
BIN
web/imgs/dogstats-50.png
Normal file
BIN
web/imgs/dogstats-50.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
web/imgs/dogstats.png
Normal file
BIN
web/imgs/dogstats.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 MiB |
123
web/index.html
123
web/index.html
@ -1,17 +1,112 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta charset="UTF-8">
|
||||||
<title>Document</title>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<!-- Tailwind CSS -->
|
<title>Dogstats</title>
|
||||||
<link href="/css/output.css" rel="stylesheet">
|
<link href="/css/output.css" rel="stylesheet">
|
||||||
<!-- htmx -->
|
<script src="/js/htmx.min.js"></script>
|
||||||
<script src="/js/htmx.min"></script>
|
</head>
|
||||||
</head>
|
|
||||||
<body>
|
<body></body>
|
||||||
<h1 class="text-3xl font-bold underline">
|
<div class="bg-white">
|
||||||
Hello world!
|
<header class="absolute inset-x-0 top-0 z-50">
|
||||||
</h1>
|
<nav class="flex items-center justify-between p-6 lg:px-8" aria-label="Global">
|
||||||
</body>
|
<div class="flex lg:flex-1">
|
||||||
|
<a href="#" hx-get="/api" hx-target="#main" class="-m-1.5 p-1.5">
|
||||||
|
<span class="sr-only">Dogstats</span>
|
||||||
|
<img class="h-8 w-auto" src="/imgs/dogstats-50.png" alt="">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="flex lg:hidden">
|
||||||
|
<button type="button"
|
||||||
|
class="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700">
|
||||||
|
<span class="sr-only">Open main menu</span>
|
||||||
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||||
|
aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="hidden lg:flex lg:gap-x-12">
|
||||||
|
<a href="#" hx-get="/templates/product.html" hx-target="#main" class="text-sm font-semibold leading-6 text-gray-900">Product</a>
|
||||||
|
<a href="#" hx-get="/templates/features.html" hx-target="#main" class="text-sm font-semibold leading-6 text-gray-900">Features</a>
|
||||||
|
</div>
|
||||||
|
<div class="hidden lg:flex lg:flex-1 lg:justify-end">
|
||||||
|
<a href="#" hx-get="/templates/login.html" hx-target="#main" class="text-sm font-semibold leading-6 text-gray-900">Log in <span
|
||||||
|
aria-hidden="true">→</span></a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<!-- Mobile menu, show/hide based on menu open state. -->
|
||||||
|
<div class="lg:hidden" role="dialog" aria-modal="true">
|
||||||
|
<!-- Background backdrop, show/hide based on slide-over state. -->
|
||||||
|
<div class="fixed inset-0 z-50"></div>
|
||||||
|
<div
|
||||||
|
class="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<a href="#" class="-m-1.5 p-1.5">
|
||||||
|
<span class="sr-only">Dogstatsy</span>
|
||||||
|
<img class="h-8 w-auto"
|
||||||
|
src="/imgs/dogstats-50.png" alt="">
|
||||||
|
</a>
|
||||||
|
<button type="button" class="-m-2.5 rounded-md p-2.5 text-gray-700">
|
||||||
|
<span class="sr-only">Close menu</span>
|
||||||
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
|
stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="mt-6 flow-root">
|
||||||
|
<div class="-my-6 divide-y divide-gray-500/10">
|
||||||
|
<div class="space-y-2 py-6">
|
||||||
|
<a href="#"
|
||||||
|
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Product</a>
|
||||||
|
<a href="#"
|
||||||
|
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Features</a>
|
||||||
|
</div>
|
||||||
|
<div class="py-6">
|
||||||
|
<a href="#"
|
||||||
|
class="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Log
|
||||||
|
in</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="relative isolate px-6 pt-14 lg:px-8">
|
||||||
|
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||||
|
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="main" hx-get="/api" hx-trigger="load" class="mx-auto max-w-2xl">
|
||||||
|
<div class="hidden sm:mb-8 sm:flex sm:justify-center">
|
||||||
|
<div
|
||||||
|
class="relative rounded-full px-3 py-1 text-sm leading-6 text-gray-600 ring-1 ring-gray-900/10 hover:ring-gray-900/20">
|
||||||
|
Announcing our next round of funding. <a href="#" class="font-semibold text-indigo-600"><span
|
||||||
|
class="absolute inset-0" aria-hidden="true"></span>Read more <span
|
||||||
|
aria-hidden="true">→</span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">Dogstats - der Agilityhelfer</h1>
|
||||||
|
<p class="mt-6 text-lg leading-8 text-gray-600">Anim aute id magna aliqua ad ad non deserunt sunt.
|
||||||
|
Qui irure qui lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.</p>
|
||||||
|
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||||
|
<a href="#"
|
||||||
|
class="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Get
|
||||||
|
started</a>
|
||||||
|
<a href="#" class="text-sm font-semibold leading-6 text-gray-900">Learn more <span
|
||||||
|
aria-hidden="true">→</span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</html>
|
</html>
|
1
web/templates/features.html
Normal file
1
web/templates/features.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
soo many features prolly
|
36
web/templates/login.html
Normal file
36
web/templates/login.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<section class="">
|
||||||
|
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
|
||||||
|
<div class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
|
||||||
|
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
|
||||||
|
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
|
||||||
|
Sign in to your account
|
||||||
|
</h1>
|
||||||
|
<form class="space-y-4 md:space-y-6" action="#">
|
||||||
|
<div>
|
||||||
|
<label for="email" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your email</label>
|
||||||
|
<input type="email" name="email" id="email" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="name@company.com" required="">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Password</label>
|
||||||
|
<input type="password" name="password" id="password" placeholder="••••••••" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-start">
|
||||||
|
<div class="flex items-center h-5">
|
||||||
|
<input id="remember" aria-describedby="remember" type="checkbox" class="w-4 h-4 border border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-primary-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-primary-600 dark:ring-offset-gray-800" required="">
|
||||||
|
</div>
|
||||||
|
<div class="ml-3 text-sm">
|
||||||
|
<label for="remember" class="text-gray-500 dark:text-gray-300">Remember me</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="#" class="text-sm font-medium text-primary-600 hover:underline dark:text-primary-500">Forgot password?</a>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">Sign in</button>
|
||||||
|
<p class="text-sm font-light text-gray-500 dark:text-gray-400">
|
||||||
|
Don’t have an account yet? <a href="#" class="font-medium text-primary-600 hover:underline dark:text-primary-500">Sign up</a>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
9
web/templates/product.html
Normal file
9
web/templates/product.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
|
||||||
|
<div class="shrink-0">
|
||||||
|
<img class="h-12 w-12" src="/imgs/dogstats.png" alt="Logo">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-xl font-medium text-black">Dogstats is super</div>
|
||||||
|
<p class="text-slate-500">You have a new message!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
Reference in New Issue
Block a user