Sfoglia il codice sorgente

Merge branch 'Teams'

Iñigo Valentin 6 anni fa
parent
commit
a6147f2bf4

+ 17 - 3
application/Constant.php

@@ -1,6 +1,7 @@
 <?php
 
     $DIFFICULTY = [
+        "EASY" => 0,
         "NORMAL" => 1,
         "HARD" => 2,
         "HELL" => 3,
@@ -78,9 +79,9 @@
 
     $SCENARIO = [
         'GAREN_FOREST' => 1,
-        'MT._SIZ' => 2,
+        'MT_SIZ' => 2,
         'KABIR_RUINS' => 3,
-        'MT._WHITE_RAGON' => 4,
+        'MT_WHITE_RAGON' => 4,
         'TELAIN_FOREST' => 5,
         'HYDENI_RUINS' => 6,
         'TAMOR_DESERT' => 7,
@@ -108,7 +109,7 @@
         'HALL_OF_LIGHT' => 7001,
         'GIANTS_KEEP' => 8001,
         'DRAGONS_LAIR' => 9001,
-
+        // TODO: Lumel
     ];
 
     $ELEMENTAL_RIFT_DUNGEON = [
@@ -127,6 +128,19 @@
         'LEVEL_5' => 5,
     ];
 
+    $LABYRINTH_STAGES = [
+        'TARTARUS' => 1,
+        'KOTTOS' => 2,
+        'LEOS' => 3,
+        'AQUILES' => 4,
+        'NORMAL' => 5,
+        'RESCUE' => 6,
+        'EXPLODE' => 7,
+        'COOL_TIME' => 8,
+        'SPEED_LIMIT' => 9,
+        'TIME_LIMIT' => 10
+    ];
+
     $BUILDING = [
         'SUMMONERS_TOWER' => 1,
         'SUMMONHENGE' => 2,

+ 10 - 4
application/Controller.php

@@ -50,6 +50,12 @@
                     case "LOGIN":
                         require_once($path["action"] . "login.php");
                         action($db);
+                        return;
+                        break;
+                    case "NEW_TEAM":
+                        require_once($path["action"] . "new_team.php");
+                        action($db);
+                        return;
                         break;
                     default:
                         require_once($path["page"] . "Error_Page.php");
@@ -61,7 +67,6 @@
             // TODO: Validate private/public user with cookie and redirect
             $UID = $uid;
             if (preg_match("/\d{7}/", $UID)){
-error_log('1');
                 $q = $db->query("SELECT count(uid) AS c FROM player WHERE uid = $UID;");
                 $r = $q->fetchArray(SQLITE3_ASSOC);
                 if ($r["c"] == 0){
@@ -72,15 +77,12 @@ error_log('1');
                 }
             }
             else{
-error_log('2');
                 if ($_SESSION['session'] == true && isset($_SESSION['uid'])){
-error_log('2.1');
                     $UID = $_SESSION['uid'];
                     header("Location: /$UID" . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH));
                     return;
                 }
                 else{
-error_log('2.2');
                     require_once($path["page"] . "Landing_Page.php");
                     $page = new Landing_Page($db);
                     require_once($page->view);
@@ -110,6 +112,10 @@ error_log('2.2');
                     require_once($path["page"] . "Runs_Page.php");
                     $page = new Runs_Page($db);
                 }
+                elseif (strtoupper($pars[0]) == "TEAMS"){
+                    require_once($path["page"] . "Teams_Page.php");
+                    $page = new Teams_Page($db);
+                }
                 elseif (strtoupper($pars[0]) == "MONSTERS"){
                     if (count($pars) == 1){
                         require_once($path["page"] . "Monsters_Page.php");

+ 6 - 1
application/Filter.php

@@ -2,7 +2,7 @@
 
     global $QUALITY;
     global $RUNE_STAT;
-    
+
     $a = "VARIALEA";
 
     $FILTER_CATALOG = [
@@ -143,4 +143,9 @@
         "helper" => false,
         "number" => 20,
     ];
+    
+    $FILTER_TEAM = [
+        "name" => "",
+        "area" => null
+    ];
 ?>

+ 170 - 0
application/action/new_team.php

@@ -0,0 +1,170 @@
+<?php
+    function action($db = null){
+        global $AREA_TYPE;
+        global $DIFFICULTY;
+        global $SCENARIO;
+        global $DUNGEON;
+        global $ELEMENTAL_RIFT_DUNGEON;
+        global $LABYRINTH_STAGES;
+        global $UID;
+
+        //$player = SQLite3::escapeString($_POST["uid"]);
+        $player = filter_input(INPUT_POST, 'uid');
+        $area_type = filter_input(INPUT_POST, 'area_type');
+        $area = filter_input(INPUT_POST, 'area');
+        $stage = filter_input(INPUT_POST, 'stage');
+        error_log("STAGE1: " . $stage);
+        $difficulty = filter_input(INPUT_POST, 'difficulty');
+        $ids = filter_input(INPUT_POST, 'ids');
+        $name = filter_input(INPUT_POST, 'name');
+        $description = filter_input(INPUT_POST, 'description');
+        $id = preg_split("/[\s,]+/", $ids);
+        $id_count = sizeof($id);
+        if ($name == null || strlen($name) == 0){
+            return -1;
+        }
+        switch ($area_type){
+            case $AREA_TYPE["SCENARIO"]:
+                if ($stage < 0 || $stage > 7){
+                    return -31;
+                }
+                if (!($difficulty == 0 || in_array($difficulty, $DIFFICULTY) || $difficulty == $DIFFICULTY["EASY"])){
+                    return -32;
+                }
+                if ($id_count < 1 || $id_count > 4){
+                    return -33;
+                }
+                if (!in_array($area, $SCENARIO)){
+                    return -34;
+                }
+                break;
+            case $AREA_TYPE["CAIROS_DUNGEON"]:
+                if ($stage < 0 || $stage > 10){
+                    return -35;
+                }
+                $difficulty = null;
+                if ($id_count < 1 || $id_count > 5){
+                    return -36;
+                }
+                if (!in_array($area, $DUNGEON)){
+                    return -37;
+                }
+                break;
+            case $AREA_TYPE["RIFT_DUNGEON"]:
+                $stage = null;
+                $difficulty = null;
+                if ($id_count < 1 || $id_count > 6){
+                    return -39;
+                }
+                if (!in_array($area, $ELEMENTAL_RIFT_DUNGEON)){
+                    return -40;
+                }
+                break;
+            case $AREA_TYPE["RIFT_RAID"]:
+                if ($stage < 0 || $stage > 5){
+                    return -41;
+                }
+                $difficulty = null;
+                if ($id_count < 1 || $id_count > 6){
+                    return -42;
+                }
+                $area = null;
+                break;
+            case $AREA_TYPE["ARENA"]:
+                $area = null;
+                $stage = null;
+                $difficulty = null;
+                break;
+            case $AREA_TYPE["GUILD_WAR"]:
+                $area = null;
+                $stage = null;
+                $difficulty = null;
+                break;
+            case $AREA_TYPE["GUILD_SIEGE"]:
+                $area = null;
+                $stage = null;
+                $difficulty = null;
+                break;
+            case $AREA_TYPE["TARTARUS_LABYRINTH"]:
+                $stage = null;
+                if ($difficulty < 0 || !in_array($difficulty, $DIFFICULTY)){
+                    return -43;
+                }
+                if ($id_count < 1 || $id_count > 5){
+                    return -44;
+                }
+                if (!in_array($area, $LABYRINTH_STAGES)){
+                    return -45;
+                }
+                break;
+            case $AREA_TYPE["TRIAL_OF_ASCENSION"]:
+                if ($difficulty != 0 && $difficulty != $DIFFICULTY["NORMAL"] && $difficulty != $DIFFICULTY["HARD"]){
+                    return -46;
+                }
+                $stage = null;
+                if ($id_count < 1 || $id_count > 5){
+                    return -47;
+                }
+                $area = null;
+                break;
+            case $AREA_TYPE["DIMENSIONAL_HOLE"]:
+                if ($stage < 0 || $stage > 5){
+                    return -48;
+                }
+                $difficulty = null;
+                if ($id_count < 1 || $id_count > 4){
+                    return -49;
+                }
+                if (!in_array($area, $DUNGEON)){
+                    return -50;
+                }
+                break;
+            case $AREA_TYPE["DIMENSIONAL_RIFT"]:
+                if ($difficulty != 0 && $difficulty != $DIFFICULTY["NORMAL"] && $difficulty != $DIFFICULTY["HARD"]){
+                    return -51;
+                }
+                $stage = null;
+                if ($id_count < 1 || $id_count > 5){
+                    return -52;
+                }
+                $area = null;
+                break;
+            default:
+                return -3;
+        }
+        $unique_id = array_unique($id);
+        if ($id_count != sizeof($unique_id)){
+            return -4;
+        }
+        
+        
+        error_log("STAGE2: " . $stage);
+        
+        $s = "SELECT CASE WHEN MAX(id) IS NULL THEN 1 ELSE MAX(id) + 1 END AS id FROM team;";
+        $q = $db->query($s);
+        $r = $q->fetchArray(SQLITE3_ASSOC);
+        $team_id = $r["id"];
+        
+        $statement = $db->prepare('INSERT INTO team (uid, id, name, description, area_type, area, stage, difficulty) VALUES (:uid, :id, :name, :description, :area_type, :area, :stage, :difficulty);');
+        $statement->bindValue(':uid', $player);
+        $statement->bindValue(':id', $team_id);
+        $statement->bindValue(':name', $name);
+        $statement->bindValue(':description', $description);
+        $statement->bindValue(':area_type', $area_type);
+        $statement->bindValue(':area', $area);
+        $statement->bindValue(':stage', $stage);
+        $statement->bindValue(':difficulty', $difficulty);
+        $res = $statement->execute();
+        
+        if (!$res){
+            return -5;
+        }
+        
+        foreach ($id as $i){
+            $s = "INSERT INTO team_unit VALUES ($team_id, $i);";
+            $db->query($s);
+        }
+        
+        return 0;
+    }
+?>

+ 97 - 0
application/entity/Team.php

@@ -0,0 +1,97 @@
+<?php
+
+    require_once($path["entity"] . "K_Area.php");
+    require_once($path["entity"] . "Unit.php");
+
+
+    /**
+     * A Team.
+     *
+     * Represents an object from the table 'unit'.
+     */
+    class Team extends Entity{
+
+        /**
+         * Owner identifier.
+         */
+        public $uid;
+
+        /**
+         * Team identifier.
+         */
+        public $id;
+
+        /**
+         * Team name.
+         */
+        public $name;
+
+        /**
+         * Team description.
+         */
+        public $description;
+
+        /**
+         * List of {@see Unit}s in the team.
+         */
+        public $unit = [];
+
+        /**
+         * Area the team is designed for.
+         */
+        public $area;
+
+        /**
+         * Stage the team is designed for. It can be null.
+         */
+        public $stage;
+
+        /**
+         * Constructor.
+         *
+         * Searches the database and retrieves the information about the
+         * monster, populating it and it's items.
+         *
+         * @param SQLite3 $db Connection to the database.
+         * @param int $id Monster identifier.
+         * @param complete If false, query only monster and k_monster.
+         */
+        public function __construct($db, $id, $complete = true){
+            global $path;
+            parent::__construct($db);
+            $s = "
+              SELECT
+                uid,
+                id,
+                name,
+                description,
+                area_type,
+                area,
+                stage,
+                difficulty
+              FROM team
+              WHERE id = '$id';
+            ";
+            $q = $this->db->query($s);
+            $r = $q->fetchArray(SQLITE3_ASSOC);
+            $this->uid = $r["uid"];
+            $this->id = $r["id"];
+            $this->name = $r["name"];
+            $this->description = $r["description"];
+            $this->area = new K_Area($this->db, $r["area"], $r["area_type"]);
+            $this->stage = $r["stage"];
+            if ($complete){
+                $s = "
+                  SELECT unit
+                  FROM team_unit
+                  WHERE team = '$id';
+                ";
+                $q = $this->db->query($s);
+                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                    array_push($this->unit, new Unit($this->db, $r["unit"], false));
+                }
+            }
+        }
+
+    }
+?>

+ 11 - 1
application/page/Report_Runeupgrade_Page.php

@@ -3,6 +3,16 @@
     require_once($path["page"] . "Page.php");
     require_once($path["entity"] . "Unit.php");
     require_once($path["entity"] . "Rune.php");
+    
+    class Upgrade{
+        private $db;
+        public $unit = null;
+        public $rune = [];
+        
+        public function __construct($db){
+            $this->db = $db;
+        }
+    }
 
     /**
      * Upgradeable runes report page.
@@ -296,7 +306,7 @@
                     break;
             }
             if (strlen($this->filters["monster_name"]) > 0){
-                $s = $s . " AND k_unit.name LIKE = '%" . $this->filters["monster_name"] . "%' ";
+                $s = $s . " AND upper(k_unit.name) LIKE = upper('%" . $this->filters["monster_name"] . "%') ";
             }
             if (!$this->filters["monster_in_storage"]){
                 //$s = $s . " AND unit.in_storage = 0 ";

+ 101 - 0
application/page/Teams_Page.php

@@ -0,0 +1,101 @@
+ <?php
+
+    require_once($path["page"] . "Page.php");
+    require_once($path["entity"] . "Team.php");
+
+    /**
+     * Monster list page.
+     */
+    class Teams_Page extends Page{
+
+        /**
+         * Array of @{see Team}s.
+         */
+        public $teams = [];
+
+        /**
+         * The filters the page can handle.
+         */
+        public $filters;
+
+        /**
+         * List of all units for team creation
+         */
+        public $units = [];
+
+
+        /**
+         * Constructor.
+         *
+         * Retrieves the data and initializes the variables.
+         *
+         * @param SQLite3 $db Connection to the database.
+         */
+        public function __construct($db){
+            global $path;
+            global $root;
+            global $UID;
+            parent::__construct($db);
+            $this->view = $path["view"] . "teams.php";
+            $this->parse_filters();
+            $s = $this->build_query();
+            $q = $this->db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->teams, new Team($db, $r["id"]));
+            }
+            $s = "
+              SELECT id
+              FROM unit
+              WHERE unit.uid = '$UID';
+            ";
+            $q = $this->db->query($s);
+            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
+                array_push($this->units, new Unit($this->db, $r["id"], false));
+            }
+            $this->title = "Teams - SWDB";
+            $this->description = "Teams";
+            $this->canonical = $root . "teams/";
+        }
+
+        /**
+         * Parses the request looking for the selected filters, validates them
+         * and adds them to the $filters array.
+         */
+        private function parse_filters(){
+            global $FILTER_TEAM;
+            global $AREA_TYPE;
+            $this->filters = $FILTER_TEAM;
+            if (isset($_GET["area"]) && in_array($_GET["area"], $AREA_TYPE)){
+                $this->filters["area"] = $_GET["area"];
+            }
+            if (isset($_GET["name"]) && strlen($_GET["name"]) > 0){
+                $this->filters["name"] = SQLite3::escapeString($_GET["name"]);
+            }
+            return;
+        }
+
+        /**
+         * Builds the query to the rune table using the selected or default
+         * filters.
+         *
+         * @return The query to be executed.
+         */
+        private function build_query(){
+            global $ELEMENT;
+            global $UID;
+            $s = "
+              SELECT id
+              FROM team
+              WHERE uid = '$UID'
+            ";
+            if (in_array($this->filters["area"], $ELEMENT)){
+                $s = $s . " AND area  = '" . strtoupper($this->filters["area"]) . "') ";
+            }
+            if ($this->filters["name"] != ""){
+                $s = $s . " AND upper(name) LIKE '%" . strtoupper($this->filters["name"]) . "%' ";
+            }
+            return $s;
+        }
+
+    }
+?>

+ 34 - 0
application/view/inc/filter_teams.php

@@ -0,0 +1,34 @@
+<?php
+    global $AREA_TYPE;
+?>
+<form action='/<?=$UID?>/teams/' method='get'  id='filter_monsters' class='filter'>
+    <table>
+        <tr>
+            <td class='filter' colspan='2'>
+                <span>Name:</span>
+                <input type='text' name='name' id='filter_name' value='<?=$page->filters["name"]?>'/>
+            </td>
+            <td>
+                <span>Area:</span>
+                <select name='area'>
+                    <option value=''> <option>
+                    <option value='<?=$AREA_TYPE["SCENARIO"]?>'>Scenario</option>
+                    <option value='<?=$AREA_TYPE["CAIROS_DUNGEON"]?>'>Cairos Dungeon</option>
+                    <option value='<?=$AREA_TYPE["RIFT_DUNGEON"]?>'>Rift Dungeon</option>
+                    <option value='<?=$AREA_TYPE["RIFT_RAID"]?>'>Rift Raid</option>
+                    <option value='<?=$AREA_TYPE["DIMENSIONAL_HOLE"]?>'>Dimensional Hole></option>
+                    <option value='<?=$AREA_TYPE["AREAN"]?>'>Arena</option>
+                    <option value='<?=$AREA_TYPE["GUILD_WAR"]?>'>Guild War</option>
+                    <option value='<?=$AREA_TYPE["GUILD_SIEGE"]?>'>Guild Siege</option>
+                    <option value='<?=$AREA_TYPE["TARTARUS_LABYRINTH"]?>'>Tartarus Labyrinth</option>
+                    <option value='<?=$AREA_TYPE["TRIAL_OF_ASCENSION"]?>'>Trial of Ascension</option>
+                    <option value='<?=$AREA_TYPE["WORLD_BOSS"]?>'>World Boss</option>
+                    <option value='<?=$AREA_TYPE["DIMENSIONAL_RIFT"]?>'>Dimensinal Rift</option>
+                </select>
+            </td>
+        </tr>
+    </table>
+    <div id='filter_apply'>
+        <input type='submit' value='Apply'/>
+    </div>
+</form>

+ 3 - 0
application/view/inc/header.php

@@ -33,6 +33,9 @@
             <a href='/<?=$UID?>/runs/'>
                 Runs
             </a>
+            <a href='/<?=$UID?>/teams/'>
+                Teams
+            </a>
             <a href='/<?=$UID?>/report/'>
                 Reports
             </a>

+ 689 - 0
application/view/teams.php

@@ -0,0 +1,689 @@
+<?php
+    global $AREA_TYPE;
+    global $SCENARIO;
+    global $DUNGEON;
+    global $LABYRINTH_STAGES;
+    global $DIFFICULTY;
+    global $ELEMENTAL_RIFT_DUNGEON;
+    global $UID;
+?>
+<!DOCTYPE html>
+<html lang='en'>
+    <head>
+        <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
+        <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
+        <title><?=$page->title?></title>
+        <link rel='shortcut icon' href='<?=$page->favicon?>'/>
+        <!-- CSS files -->
+        <link rel='stylesheet' type='text/css' href='<?=$path["css"]?>ui.css'/>
+        <link rel='stylesheet' type='text/css' href='<?=$path["css"]?>teams.css'/>
+        <link rel='stylesheet' type='text/css' href='<?=$path["css"]?>filters.css'/>
+        <!-- Script files -->
+        <script src="<?=$path["js"]?>ui.js"></script>
+        <script src="<?=$path["js"]?>teams.js"></script>
+        <!-- Meta tags -->
+        <link rel='canonical' href='<?=$page->canonical?>'/>
+        <link rel='author' href='<?=$page->author?>'/>
+        <link rel='publisher' href='<?=$page->author?>'/>
+        <meta name='description' content='<?=$page->description?>'/>
+        <meta property='og:title' content='<?=$page->title?>'/>
+        <meta property='og:url' content='<?=$page->canonical?>'/>
+        <meta property='og:description' content='<?=$page->description?>'/>
+        <meta property='og:image' content='<?=$page->icon?>'/>
+        <meta property='og:site_name' content='<?=$page->name?>'/>
+        <meta property='og:type' content='website'/>
+        <meta property='og:locale' content='en'/>
+        <meta name='twitter:card' content='summary'/>
+        <meta name='twitter:title' content='<?=$page->title?>'/>
+        <meta name='twitter:description' content='<?=$page->description?>'/>
+        <meta name='twitter:image' content='<?=$page->icon?>'/>
+        <meta name='twitter:url' content='<?=$page->canonical?>'/>
+        <meta name='robots' content='index follow'/>
+        <script>
+            units = [];
+            max_units = 0;
+            selected_units = 0;
+            selected_ids = [];
+<?php
+            foreach ($page->units as $unit){
+?>
+                units.push(
+                    {
+                        id: <?=$unit->id?>,
+                        name: "<?=$unit->title?>",
+                        stars: <?=$unit->stars?>,
+                        level: <?=$unit->level?>,
+                        image: '<?=$unit->unit->get_image()?>',
+                        awakens_from: '<?=$unit->unit->awakens_from?>',
+                        awakens_to: '<?=$unit->unit->awakens_to?>',
+                        element: '<?=$unit->unit->element_name?>'
+                    }
+                );
+<?php
+            }
+?>
+            /**
+             * Shows or hiddes the new team panel.
+             * 
+             * @param show True to show, false to hide.
+             */
+            function showNewTeam(show){
+                if (show === true){
+                    document.getElementById('new_team').style.display = 'block';
+                }
+                else{
+                    document.getElementById('new_team').style.display = 'none';
+                }
+            }
+
+            function saveTeam(){
+                if (selected_units > max_units){
+                    alert('Too many units selected.');
+                    return;
+                }
+                var name = document.getElementById('new_team_name').value;
+                var description = document.getElementById('new_team_description').value;
+                var area_type = document.getElementById('new_area_type').options[document.getElementById('new_area_type').selectedIndex].value;
+                var area = null;
+                var difficulty = null;
+                var stage = null;
+                switch (area_type){
+                    case '<?=$AREA_TYPE["SCENARIO"]?>':
+                        area = document.getElementById('new_area_scenario').options[document.getElementById('new_area_scenario').selectedIndex].value;
+                        difficulty = document.getElementById('new_area_difficulty').options[document.getElementById('new_area_difficulty').selectedIndex].value;
+                        stage = document.getElementById('new_area_stage').options[document.getElementById('new_area_stage').selectedIndex].value;
+                        break;
+                    case '<?=$AREA_TYPE["CAIROS_DUNGEON"]?>':
+                        area = document.getElementById('new_area_cairos_dungeon').options[document.getElementById('new_area_cairos_dungeon').selectedIndex].value;
+                        stage = document.getElementById('new_area_stage').options[document.getElementById('new_area_stage').selectedIndex].value;
+                        break;
+                    case '<?=$AREA_TYPE["RIFT_DUNGEON"]?>':
+                        area = document.getElementById('new_area_rift_dungeon').options[document.getElementById('new_area_rift_dungeon').selectedIndex].value;
+                        break;
+                    case '<?=$AREA_TYPE["RIFT_RAID"]?>':
+                        area = document.getElementById('new_area_rift_raid').options[document.getElementById('new_area_rift_raid').selectedIndex].value;
+                        stage = document.getElementById('new_area_stage').options[document.getElementById('new_area_stage').selectedIndex].value;
+                        break;
+                    case '<?=$AREA_TYPE["ARENA"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["GUILD_WAR"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["GUILD_SIEGE"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["TARTARUS_LABYRINTH"]?>':
+                        difficulty = document.getElementById('new_area_difficulty').options[document.getElementById('new_area_difficulty').selectedIndex].value;
+                        stage = document.getElementById('new_area_stage').options[document.getElementById('new_area_stage').selectedIndex].value;
+                        break;
+                    case '<?=$AREA_TYPE["TRIAL_OF_ASCENSION"]?>':
+                        difficulty = document.getElementById('new_area_difficulty').options[document.getElementById('new_area_difficulty').selectedIndex].value;
+                        break;
+                    case '<?=$AREA_TYPE["DIMENSIONAL_HOLE"]?>':
+                        area = document.getElementById('new_area_dimensional_hole').options[document.getElementById('new_area_dimensional_hole').selectedIndex].value;
+                        stage = document.getElementById('new_area_stage').options[document.getElementById('new_area_stage').selectedIndex].value;
+                        break;
+                    case '<?=$AREA_TYPE["DIMENSIONAL_RIFT"]?>':
+                        difficulty = document.getElementById('new_area_difficulty').options[document.getElementById('new_area_difficulty').selectedIndex].value;
+                        break;
+                    default:
+                        alert('Unknown Area');
+                        return;
+                }
+                if (!Number.isInteger(parseInt(area))){
+                    area = 0;
+                }
+                if (!Number.isInteger(parseInt(stage))){
+                    stage = 0;
+                }
+                if (!Number.isInteger(parseInt(difficulty))){
+                    difficulty = 0;
+                }
+
+                var ids = selected_ids.join(',');
+                var xhttp = new XMLHttpRequest();
+                xhttp.onreadystatechange = function() {
+                    if (this.readyState == 4 && this.status == 200) {
+                        alert("200");
+                        //location.reload(); 
+                    }
+                };
+                xhttp.open("POST", "/action/new_team/", true);
+                xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+                console.log('uid=<?=$UID?>&ids=' + ids + '&area_type=' + area_type + '&area=' + area + '&difficulty=' + difficulty + '&stage=' + stage + '&name=' + encodeURI(name) + '&description=' + encodeURI(description));
+                xhttp.send('uid=<?=$UID?>&ids=' + ids + '&area_type=' + area_type + '&area=' + area + '&difficulty=' + difficulty + '&stage=' + stage + '&name=' + encodeURI(name) + '&description=' + encodeURI(description));
+
+            }
+
+            /**
+             * Searches a unit with the pattern entered in the 'new_unit_id'
+             * field. Shows a clickable list of matching units.
+             */
+            function searchUnit(){
+                key = document.getElementById('new_unit_id').value;
+                var autocomplete = document.getElementById('new_unit_autocomplete');
+                while (autocomplete.firstChild) {
+                    autocomplete.removeChild(autocomplete.firstChild);
+                }
+                if (key.length == 0){
+                    autocomplete.style.display = 'none';
+                }
+                for (var i = 0; i < units.length; i++) {
+                    if (units[i].name.toUpperCase().includes(key.toUpperCase())){
+                        autocomplete.style.display = 'block';
+                        var line = document.createElement('div');
+                        var img = document.createElement('img');
+                        img.setAttribute('src', units[i].image);
+                        var nam = document.createElement('span');
+                        var tex = document.createTextNode(units[i].name + '(' + units[i].stars + '*, Lv. ' + units[i].level + ')');
+                        nam.appendChild(tex);
+                        line.appendChild(img);
+                        line.appendChild(nam);
+                        sid = units[i].id;
+                        line.setAttribute('onclick', 'selectUnit(' + sid + ');');
+                        autocomplete.appendChild(line);
+                    }
+                }
+            }
+
+            /**
+             * Selects a unit from the list and adds it to the new team.
+             * The search list is hidden afterwards.
+             *
+             * @param id Unit id.
+             */
+            function selectUnit(id){
+                var name = null;
+                var stars = null;
+                var level = null;
+                var image = null;
+                var element = null;
+                for (var i = 0; i < units.length; i ++) {
+                    if (units[i].id == id){
+                        name = units[i].name;
+                        stars = units[i].stars;
+                        level = units[i].level;
+                        image = units[i].image;
+                        element = units[i].element;
+                        break;
+                    }
+                }
+                if (name != null){
+                    var monsterPanel = document.createElement('div');
+                    monsterPanel.setAttribute('class', 'monster_panel');
+                    var monsterStars = document.createElement('span');
+                    monsterStars.setAttribute('class', 'stars');
+                    for (var i = 0; i < stars; i ++){
+                        var star = document.createElement('img');
+                        // TODO: Handle star color.
+                        star.setAttribute('class', 'star star_purple');
+                        star.setAttribute('src', '<?=$path["img"]["icon"]?>star.png');
+                        monsterStars.appendChild(star);
+                    }
+                    var monsterImage = document.createElement('img');
+                    monsterImage.setAttribute('class', 'monster border_' + element);
+                    monsterImage.setAttribute('src', image);
+                    var monsterLevel = document.createElement('span');
+                    monsterLevel.setAttribute('class', 'level');
+                    monsterLevel.appendChild(document.createTextNode(level));
+                    monsterPanel.appendChild(monsterStars);
+                    monsterPanel.appendChild(monsterImage);
+                    monsterPanel.appendChild(monsterLevel);
+                    var teamPanel = document.getElementById('new_team_units');
+                    teamPanel.appendChild(monsterPanel);
+                    // Hide the selector
+                    var autocomplete = document.getElementById('new_unit_autocomplete');
+                    while (autocomplete.firstChild) {
+                        autocomplete.removeChild(autocomplete.firstChild);
+                    }
+                    autocomplete.style.display = 'none';
+                    document.getElementById('new_unit_id').value = '';
+                    selected_units ++;
+                    if (selected_units >= max_units){
+                        document.getElementById('new_unit').style.display = 'none';
+                    }
+                    else{
+                        document.getElementById('new_unit').style.display = 'block';
+                    }
+                    selected_ids.push(id);
+                }
+            }
+
+            /**
+             * Deletes a unit from the new team form.
+             * 
+             * @param id Unit id.
+             */
+            function deleteUnit(id){
+            }
+
+            /**
+             * Shows the stage selector in the new team panel.
+             * 
+             * @param total The number of stages to show.
+             */
+            function populateStage(total){
+                var sel = document.getElementById('new_area_stage');
+                while (sel.firstChild) {
+                    sel.removeChild(sel.firstChild);
+                }
+                var opt;
+                var att;
+                // Empty
+                opt = document.createElement('option');
+                tex = document.createTextNode('');
+                opt.appendChild(tex);
+                sel.appendChild(opt);
+                for (var i = 1; i <= total; i ++){
+                    opt = document.createElement('option');
+                    tex = document.createTextNode('Stage ' + i);
+                    att = document.createAttribute('value');
+                    att.value = i;
+                    opt.setAttributeNode(att);
+                    opt.appendChild(tex);
+                    sel.appendChild(opt);
+                }
+            }
+
+            /**
+             * Shows the difficulty selector in the new team panel.
+             * 
+             * @param labyrinth Indicates if the area type is the Tartarus
+             *        labyrinth. If so, it includes 'Easy'.
+             * @param toa Indicates if the area type is the Tower of
+             *        Ascension. If so, it excludes 'Hell'.
+             */
+            function populateDifficulty(labyrinth = false, toa = false){
+                var sel = document.getElementById('new_area_difficulty');
+                while (sel.firstChild) {
+                    sel.removeChild(sel.firstChild);
+                }
+                var opt;
+                var att;
+                var tex;
+                // Empty
+                opt = document.createElement('option');
+                tex = document.createTextNode('');
+                opt.appendChild(tex);
+                sel.appendChild(opt);
+                // Easy (Labyrinth only)
+                if (labyrinth){
+                    opt = document.createElement('option');
+                    tex = document.createTextNode('Easy difficulty');
+                    att = document.createAttribute('value');
+                    att.value = '<?=$DIFFICULTY["EASY"]?>';
+                    opt.setAttributeNode(att);
+                    opt.appendChild(tex);
+                    sel.appendChild(opt);
+                }
+                // Normal
+                opt = document.createElement('option');
+                tex = document.createTextNode('Normal difficulty');
+                att = document.createAttribute('value');
+                att.value = '<?=$DIFFICULTY["NORMAL"]?>';
+                opt.setAttributeNode(att);
+                opt.appendChild(tex);
+                sel.appendChild(opt);
+                // Hard
+                opt = document.createElement('option');
+                tex = document.createTextNode('Hard difficulty');
+                att = document.createAttribute('value');
+                att.value = '<?=$DIFFICULTY["HARD"]?>';
+                opt.setAttributeNode(att);
+                opt.appendChild(tex);
+                sel.appendChild(opt);
+                // Hell
+                if (!toa){
+                    opt = document.createElement('option');
+                    tex = document.createTextNode('Hell difficulty');
+                    att = document.createAttribute('value');
+                    att.value = '<?=$DIFFICULTY["HELL"]?>';
+                    opt.setAttributeNode(att);
+                    opt.appendChild(tex);
+                    sel.appendChild(opt);
+                }
+            }
+
+            /**
+             * Shows the appropiate area selector when the area type is
+             * selected in the new team panel.
+             */
+            function selectNewAreaType(){
+                var type = document.getElementById('new_area_type').options[document.getElementById('new_area_type').selectedIndex].value;
+                document.getElementById('new_area_scenario').style.display = 'none';
+                document.getElementById('new_area_scenario').selectedIndex = 0;
+                document.getElementById('new_area_cairos_dungeon').style.display = 'none';
+                document.getElementById('new_area_cairos_dungeon').selectedIndex = 0;
+                document.getElementById('new_area_rift_dungeon').style.display = 'none';
+                document.getElementById('new_area_rift_dungeon').selectedIndex = 0;
+                document.getElementById('new_area_tartarus_labyrinth').style.display = 'none';
+                document.getElementById('new_area_tartarus_labyrinth').selectedIndex = 0;
+                document.getElementById('new_area_dimensional_hole').style.display = 'none';
+                document.getElementById('new_area_dimensional_hole').selectedIndex = 0;
+                document.getElementById('new_area_difficulty').style.display = 'none';
+                document.getElementById('new_area_difficulty').selectedIndex = 0;
+                document.getElementById('new_area_stage').style.display = 'none';
+                document.getElementById('new_area_stage').selectedIndex = 0;
+                switch (type){
+                    case '<?=$AREA_TYPE["SCENARIO"]?>':
+                        document.getElementById('new_area_scenario').style.display = 'inline';
+                        max_units = 4;
+                        break;
+                    case '<?=$AREA_TYPE["CAIROS_DUNGEON"]?>':
+                        document.getElementById('new_area_cairos_dungeon').style.display = 'inline';
+                        max_units = 5;
+                        break;
+                    case '<?=$AREA_TYPE["RIFT_DUNGEON"]?>':
+                        document.getElementById('new_area_rift_dungeon').style.display = 'inline';
+                        max_units = 6;
+                        break;
+                    case '<?=$AREA_TYPE["RIFT_RAID"]?>':
+                        document.getElementById('new_area_rift_raid').style.display = 'inline';
+                        max_units = 6
+                        break;
+                    case '<?=$AREA_TYPE["ARENA"]?>':
+                        max_units = 4;
+                        //document.getElementById('new_area_arena').style.display = 'inline';
+                        break;
+                    case '<?=$AREA_TYPE["GUILD_WAR"]?>':
+                        max_units = 3;
+                        document.getElementById('new_area_guild_war').style.display = 'inline';
+                        break;
+                    case '<?=$AREA_TYPE["GUILD_SIEGE"]?>':
+                        max_units = 3;
+                        document.getElementById('new_area_guild_siege').style.display = 'inline';
+                        break;
+                    case '<?=$AREA_TYPE["TARTARUS_LABYRINTH"]?>':
+                        max_units = 5;
+                        document.getElementById('new_area_tartarus_labyrinth').style.display = 'inline';
+                        break;
+                    case '<?=$AREA_TYPE["TRIAL_OF_ASCENSION"]?>':
+                        max_units = 5;
+                        //document.getElementById('new_area_trial_of_ascension').style.display = 'inline';
+                        break;
+                    case '<?=$AREA_TYPE["WORLD_BOSS"]?>':
+                        //max_units = 5;
+                        //document.getElementById('new_area_world_boss').style.display = 'inline';
+                        break;
+                    case '<?=$AREA_TYPE["DIMENSIONAL_HOLE"]?>':
+                        max_units = 4;
+                        document.getElementById('new_area_dimensional_hole').style.display = 'inline';
+                        break;
+                    case '<?=$AREA_TYPE["DIMENSIONAL_RIFT"]?>':
+                        max_units = 5;
+                        //document.getElementById('new_area_dimensional_rift').style.display = 'inline';
+                        break;
+                }
+                if (selected_units >= max_units || type == ''){
+                    document.getElementById('new_unit').style.display = 'none';
+                }
+                else{
+                    document.getElementById('new_unit').style.display = 'block';
+                }
+            }
+
+            /**
+             * Populates the difficulty and stage selectors when an area is
+             * selected in the new team panel.
+             */
+            function selectNewArea(){
+                var type = document.getElementById('new_area_type').options[document.getElementById('new_area_type').selectedIndex].value;
+                document.getElementById('new_area_stage').selectedIndex = 0;
+                document.getElementById('new_area_difficulty').selectedIndex = 0;
+                document.getElementById('new_area_stage').style.display = 'none';
+                document.getElementById('new_area_difficulty').style.display = 'none';
+                switch (type){
+                    case '<?=$AREA_TYPE["SCENARIO"]?>':
+                        document.getElementById('new_area_stage').style.display = 'inline';
+                        document.getElementById('new_area_difficulty').style.display = 'inline';
+                        populateStage(7);
+                        populateDifficulty();
+                        break;
+                    case '<?=$AREA_TYPE["CAIROS_DUNGEON"]?>':
+                        document.getElementById('new_area_stage').style.display = 'inline';
+                        populateStage(10);
+                        populateDifficulty();
+                        break;
+                    case '<?=$AREA_TYPE["RIFT_DUNGEON"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["RIFT_RAID"]?>':
+                        document.getElementById('new_area_stage').style.display = 'inline';
+                        populateStage(5);
+                        break;
+                    case '<?=$AREA_TYPE["ARENA"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["GUILD_WAR"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["GUILD_SIEGE"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["TARTARUS_LABYRINTH"]?>':
+                        document.getElementById('new_area_difficulty').style.display = 'inline';
+                        populateDifficulty(true, false);
+                        break;
+                    case '<?=$AREA_TYPE["TRIAL_OF_ASCENSION"]?>':
+                        document.getElementById('new_area_difficulty').style.display = 'inline';
+                        populateDifficulty(false, true);
+                        break;
+                    case '<?=$AREA_TYPE["WORLD_BOSS"]?>':
+                        break;
+                    case '<?=$AREA_TYPE["DIMENSIONAL_HOLE"]?>':
+                        document.getElementById('new_area_stage').style.display = 'inline';
+                        populateStage(5);
+                        break;
+                    case '<?=$AREA_TYPE["DIMENSIONAL_RIFT"]?>':
+                        break;
+                }
+            }
+        </script>
+    </head>
+    <body>
+<?php
+        include __DIR__ . "/inc/header.php";
+?>
+            <section class='filters'>
+                <h2>
+                    Team filters
+                </h2>
+<?php
+                $filters = $page->filters;
+                include __DIR__ . "/inc/filter_team.php";
+?>
+            </section> <!-- #filters -->
+            <section class='list'>
+                <h2>
+                    Teams
+                </h2>
+                <article>
+                    <table id='teams'>
+                        <tr>
+                            <th>
+                                Team
+                            </th>
+                            <th>
+                                Description
+                            </th>
+                            <th>
+                                Units
+                            </th>
+                        </tr>
+<?php
+                        $odd = "odd";
+                        foreach ($page->teams as $team){
+?>
+                            <tr>
+                                <td class='team <?=$odd?>'>
+                                    <h4>
+                                        <?=$team->name?>
+                                    </h4>
+<?php
+                                    $area = $team->area->name;
+                                    if (intval($team->stage) > 0){
+                                        $area = $area . " - " . $team->stage;
+                                    }
+?>
+                                    <h5>
+                                        <?=$area?>
+                                    </h5>
+                                </td>
+                                <td class='description <?=$odd?>'>
+                                    <?=$team->description?>
+                                </td>
+                                <td class='units <?=$odd?>'>
+<?php
+                                    foreach ($team->unit as $unit){
+?>
+                                        <a href='/<?=$UID?>/monsters/<?=$unit->id?>'>
+                                            <div class='monster_panel'>
+                                                <?=html_unit_panel($unit)?>
+                                            </div>
+                                        </a>
+<?php
+                                    }
+?>
+                                </td>
+                            </tr>
+<?php
+                            if ($odd == ""){
+                                $odd = "odd";
+                            }
+                            else{
+                                $odd = "";
+                            }
+                        }
+?>
+                    </table>
+                    <input type='button' onClick='showNewTeam(true);' value='New Team'/>
+                </article>
+            </section> <!-- .list -->
+
+<?php
+        include __DIR__ . "/inc/footer.php";
+?>
+        <section id='new_team' class='content'>
+            <h2>
+                New team
+            </h2>
+            <article>
+                <table>
+                    <tr>
+                        <td class='new_title'>
+                            Area
+                        </td>
+                        <td class='new_values'>
+                            <select id='new_area_type' name='new_area_type' onChange='selectNewAreaType();'>
+                                <option value=''> </option>
+                                <option value='<?=$AREA_TYPE["SCENARIO"]?>'>Scenario</option>
+                                <option value='<?=$AREA_TYPE["CAIROS_DUNGEON"]?>'>Cairos Dungeon</option>
+                                <option value='<?=$AREA_TYPE["RIFT_DUNGEON"]?>'>Rift Dungeon</option>
+                                <option value='<?=$AREA_TYPE["RIFT_RAID"]?>'>Rift Raid</option>
+                                <option value='<?=$AREA_TYPE["DIMENSIONAL_HOLE"]?>'>Dimensional Hole</option>
+                                <option value='<?=$AREA_TYPE["ARENA"]?>'>Arena</option>
+                                <option value='<?=$AREA_TYPE["GUILD_WAR"]?>'>Guild War</option>
+                                <option value='<?=$AREA_TYPE["GUILD_SIEGE"]?>'>Guild Siege</option>
+                                <option value='<?=$AREA_TYPE["TARTARUS_LABYRINTH"]?>'>Tartarus Labyrinth</option>
+                                <option value='<?=$AREA_TYPE["TRIAL_OF_ASCENSION"]?>'>Trial of Ascension</option>
+                                <!--<option value='<?=$AREA_TYPE["WORLD_BOSS"]?>'>World Boss</option>-->
+                                <option value='<?=$AREA_TYPE["DIMENSIONAL_RIFT"]?>'>Dimensinal Rift</option>
+                            </select>
+                            <select id='new_area_scenario' class='new_area' onChange='selectNewArea();'>
+                                <option value=''> </option>
+                                <option value='<?=$SCENARIO['GAREN_FOREST']?>'>Garen Forest</option>
+                                <option value='<?=$SCENARIO['MT_SIZ']?>'>Mt. Siz</option>
+                                <option value='<?=$SCENARIO['KABIR_RUINS']?>'>Kabir Ruins</option>
+                                <option value='<?=$SCENARIO['MT_WHITE_RAGON']?>'>Mt. White Ragon</option>
+                                <option value='<?=$SCENARIO['TELAIN_FOREST']?>'>Telain Forest</option>
+                                <option value='<?=$SCENARIO['HYDENI_RUINS']?>'>Hydeni Ruins</option>
+                                <option value='<?=$SCENARIO['TAMOR_DESERT']?>'>Tamor Desert</option>
+                                <option value='<?=$SCENARIO['VROFAGUS_RUINS']?>'>Vrofagus Ruins</option>
+                                <option value='<?=$SCENARIO['FAIMON_VOLCANO']?>'>Faimon Volcano</option>
+                                <option value='<?=$SCENARIO['AIDEN_FOREST']?>'>Aiden Forest</option>
+                                <option value='<?=$SCENARIO['FERUN_CASTLE']?>'>Ferun Castle</option>
+                                <option value='<?=$SCENARIO['MT_RUNAR']?>'>Mt. Runar</option>
+                                <option value='<?=$SCENARIO['CHIRUKA_REMAINS']?>'>Charuca Remains</option>
+                            </select>
+                            <select id='new_area_cairos_dungeon' class='new_area' onChange='selectNewArea();'>
+                                <option value=''> </option>
+                                <option value='<?=$DUNGEON['GIANTS_KEEP']?>'>Giant&#39;s Keep</option>
+                                <option value='<?=$DUNGEON['DRAGONS_LAIR']?>'>Dragon&#39;s Lair</option>
+                                <option value='<?=$DUNGEON['NECROPOLIS']?>'>Necropolis</option>
+                                <option value='<?=$DUNGEON['HALL_OF_MAGIC']?>'>Hall of Magic</option>
+                                <option value='<?=$DUNGEON['HALL_OF_FIRE']?>'>Hall of Fire</option>
+                                <option value='<?=$DUNGEON['HALL_OF_WATER']?>'>Hall of Water</option>
+                                <option value='<?=$DUNGEON['HALL_OF_WIND']?>'>Hall of Wind</option>
+                                <option value='<?=$DUNGEON['HALL_OF_LIGHT']?>'>Hall of Light</option>
+                                <option value='<?=$DUNGEON['HALL_OF_DARK']?>'>Hall of Dark</option>
+                            </select>
+                            <select id='new_area_rift_dungeon' class='new_area' onChange='selectNewArea();'>
+                                <option value=''> </option>
+                                <option value='<?=$ELEMENTAL_RIFT_DUNGEON['FIRE_BEAST']?>'>Fire Beast</option>
+                                <option value='<?=$ELEMENTAL_RIFT_DUNGEON['ICE_BEAST']?>'>Ice Beast</option>
+                                <option value='<?=$ELEMENTAL_RIFT_DUNGEON['WIND_BEAST']?>'>Wind Beast</option>
+                                <option value='<?=$ELEMENTAL_RIFT_DUNGEON['LIGHT_BEAST']?>'>Light Beast</option>
+                                <option value='<?=$ELEMENTAL_RIFT_DUNGEON['DARK_BEAST']?>'>Dark Beast</option>
+                            </select>
+                            <select id='new_area_dimensional_hole' class='new_area' onChange='selectNewArea();'>
+                                <option value=''> </option>
+                                <option value='<?=$DUNGEON['FOREST_OF_ROARING_BEASTS']?>'>Forest or Roaring Beasts</option>
+                                <option value='<?=$DUNGEON['KARZHAN_REMAINS_WARBEAR']?>'>Karzhan Remains (Warbear)</option>
+                                <option value='<?=$DUNGEON['KARZHAN_REMAINS_WARBEAR']?>'>Karzhan Remains (Inugami)</option>
+                                <option value='<?=$DUNGEON['SANCTUARY_OF_DREAMING_FAIRIES']?>'>Sanctuary of Dreaming Fairies</option>
+                                <option value='<?=$DUNGEON['ELLUNIA_REMAINS_FAIRY']?>'>Ellunia Remains (Fairy)</option>
+                                <option value='<?=$DUNGEON['ELLUNIA_REMAINS_PIXIE']?>'>Ellunia Remains (Pixie)</option>
+                                <!-- TODO: Lumel -->
+                            </select>
+                            <select id='new_area_tartarus_labyrinth' class='new_area' onChange='selectNewArea();'>
+                                <option value=''> </option>
+                                <option value='<?=$LABYRINTH_STAGES['TARTARUS']?>'>Tartarus</option>
+                                <option value='<?=$LABYRINTH_STAGES['KOTTOS']?>'>Kottos</option>
+                                <option value='<?=$LABYRINTH_STAGES['LEOS']?>'>Leos</option>
+                                <option value='<?=$LABYRINTH_STAGES['AQUILES']?>'>Aquiles</option>
+                                <option value='<?=$LABYRINTH_STAGES['NORMAL']?>'>Normal Stage</option>
+                                <option value='<?=$LABYRINTH_STAGES['RESCUE']?>'>Rescue Stage</option>
+                                <option value='<?=$LABYRINTH_STAGES['EXPLODE']?>'>Explode Stage</option>
+                                <option value='<?=$LABYRINTH_STAGES['COOL_TIME']?>'>Cool Time Stage</option>
+                                <option value='<?=$LABYRINTH_STAGES['SPEED_LIMIT']?>'>Speed Limit Stage</option>
+                                <option value='<?=$LABYRINTH_STAGES['TIME_LIMIT']?>'>Time Limit Stage</option>
+                                <!-- TODO: Lumel -->
+                            </select>
+                            <select id='new_area_difficulty'>
+                            </select>
+                            <select id='new_area_stage'>
+                            </select>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td class='new_title'>
+                            Name
+                        </td>
+                        <td class='new_values'>
+                            <input type='text' id='new_team_name' name='name'/>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td class='new_title'>
+                            Description
+                        </td>
+                        <td class='new_values'>
+                            <textarea id='new_team_description' name='description'></textarea>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td class='new_title'>
+                            Units:
+                            <div class='new_unit' id='new_unit'>
+                                <input id='new_unit_id' onInput='searchUnit();'/>
+                                <div id='new_unit_autocomplete' class='new_unit_autocomplete'>
+                            </div>
+                        </td>
+                        <td class='new_values'>
+                            <div id='new_team_units'>
+                            </div>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td colspan='2'>
+                            <input type='button' value='Save' onClick='saveTeam();'/>
+                        </td>
+                    </tr>
+            </article>
+        </section>
+    </body>
+</html>

+ 2 - 1
install_data/setup.sql

@@ -478,7 +478,8 @@ CREATE TABLE IF NOT EXISTS team(
     description TEXT,
     area_type INT NOT NULL REFERENCES k_area_type(id),
     area INT REFERENCES k_area(id),
-    stage INT
+    stage INT,
+    difficulty INT REFERENCES k_difficulty(id)
 );
 CREATE TABLE IF NOT EXISTS team_unit(
     team INT NOT NULL REFERENCES team(id),

+ 115 - 0
public/css/teams.css

@@ -0,0 +1,115 @@
+table#teams{
+    width: 100%;
+    border-collapse: collapse;
+    border: 0.1em solid #000000;
+}
+
+table#teams th{
+    border-top: 0.1em solid #000000;
+    border-bottom: 0.1em solid #000000;
+}
+
+table#teams td{
+    border-bottom: 0.1em solid #000000;
+    text-align: left;
+    padding: 0.2em;
+}
+
+table#teams td.odd{
+    background-color: #00000033;
+}
+
+table#teams td.team h4{
+    margin: 0.2em;
+}
+
+table#teams td.team h5{
+    margin: 0.1em;
+}
+
+table#teams td.units div.monster_panel{
+    font-size: 25%;
+    margin-bottom: -2em;
+}
+
+section#new_team{
+    z-index: 1;
+    display: none;
+    position: fixed;
+    width: 80%;
+    height: 70%;
+    margin: 0 10%;
+    top: 10%;
+    filter: drop-shadow(0 0 10em #000000) drop-shadow(0 0 6em #000000);
+}
+
+section#new_team table{
+    width: 100%;
+}
+
+section#new_team table td.new_title{
+    width: 10em;
+    text-align: right;
+    padding-right: 2em;
+}
+
+section#new_team table td.new_values{
+    text-align: left;
+    padding-right: 2em;
+}
+
+section#new_team select.new_area{
+    display: none;
+}
+
+section#new_team select#new_area_difficulty{
+    display: none;
+}
+
+section#new_team select#new_area_stage{
+    display: none;
+}
+
+section#new_team div#new_team_units{
+    background-color: #00000033;
+    border-radius: 0.5em;
+    height: 5em;
+    text-align: left;
+}
+
+section#new_team div#new_team_units div.monster_panel{
+    font-size: 50%;
+}
+
+section#new_team div.new_unit{
+    text-align: right;
+    display: none;
+}
+
+section#new_team div.new_unit div.new_unit_autocomplete{
+    border: 0.1em solid #000000;
+    display: none;
+    border-radius: 0.5em;
+    margin: auto auto auto 1em;
+    position: absolute;
+}
+
+section#new_team div.new_unit div.new_unit_autocomplete div{
+    border: 0.05em solid #000000;
+    margin: 0.1em;
+    text-align: left;
+    cursor: pointer;
+}
+
+section#new_team div.new_unit div.new_unit_autocomplete div span{
+    vertical-align: middle;
+}
+
+section#new_team div.new_unit div.new_unit_autocomplete div img{
+    height: 1.5em;
+    width: 1.5em;
+    vertical-align: middle;
+    border-radius: 0.1em;
+    border: 0.1em solid #000000;
+}
+

+ 1 - 1
public/css/ui.css

@@ -273,7 +273,7 @@ footer table#footer_table td{
         line-height: 0.9em;
     }
 }
-input, select, a.a_button{
+input, select, a.a_button, textarea{
     font-size: 100%;
     text-transform: capitalize;
     font-variant: small-caps;