summaryrefslogtreecommitdiff
path: root/html
diff options
context:
space:
mode:
Diffstat (limited to 'html')
-rw-r--r--html/app/config/app_constants.php29
-rw-r--r--html/app/controllers/Auth.php105
-rw-r--r--html/app/extends/Classroom_manager.php106
-rw-r--r--html/app/extends/Classroom_user.php105
-rw-r--r--html/app/models/admin/History_model.php25
-rw-r--r--html/app/models/admin/User_model.php52
-rw-r--r--html/app/routes/api.php68
-rw-r--r--html/app/routes/frontend.php4
-rw-r--r--html/app/views/basic.php50
-rw-r--r--html/app/views/components/breadcrumbs.php30
-rw-r--r--html/app/views/components/header_includes.php23
-rw-r--r--html/app/views/components/top-bar.php17
-rw-r--r--html/app/views/components/user-management.php35
-rw-r--r--html/app/views/error/404.php8
-rw-r--r--html/app/views/error/general.php8
-rw-r--r--html/app/views/group.php5
-rw-r--r--html/app/views/user/login.php8
-rw-r--r--html/app/views/user/new-password.php68
-rw-r--r--html/app/views/user/register.php175
-rw-r--r--html/app/views/welcome.php21
-rw-r--r--html/assets/css/class.css8
-rw-r--r--html/assets/css/overides.css13
22 files changed, 632 insertions, 331 deletions
diff --git a/html/app/config/app_constants.php b/html/app/config/app_constants.php
index 3c8d4c3..a89cc6a 100644
--- a/html/app/config/app_constants.php
+++ b/html/app/config/app_constants.php
@@ -1,6 +1,12 @@
<?php
+// CENTRAL DEFAULTS ////////////////////////////////////////////////////////////
+// -----------------------------------------------------------------------------
+
define('SITE_TITLE', 'Classroom');
+define('NO_REPLY_EMAIL', 'noreply@roptron.gr');
+define('REPLY_TO_EMAIL', 'noreply@roptron.gr');
+
// DEFAULT VALUES //////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
@@ -16,7 +22,7 @@ define('DEFAULT_PRIVILEGES', [
-define('COMMON_USER', 1);
+define('READER', 1);
define('EDITOR', 2);
define('ADMIN', 3);
@@ -87,3 +93,24 @@ define('FONT_FILES', array(
'CFAstyStdMedium' => 'CFAstyStd-Medium.woff2'
)
);
+
+
+
+
+// Mesagges ////////////////////////////////////////////////////////////////////
+// -----------------------------------------------------------------------------
+
+define('REGISTRATION_SUCCESS', "<h3>Επιτυχής Εγγραφή</h3>
+ <p>
+ Παρακαλώ ελέγξτε το email σας και ακολουθήστε το σύνδεσμο ενεργοποίησης
+ που σας 'εχει αποσταλεί, ώστε να έχετε πρόσβαση σε επιπλέον περιεχόμενο του site
+ </p>"
+);
+
+define ('REGISTRATION_USER_EXISTS', "<h3>Αποτυχία Εγγραφής</h3>
+ <p>
+ Υπάρχει ήδη χρήστης με αυτό το email. Αν δεν θυμάστε το password
+ μπορείτε να κάνετε επαναφορά του ακολουθώντας
+ <a href='/reset-password'>αυτό το σύνδεσμο</a>.
+ </p>"
+); \ No newline at end of file
diff --git a/html/app/controllers/Auth.php b/html/app/controllers/Auth.php
index c75f979..d0462e2 100644
--- a/html/app/controllers/Auth.php
+++ b/html/app/controllers/Auth.php
@@ -1,11 +1,17 @@
<?php
-
namespace app\controllers;
use Registry;
-use UserManager;
-use User;
-use app\models\user\User_model;
+
+// user classes and models
+use app\extends\Classroom_user;
+use app\extends\Classroom_manager;
+use app\models\admin\User_model;
+
+// mailer
+use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\SMTP;
+use PHPMailer\PHPMailer\Exception;
/** class Auth
@@ -52,28 +58,105 @@ class Auth {
}
+
+ public static function confirm_account()
+ {
+
+ }
+
/** register
*
- * registers new user
+ * Method for new user registration
*
*/
public static function register()
{
- $userManager = new UserManager();
+ $userManager = new Classroom_manager();
$req = Registry::get('REQUEST');
// create a salted password hash
$password = $userManager->cryptPassword($req->POST['password']);
+
+ // echo $password; print_r($req->POST); die(); // OK!
- $user = (new User())
- ->setUserName($req->POST['username'])
+ $user = (new Classroom_user())
+ ->setUserName($req->POST['email'])
->setPassword($password)
- ->setRoles(['ROLE_USER']);
+ ->setRoles([ READER ]) // Role: authorized reader
+ ->setPrivileges([]); // none privilege until acount confirmation
+
+ // create user record
+ $activation_code = User_model::registerUser($req->POST, $password);
// TODO:
- // store user to database
+ // handle error on user registration
+ // ...
+ //
+ // if ($activatopn_code[] == -1) {
+ // return [
+ // 'success' => false,
+ // 'message' => REGISTRATION_USER_EXISTS
+ // ];
+ // }
+
+ $activation_sent = self::mail_activationCode([
+ 'email' => $req->POST['email'],
+ 'name' => $req->POST['name'] .' '. $req->POST['surname'],
+ 'code' => $activation_code['activation']
+ ]);
+
+ // Send replies
+ if ($activation_sent) {
+ return [
+ 'success' => true,
+ 'message' => REGISTRATION_SUCCESS
+ ];
- $userManager->createUserToken($user);
+ } else {
+ return [
+ 'success' => false,
+ 'message' => 'error on sending email'
+ ];
+ }
+
+
+
+ }
+
+
+ private static function mail_activationCode($letter)
+ {
+ $mail = new PHPMailer();
+ $mail->CharSet = 'utf-8';
+ $mail->IsHTML(true);
+ //It's important not to use the submitter's address as the from address as it's forgery,
+ //which will cause your messages to fail SPF checks.
+ //Use an address in your own domain as the from address, put the submitter's address in a reply-to
+ $mail->setFrom(NO_REPLY_EMAIL, SITE_TITLE);
+ $mail->addAddress($letter['email'], $letter['name']);
+ $mail->addReplyTo(REPLY_TO_EMAIL, SITE_TITLE);
+ $mail->AddBCC("piipiis@gmail.com", "tester"); // notifiation email while testing
+ $mail->Subject = 'Εγγραφή στο Classroom';
+ $mail->Body = "Χαίρετε,<br>
+ το παρόν αυτοποιημένο email σάς έχει σταλεί γιατί έχει γίνει αίτημα εγγραφής σας στο Classroom.<br>
+ <br>
+ Όνομα επαφής: <b>". $letter['name'] ."</b><br>
+ Email : <b>". $letter['email'] ."</b><br>
+ <br>
+ Για να ενεργοποιήσετε την πρόσβασή σας στο site θα πρέπει να παρακαλώ πατήστε στον
+ παρακάτω σύνδεσμο url
+ <a href=\"https://eaadhsy.roptron.gr/activate?id=". $letter['code'] ."\">.
+ <br>
+ <br>
+ Μετά την ενεργοποίηση θα έχετε πρόσσβαση στο περιεχόμενο του site.<br>
+ <br>
+ Μην απαντήσετε στο email γιατί δεν υπάρχει φυσική επαφή η οποία να λαμβάνει τυχόν replies.<br>";
+ if (!$mail->send()) {
+ return false;
+ } else {
+ return true;
+ }
+
}
diff --git a/html/app/extends/Classroom_manager.php b/html/app/extends/Classroom_manager.php
new file mode 100644
index 0000000..4d38ba3
--- /dev/null
+++ b/html/app/extends/Classroom_manager.php
@@ -0,0 +1,106 @@
+<?php
+namespace app\extends;
+
+use UserManager;
+use Registry;
+
+
+/** ClassUserManager
+ *
+ * extends (anom's) UserManager
+ *
+ * this way it specializes the UserManagement
+ * according to this app's special rules
+ *
+ */
+class Classroom_manager extends UserManager
+{
+
+ private $index_key = 'email'; // identifing user field (username, email, etc )
+
+ protected $user;
+
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+
+ /** register user
+ *
+ * register into database;
+ * send OTP for account confirmation
+ *
+ * @param (void) : user properties passed via REQUEST->POST
+ *
+ */
+ public function register_user()
+ {
+ $req = Registry::get('REQUEST');
+ $register = User_model::registerUser($req->POST);
+
+ if ($register['success']) {
+
+ //create OTP;
+ $otp = $this->create_OPT($register['id']);
+
+ // send for account confirmation
+
+
+ } else {
+ print_r($register);
+ }
+
+ }
+
+
+ public function login_user()
+ {
+
+ }
+
+
+ /** forgot password
+ *
+ * send an otp
+ * (then verify)
+ *
+ */
+ public function forgot_password()
+ {
+
+ }
+
+
+ /** create OTP
+ *
+ * create a random OTP
+ * keep it into User's database Table
+ *
+ * @param $id (int): user id
+ *
+ */
+ public function create_OTP($id)
+ {
+ $otp = rand(100000,999999);
+ User_model::set_OTP($id, $otp);
+
+ return true;
+ }
+
+
+ /** Verify Account
+ *
+ * check if posted OTP matched the one sent to the user
+ *
+ * @param $identity (array): pair of [index_key => identity_value]
+ * example: [ 'email' => 'geo@roptron.gr' ]
+ *
+ */
+ public function verify_otp($identity, $otp)
+ {
+
+ }
+
+
+} \ No newline at end of file
diff --git a/html/app/extends/Classroom_user.php b/html/app/extends/Classroom_user.php
index b451114..fd1e573 100644
--- a/html/app/extends/Classroom_user.php
+++ b/html/app/extends/Classroom_user.php
@@ -1,107 +1,52 @@
<?php
-namespace app\controllers;
+namespace app\extends;
-use UserManager;
+use User;
use Registry;
-use app\models\admin\User_model;
-
-/** ClassUserManager
+/** Classroom_user
*
- * extends (anom's) UserManager
+ * extends (anom's) User
*
* this way it specializes the UserManagement
* according to this app's special rules
*
+ * Add privileges concept
+ * ---
+ * A Class_user has privileges (which are deferent than Roles)
+ * In fact, privileges extend the authorization requirements for users
+ *
+ * Authorized content is marked with some 'minimum Privilege'
+ * So the content is available to the READER(s) that have certain Privileges
+ *
*/
-class Classroom_user extends UserManager
+class Classroom_user extends User
{
- private $index_key = 'email'; // identifing user field (username, email, etc )
-
- protected $user;
-
- public function __construct()
- {
- parent::__construct();
- }
+ // @var array
+ private $privileges = [];
- /** register user
- *
- * register into database;
- * send OTP for account confirmation
- *
- * @param (void) : user properties passed via REQUEST->POST
+ /** getPrivileges
*
+ * @return privileges (array)
*/
- public function register_user()
+ public function getPrivileges(): array
{
- $req = Registry::get('REQUEST');
- $register = User_model::registerUser($req->POST);
-
- if ($register['success']) {
-
- //create OTP;
- $otp = $this->create_OPT($register['id']);
-
- // send for account confirmation
-
-
- } else {
- print_r($register);
- }
-
+ return $this->privileges;
}
-
- public function login_user()
- {
-
- }
-
-
- /** forgot password
+ /** setPrivileges()
*
- * send an otp
- * (then verify)
+ * @param array $privileges
*
+ * @return User
*/
- public function forgot_password()
+ public function setPrivileges(array $privileges): self
{
-
- }
-
-
- /** create OTP
- *
- * create a random OTP
- * keep it into User's database Table
- *
- * @param $id (int): user id
- *
- */
- public function create_OTP($id)
- {
- $otp = rand(100000,999999);
- User_model::set_OTP($id, $otp);
-
- return true;
- }
-
-
- /** Verify Account
- *
- * check if posted OTP matched the one sent to the user
- *
- * @param $identity (array): pair of [index_key => identity_value]
- * example: [ 'email' => 'geo@roptron.gr' ]
- *
- */
- public function verify_otp($identity, $otp)
- {
-
+ $this->privileges = $privileges;
+ return $this;
}
diff --git a/html/app/models/admin/History_model.php b/html/app/models/admin/History_model.php
index 438121e..04ce630 100644
--- a/html/app/models/admin/History_model.php
+++ b/html/app/models/admin/History_model.php
@@ -1,31 +1,30 @@
<?php
-
namespace app\models\admin;
use \Registry;
-class Histrory_model
+class History_model
{
/** track user access
*
*/
- public static function trackUserAccess($user_id, $type, $message, $note='')
+ public static function trackUserAccess($user_id, $type, $message, $note='_')
{
- $access = [
- 'user_id' => $user_id,
- 'type' => $type,
- 'message' => $message,
- 'note' => $note,
- 'ip' => Registry::get('REQUEST')->IP
- ];
Registry::use('database')->query(
"INSERT INTO history
- (user_id, `type`, `message`, note, ip)
- VALUES (:user_id, :type, :message, note, :ip)",
- [ $access ]
+ (user_id, `type`, `message`, `note`, `ip`)
+ VALUES
+ (:uid, :type, :msg, :note, :ip)",
+ [
+ ':uid' => $user_id,
+ ':type' => $type,
+ ':msg' => $message,
+ ':note' => $note,
+ ':ip' => Registry::get('REQUEST')->IP
+ ]
)->lastInsertID();
}
diff --git a/html/app/models/admin/User_model.php b/html/app/models/admin/User_model.php
index e4ac2ea..d0def1b 100644
--- a/html/app/models/admin/User_model.php
+++ b/html/app/models/admin/User_model.php
@@ -119,10 +119,18 @@ class User_model
/** create user
*
+ * creates user record;
+ * assigns privileged (usualy defaults);
+ * creates activation_code
+ *
+ * @param $data (array): Request->POST array
+ * @param $password (string): secure hashed password
+ *
+ * @return $activation_code
+ *
*/
- public static function registerUser($data, $privileges = ['ec.1', 'pr.1'])
+ public static function registerUser($data, $password, $privileges = ['ec.1', 'pr.1'])
{
-
$required_fields = [
'name',
'surname',
@@ -140,33 +148,43 @@ class User_model
return [ "success" => false, 'error' => EMPTY_REQUIRED_FIELDS ];
}
- // if isOK go on and create user record
- $user = [
- 'prefix' => $data['prefix'] ?? '',
- 'name' => $data['name'],
- 'surname' => $data['surname'],
- 'email' => $data['email'],
- 'password' => $data['password'],
- 'active' => 0 // needs email confirmation
- ];
- // insert new user record
+ // TODO:
+ // check if email exists
+ // ...
+
+ // create an activation code
+ $activation_code = md5($data['email'].time().rand(0, 10000));
+
+ // if isOK go on and...
+ // create user record
$new_user_id = Registry::use('database')->query(
"INSERT INTO user
- (`prefix`, `name`, `surname`, email, `password`, user_id)
+ (`first_name`, `last_name`, `email`, `password`, `active`, `activation`)
VALUES
- (:prefic, :name, :surname, :email, :password, :userid)"
- [ $user ]
+ (:nam, :surname, :email, :pass, :act, :actcode)",
+ [
+ ':nam' => $data['name'],
+ ':surname' => $data['surname'],
+ ':email' => $data['email'],
+ ':pass' => $password,
+ ':act' => 0, // needs email confirmation to be activated ...
+ ':actcode' => $activation_code // ... with the activation code
+ ]
)->lastInsertID();
// set default privileges
- self::set_user_privileges($privileges);
+ // self::set_user_privileges($privileges);
// update history
History::trackUserAccess($new_user_id, TRACK_ACCOUNT, 'Create User Account');
// return success and user id
- return [ "success" => true, 'id' => $new_user_id ];
+ return [
+ "success" => true,
+ 'id' => $new_user_id ,
+ 'activation' => $activation_code
+ ];
}
diff --git a/html/app/routes/api.php b/html/app/routes/api.php
index 659c25f..ecf15fb 100644
--- a/html/app/routes/api.php
+++ b/html/app/routes/api.php
@@ -1,8 +1,17 @@
<?php
+use app\controllers\Auth;
use app\controllers\api\Common_api;
use app\controllers\api\Doc_api;
+
+/** API CALLS
+ * -----------------------------------------------------------------------------
+ *
+ * these calls return json responses
+ */
+
+
// api: tree of product-categories
Route::add('/api/tree',
function() { Doc_api::tree(); },
@@ -32,33 +41,54 @@ Route::add('/api/([0-9a-zA-Z-_]*)/([0-9]*)',
);
-# // test on the go
-# // find products with large differences on price between stores
-# // ---
-# Route::add('/api/price-diffs', function() {
-# $wtf = Registry::use('database')->runQuery("SELECT sku,
-# max(ProductPrice_OriginalPrice) as MX,
-# min(ProductPrice_OriginalPrice) as MN,
-# ((max(ProductPrice_OriginalPrice)-min(ProductPrice_OriginalPrice))/max(ProductPrice_OriginalPrice)) as Di
-# FROM prices
-# GROUP BY sku
-# ORDER BY Di desc
-# LIMIT 300",
-# []
-# );
-# reply_json([
-# 'success' => true,
-# 'result' => $wtf
-# ]); die();
-# });
+
+/** XML CALLS
+ * -----------------------------------------------------------------------------
+ *
+ * These calls are like `/api`, except...
+ * they return xml/html as part of the responses;
+ *
+ * example: { success: true, message: html }
+ *
+ * Used when an html message needs to be passed in some div
+ *
+ */
+
+
+// user sends a registration form;
+Route::add('/xml/register', function() { $x = Auth::register(); print_r($x); }, 'post');
+
+
+// user sends a confirmation request (alongside with some 'account' token)
+Route::add('/xml/confirm-account', function() { Auth::confirm_account(); } );
+
+
+// user sends a reset password request)
+Route::add('/xml/reset-password', function() { Auth::confirm(); } );
+
+
+
+
+/** TEST CALLS
+ * -----------------------------------------------------------------------------
+ *
+ * direct calls to simple tests
+ *
+ */
+
// route for testing...
// ---
Route::add('/test/([0-9a-zA-Z-_\/]*)', function($test) {
+
+ // TODO:
+ // hide tests from production
+
if (file_exists(TESTS_DIRECTORY . $test .'.php')) {
if (!Benchmark::exist('start')) Benchmark::add_spot('start');
require(TESTS_DIRECTORY . $test .'.php');
} else { echo "Test {$test} not exist";
} die();
+
});
diff --git a/html/app/routes/frontend.php b/html/app/routes/frontend.php
index 4feda62..712de9a 100644
--- a/html/app/routes/frontend.php
+++ b/html/app/routes/frontend.php
@@ -7,7 +7,8 @@ use app\controllers\Classroom_user;
// Home/Welcome
// ---
Route::add('/', function() { // echo 'Welcome!'; });
- header('Location: /eidi-artozacharoplasteioy/psomi-artoskeyasmata', true, 302);
+ Render::view('welcome');
+ // header('Location: /some/default/url', true, 302);
});
@@ -22,6 +23,7 @@ Route::notFound( function() {
Route::add('/login', function() { Render::view('user/login'); });
Route::add('/register', function() { Render::view('user/register'); });
+
Route::add('/login-check', function() {
$user = new Classroom_user();
$user->register_user();
diff --git a/html/app/views/basic.php b/html/app/views/basic.php
deleted file mode 100644
index 39bdf00..0000000
--- a/html/app/views/basic.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php ob_start(); ?><!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>ΣΚΛΑΒΕΝΙΤΗΣ - <?=$page['title']?></title>
-
- <!-- import assets -->
-
- <link rel="preconnect" href="https://fonts.googleapis.com">
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
- <link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@300;400;500;700&display=swap" rel="stylesheet">
-
- <!-- TODO: parse seo data -->
-
-
-</head>
-<body class="homepage" data-plugin-lazyload>
-
- <div class="mainContainer">
-
- <div class="mainLayer"></div>
-
-
- <!-- header -->
- < ?php cache_view('partials/header', []); ? >
- <?php ob_flush(); ?>
-
-
- <!-- main content -->
- <main class="main">
-
- <?php parse_sections( $page['sections'] ); ?>
-
- </main>
- <?php ob_flush(); ?>
-
-
- <!-- footer -->
- < ?php cache_view('partials/footer', [], true) ? >
-
- </div>
-
- <!-- scripts -->
- <?php link_asset('js',
- ['require.files', 'require.slim', 'plugins.min', 'plugins.setup' ]
- ); ?>
-
-</body>
-</html><?php ob_flush(); ?>
diff --git a/html/app/views/components/breadcrumbs.php b/html/app/views/components/breadcrumbs.php
new file mode 100644
index 0000000..471cfb6
--- /dev/null
+++ b/html/app/views/components/breadcrumbs.php
@@ -0,0 +1,30 @@
+<?php
+/** breadcrumbs
+ * -----------------------------------------------------------------------------
+ *
+ * imported variables
+ * ---
+ * @param $id : category_id of last level
+ * @param $title : category title of last level
+ * @param $parents : array of parent nodes
+ * -----------------------------------------------------------------------------
+ */
+?>
+
+<div class="breadcrumb">
+ <!-- home -->
+ <a href="/">Classroom</a>
+
+ <!-- parent nodes -->
+ <?php if ($id != 0) : ?>
+ <?php foreach($parents as $node) : ?>
+ <i class="fas fa-angle-right"></i> <a href="/wiki/category?id=<?=$node['id']?>"><?=$node['title']?></a>
+ <?php endforeach; ?>
+ <?php endif; ?>
+
+ <!-- last (current) node -->
+ <?php if ($id != 0) : ?>
+ <i class="fas fa-angle-right"></i> <a href="/wiki/category?id=<?=$id?>"><?=$title?></a>
+ <?php endif; ?>
+
+</div> \ No newline at end of file
diff --git a/html/app/views/components/header_includes.php b/html/app/views/components/header_includes.php
new file mode 100644
index 0000000..4ee6904
--- /dev/null
+++ b/html/app/views/components/header_includes.php
@@ -0,0 +1,23 @@
+
+<!-- fonts (CDN) -->
+<link rel="preconnect" href="https://fonts.googleapis.com">
+<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400&display=swap" rel="stylesheet">
+
+<!-- fontawesome icons (CDN) -->
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+
+<!-- bootstap (CDN) -->
+<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
+
+<!-- main css -->
+<link href="/assets/css/class.css" rel="stylesheet">
+
+<!-- overides -->
+<link href="/assets/css/overides.css" rel="stylesheet">
+
+<!-- bootstrap javascript (CDN) -->
+<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous"></script>
+
+<!-- jQuery (CDN) -->
+<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js" integrity="sha512-pumBsjNRGGqkPzKHndZMaAG+bir374sORyzM3uulLV14lN5LyykqNk8eEeUlUkB3U0M4FApyaHraT65ihJhDpQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
diff --git a/html/app/views/components/top-bar.php b/html/app/views/components/top-bar.php
new file mode 100644
index 0000000..ed96e35
--- /dev/null
+++ b/html/app/views/components/top-bar.php
@@ -0,0 +1,17 @@
+<div class="top-bar">
+
+ <?php // breadcrumbs
+ ////////////////////////////////////////////////////////////////////////
+ Render::template("components/breadcrumbs", [
+ 'id' => 0,
+ 'title' => '',
+ 'parents' => []
+ ]);
+ ?>
+
+ <?php // User management drop-down
+ ////////////////////////////////////////////////////////////////////////
+ Render::view('components/user-management');
+ ?>
+
+</div><!-- /top-bar --> \ No newline at end of file
diff --git a/html/app/views/components/user-management.php b/html/app/views/components/user-management.php
index dd38396..02a439e 100644
--- a/html/app/views/components/user-management.php
+++ b/html/app/views/components/user-management.php
@@ -1,33 +1,42 @@
<div class="user">
- <div class="btn-group js-visitor">
+ <div class="dropdown js-visitor">
<button type="button" class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
- <i class="fa-regular fa-user"></i>
+ <i class="fa fa-regular fa-user"></i>
Διαχείριση Λογαριασμού
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
- <li><a href="/login">Είσοδος</a></li>
- <li role="separator" class="divider"></li>
- <li><a href="/register">Εγγραφή</a></li>
- <li><a href="/reset-password">Επαναφορά password</a></li>
+ <li><a class="dropdown-item" href="/login">Είσοδος</a></li>
+
+ <li><hr class="dropdown-divider"></li>
+
+ <li><a class="dropdown-item" href="/register">Εγγραφή</a></li>
+ <li><a class="dropdown-item" href="/reset-password">Επαναφορά password</a></li>
</ul>
</div>
- <div class="btn-group js-subscriber">
+ <div class="dropdown js-subscriber">
<button type="button" class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
Διαχείριση Λογαριασμού <span class="caret"></span>
</button>
<ul class="dropdown-menu">
- <li><a href="/profile">Διαχείριση Προφίλ</a></li>
- <li><a href="/courses">Ύλη μαθημάτων</a></li>
- <li><a href="/payments">Πληρωμές</a></li>
- <li role="separator" class="divider"></li>
- <li><a href="/logout">Έξοδος</a></li>
+ <li><a class="dropdown-item" href="/profile">Διαχείριση Προφίλ</a></li>
+ <li><a class="dropdown-item" href="/courses">Ύλη μαθημάτων</a></li>
+ <li><a class="dropdown-item" href="/payments">Πληρωμές</a></li>
+
+ <li><hr class="dropdown-divider"></li>
+
+ <li><a class="dropdown-item" href="/logout">Έξοδος</a></li>
</ul>
</div>
</div>
-
+<script>
+ // default: hide subscriber's menu
+ [].forEach.call(document.querySelectorAll('.js-subscriber'), function (el) {
+ el.style.display = 'none';
+ });
+</script>
diff --git a/html/app/views/error/404.php b/html/app/views/error/404.php
index f594860..2b67e8d 100644
--- a/html/app/views/error/404.php
+++ b/html/app/views/error/404.php
@@ -1,7 +1,7 @@
-<html>
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
<title>404: Not Found</title>
<style>
diff --git a/html/app/views/error/general.php b/html/app/views/error/general.php
index d6649de..84cc4d9 100644
--- a/html/app/views/error/general.php
+++ b/html/app/views/error/general.php
@@ -1,7 +1,7 @@
-<html>
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
<title>404: Not Found</title>
<style>
diff --git a/html/app/views/group.php b/html/app/views/group.php
index fddd3d2..5d5dea0 100644
--- a/html/app/views/group.php
+++ b/html/app/views/group.php
@@ -1,8 +1,3 @@
-<img src="https://cdn.sklavenitis.co.gr/uploads/products/1180106.jpg">
-<!--
-<img src="https://s1.sklavenitis.gr/images/1600x1600/40/files/ProductMedia/Products/1222798/1.jpg" style="max-height:240px;"> -->
-<img src="https://s1.sklavenitis.gr/images/ProductDetail/40/files/ProductMedia/Products/1222798/1.jpg">
-
<section>
<div style="padding: 1em">
diff --git a/html/app/views/user/login.php b/html/app/views/user/login.php
index 2cf3290..4451d52 100644
--- a/html/app/views/user/login.php
+++ b/html/app/views/user/login.php
@@ -1,7 +1,7 @@
-<html>
+<!DOCTYPE html>
+<html lang="en">
<head>
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta charset="utf-8">
<title><?=SITE_TITLE?> - Είσοδος Χρήστη</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -12,6 +12,8 @@
<link href="/assets/css/overides.css" rel="stylesheet">
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous"></script>
+
<style>
html,body{
padding:0; margin:0;
diff --git a/html/app/views/user/new-password.php b/html/app/views/user/new-password.php
index 955cffb..06e7fac 100644
--- a/html/app/views/user/new-password.php
+++ b/html/app/views/user/new-password.php
@@ -1,42 +1,42 @@
-<html>
+<!DOCTYPE html>
+<html lang="en">
<head>
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title><?=SITE_TITLE?> - Επαναφορά κωδικού πρόσβασης</title>
+ <meta charset="utf-8">
+ <title><?=SITE_TITLE?> - Επαναφορά κωδικού πρόσβασης</title>
- <link rel="preconnect" href="https://fonts.googleapis.com">
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
- <link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400&display=swap" rel="stylesheet">
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+ <link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400&display=swap" rel="stylesheet">
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
- <link href="/assets/css/overides.css" rel="stylesheet">
+ <link href="/assets/css/overides.css" rel="stylesheet">
- <style>
- html,body{
- padding:0; margin:0;
- font-size:1.25em;
- color: #037; background: #eee;
- line-height:1.2em;
- }
- h3 {
- font-size: 2em; font-style: normal;
- font-weight: 400;
- color: #05a;
- margin: 0; padding: 5px;
- opacity: 0.27;
- border-bottom: 1px solid #05a;
- }
- .container { display: flex; height: 100vh; align-items:center; }
- .content { position: relative;
- max-width:480px; width: 100%;
- margin: auto auto; padding: 1.5em;
- justify-center: center;
- background: #ddd;
- border-radius: 8px;
- box-shadow: 1px 5px 7px #7777;
- }
- </style>
+ <style>
+ html,body{
+ padding:0; margin:0;
+ font-size:1.25em;
+ color: #037; background: #eee;
+ line-height:1.2em;
+ }
+ h3 {
+ font-size: 2em; font-style: normal;
+ font-weight: 400;
+ color: #05a;
+ margin: 0; padding: 5px;
+ opacity: 0.27;
+ border-bottom: 1px solid #05a;
+ }
+ .container { display: flex; height: 100vh; align-items:center; }
+ .content { position: relative;
+ max-width:480px; width: 100%;
+ margin: auto auto; padding: 1.5em;
+ justify-center: center;
+ background: #ddd;
+ border-radius: 8px;
+ box-shadow: 1px 5px 7px #7777;
+ }
+ </style>
</head>
<body class="classroom">
<div class='container'>
diff --git a/html/app/views/user/register.php b/html/app/views/user/register.php
index 97724a6..591dcb7 100644
--- a/html/app/views/user/register.php
+++ b/html/app/views/user/register.php
@@ -1,75 +1,120 @@
-<html>
+<!DOCTYPE html>
+<html lang="en">
<head>
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title><?=SITE_TITLE?> - Εγγραφή</title>
+ <meta charset="utf-8">
+ <title><?=SITE_TITLE?> - Εγγραφή</title>
- <link rel="preconnect" href="https://fonts.googleapis.com">
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
- <link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400&display=swap" rel="stylesheet">
+ <?php // header includes
+ ////////////////////////////////////////////////////////////////////////
+ Render::view('components/header_includes');
+ ?>
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
-
- <link href="/assets/css/overides.css" rel="stylesheet">
-
- <style>
- html,body{
- padding:0; margin:0;
- font-size:1.25em;
- color: #037; background: #eee;
- line-height:1.2em;
- }
- h3 {
- font-size: 2em; font-style: normal;
- font-weight: 400;
- color: #05a;
- margin: 0; padding: 5px;
- opacity: 0.27;
- border-bottom: 1px solid #05a;
- }
- .container { display: flex; height: 100vh; align-items:center; }
- .content { position: relative;
- max-width:480px; width: 100%;
- margin: auto auto; padding: 1.5em;
- justify-center: center;
- background: #ddd;
- border-radius: 8px;
- box-shadow: 1px 5px 7px #7777;
- }
- </style>
+ <style>
+ html,body{
+ padding:0; margin:0;
+ font-size:1.25em;
+ color: #037; background: #eee;
+ line-height:1.2em;
+ }
+ h3 {
+ font-size: 2em; font-style: normal;
+ font-weight: 400;
+ color: #05a;
+ margin: 0; padding: 5px;
+ opacity: 0.27;
+ border-bottom: 1px solid #05a;
+ }
+ .container { display: flex; height: 100vh; align-items:center; }
+ .content { position: relative;
+ max-width:480px; width: 100%;
+ margin: auto auto; padding: .5em;
+ justify-center: center;
+ font-size: .9em;
+ }
+ .content-form {
+ padding: 1.5em;
+ background: #ddd;
+ border-radius: 8px;
+ box-shadow: 1px 5px 7px #7777;
+ }
+ .content .info { padding: 1.5em; font-size: .92em; }
+ .content .info p { padding: .5em; }
+ .form-label { margin-bottom: .25rem; }
+ </style>
</head>
<body class="classroom">
<div class='container'>
- <div class='content'>
- <h4>Εγγραφή</h4>
- <hr />
- <form method="post" action="/login-check">
- <div>
- <div class="mb-3">
- <label for="name" class="form-label">Όνομα</label>
- <input type="text" class="form-control form-control-sm" name="name" required>
- </div>
- <div class="mb-3">
- <label for="surname" class="form-label">Επίθετο</label>
- <input type="text" class="form-control form-control-sm" name="surname" required>
- </div>
- <div class="mb-3">
- <label for="exampleInputEmail1" class="form-label">Email</label>
- <input type="email" class="form-control form-control-sm" name="email" aria-describedby="emailHelp" rerquired>
- </div>
- <div class="mb-3">
- <label for="exampleInputPassword1" class="form-label">Κωδικός Πρόσβασης</label>
- <input type="password" class="form-control form-control-sm" name="password" required>
- </div>
- <div class="mb-3">
- <label for="exampleInputPassword2" class="form-label">Επιβεβαίωση Κωδικού Πρόσβασης</label>
- <input type="password" class="form-control form-control-sm" name="password2" required>
- </div>
- <br />
- <button type="submit" class="btn btn-primary btn-sm col-12">Εγγραφή</button>
- </div>
- </form>
+ <div class="content">
+ <div class="info">
+ <h4>Classroom: Εγγραφή</h4>
+ </div>
+ <div class='content-form'>
+ <form method="post">
+ <div>
+ <div class="mb-3">
+ <label for="name" class="form-label">Όνομα</label>
+ <input type="text" class="form-control form-control-sm" name="name" required>
+ </div>
+ <div class="mb-3">
+ <label for="surname" class="form-label">Επίθετο</label>
+ <input type="text" class="form-control form-control-sm" name="surname" required>
+ </div>
+ <div class="mb-3">
+ <label for="exampleInputEmail1" class="form-label">Email</label>
+ <input type="email" class="form-control form-control-sm" name="email" aria-describedby="emailHelp" rerquired>
+ </div>
+ <div class="mb-3">
+ <label for="exampleInputPassword1" class="form-label">Κωδικός Πρόσβασης</label>
+ <input type="password" class="form-control form-control-sm" name="password" required>
+ </div>
+ <div class="mb-3">
+ <label for="exampleInputPassword2" class="form-label">Επιβεβαίωση Κωδικού Πρόσβασης</label>
+ <input type="password" class="form-control form-control-sm" name="password2" required>
+ </div>
+ <br />
+ <button type="submit" class="btn btn-primary btn-sm col-12">Εγγραφή</button>
+ </div>
+ </form>
+ </div>
+ <div class="info">
+ <p>Αν έχετε ήδη λογαρισμό <a href="/login">συνδεθείτε</a>.</p>
+ <p>Σε κάθε περίπτωση μπορείτε να επιστρέψετε στην <a href="/">αρχική σελίδα</a>.</p>
+ </div>
</div>
</div>
</body>
+
+<script>
+ // When form is submited
+ // -------------------------------------------------------------------------
+
+ $('.content-form form').submit( event => {
+ event.preventDefault();
+
+ if ($('input[name=password]').val() != $('input[name=password2]').val()) {
+ alert('Τα δυο passrods δεν ταιριάζουν!');
+
+ } else {
+
+ // prepare data to POST
+ var data = {
+ name: $('input[name=name]').val(),
+ surname: $('input[name=surname]').val(),
+ email: $('input[name=email]').val(),
+ password: $('input[name=password]').val()
+ };
+
+ // select action url (add or update)
+ var request = '/xml/register';
+
+ // send POST request
+ $.post(request, data)
+ .done(function( data ) {
+ console.log(data);
+ });
+ }
+
+ });
+</script>
+
</html>
diff --git a/html/app/views/welcome.php b/html/app/views/welcome.php
new file mode 100644
index 0000000..11dd6c6
--- /dev/null
+++ b/html/app/views/welcome.php
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title><?=SITE_TITLE?> - Welcome!</title>
+
+ <?php // header includes
+ ////////////////////////////////////////////////////////////////////////
+ Render::view('components/header_includes');
+ ?>
+
+</head>
+<body class='classroom'>
+
+ <?php // top-bar
+ ////////////////////////////////////////////////////////////////////////
+ Render::view('components/top-bar');
+ ?>
+
+</body>
+</html> \ No newline at end of file
diff --git a/html/assets/css/class.css b/html/assets/css/class.css
index 6acb49e..598f441 100644
--- a/html/assets/css/class.css
+++ b/html/assets/css/class.css
@@ -28,6 +28,7 @@
--class-orange-opaque: #f4792099;
--class-grey-background: #eeedeb;
--class-red: #d13;
+ --light-grey-bgr: #f2f3f8;
}
@@ -41,12 +42,15 @@
justify-content: space-between;
align-items: center;
padding: 10px 14px;
+ border-bottom: 1px solid #ddd;
+ box-shadow: 1px 1px 7px #9997;
+ background: var(--light-grey-bgr);
}
.classroom .top-bar .breadcrumb { margin: 0; padding: 0; background: none; }
-
-.classroom .top-bar .admin .dropdown-menu .fas {
+.classroom .top-bar .fa,
+.classroom .top-bar .fas {
width: 32px;
text-align: center;
}
diff --git a/html/assets/css/overides.css b/html/assets/css/overides.css
index 7c68ad7..a83045c 100644
--- a/html/assets/css/overides.css
+++ b/html/assets/css/overides.css
@@ -1,3 +1,6 @@
+:root {
+ --bs-heading-color: #679;
+}
html, body { font-family: "Roboto Slab", serif; font-weight: 400; }
@@ -5,16 +8,13 @@ html, body { font-family: "Roboto Slab", serif; font-weight: 400; }
.content { text-align: unset; }
-.form-control,
-.btn-default { border: 1px solid #7777; }
+.form-control { border: 1px solid #7777; }
.form-label { font-size: .72em; color: var(--bs-heading-color); }
-
-
/* main.min.css */
.product__img {
/* max-width: 320px; */
@@ -32,8 +32,3 @@ html, body { font-family: "Roboto Slab", serif; font-weight: 400; }
/* color: #4d4d4d; */
color: #bbb7;
}
-
-
-:root {
- --bs-heading-color: #679;
-}