diff --git a/src/main/webapp/html/my.html b/src/main/webapp/html/my.html
index eb66ac55..7862a829 100644
--- a/src/main/webapp/html/my.html
+++ b/src/main/webapp/html/my.html
@@ -3,9 +3,297 @@
     <title>RPG</title>
     <script src=https://code.jquery.com/jquery-3.6.0.min.js></script>
     <link href="/css/my.css" rel="stylesheet">
+    <style>
+        table, th, td {
+            border: 1px solid black;
+        }
+         #pagesLine button.active {
+             font-weight: bold;
+             color: deeppink;
+         }
+
+        tr.title {
+            font-weight: bold;
+            background: lightskyblue;
+        }
+        div#addAccountForm label {
+            width:100px;
+            float: left;
+        }
+        div#addAccountForm input, div#addAccountForm select {
+            width:200px;
+        }
+    </style>
+
 </head>
 <body>
 <h1>RPG admin panel</h1>
 
+<label for="countPerPage">Count per page:</label>
+<select id="countPerPage">
+    <option>5</option>
+    <option>15</option>
+    <option>20</option>
+</select>
+
+<table id="table">
+    <tbody>
+    <tr class="title">
+        <td style="width: 25px">#</td>
+        <td style="width: 100px">Name</td>
+        <td style="width: 200px">Title</td>
+        <td style="width: 100px">Race</td>
+        <td style="width: 100px">Profession</td>
+        <td style="width: 50px">Level</td>
+        <td style="width: 80px">Birthday</td>
+        <td style="width: 60px">Banned</td>
+        <td>Edit</td>
+        <td>Delete</td>
+    </tr>
+    </tbody>
+</table>
+Pages: <span id="pagesLine"></span>
+
+<hr>
+<h2>Create new account: </h2>
+
+<div id="addAccountForm">
+    <div>
+        <label for="name">Name: </label>
+        <input type="text" name="name" id="name" minlength="1" maxlength="12" required>
+    </div>
+    <div>
+        <label for="title">Title: </label>
+        <input type="text" name="title" id="title" minlength="1" maxlength="30" required>
+    </div>
+    <div>
+        <label for="race">Race: </label>
+        <select name="race" id="race" required>
+            <option>HUMAN</option>
+            <option>DWARF</option>
+            <option>ELF</option>
+            <option>GIANT</option>
+            <option>ORC</option>
+            <option>TROLL</option>
+            <option>HOBBIT</option>
+        </select>
+    </div>
+    <div>
+        <label for="profession">Profession: </label>
+        <select name="profession" id="profession" required>
+            <option>WARRIOR</option>
+            <option>ROGUE</option>
+            <option>SORCERER</option>
+            <option>CLERIC</option>
+            <option>PALADIN</option>
+            <option>NAZGUL</option>
+            <option>WARLOCK</option>
+            <option>DRUID</option>
+        </select>
+    </div>
+    <div>
+        <label for="level">Level: </label>
+        <input type="number" id="level" min="0" max="100" required>
+    </div>
+    <div>
+        <label for="birthday">Birthday: </label>
+        <input type="date" name="birthday" id="birthday" required>
+    </div>
+    <div>
+        <label for="banned">Banned: </label>
+        <select name="banned" id="banned" required>
+            <option>true</option>
+            <option>false</option>
+        </select>
+    </div>
+    <div>
+        <button id="submit">Save</button>
+    </div>
+</div>
+
+<script>
+    function printTableData(pageNumber, pageSize) {
+        let xmlHttp = new XMLHttpRequest();
+        xmlHttp.open("GET", `/rest/players?pageNumber=${pageNumber}&pageSize=${pageSize}`, false);
+        xmlHttp.send(null);
+        let response = JSON.parse(xmlHttp.responseText);
+        $("#table tbody tr:not(.title)").remove();
+        let countPerPage = $("#countPerPage option:selected").val();
+        for (const element of response) {
+            let row = $('<tr>');
+            let deleteButton = $('<img class="delete" src="/img/delete.png">');
+            deleteButton[0].addEventListener('click', (event) => {
+                deleteAccount(element.id);
+                printTableData(currentPageNumber, countPerPage);
+                printPagination();
+            });
+
+            let editButton = $('<img class="edit" src="/img/edit.png">');
+            editButton[0].addEventListener('click', (event) => {
+                switchToEditMode(row[0]);
+                editOnClick(row[0]);
+            });
+
+            let saveButton = $('<img class="save" src="/img/save.png" style="display: none;">');
+            saveButton[0].addEventListener('click', (event) => {
+                let account = prepareAccountFromTableRow(row[0]);
+                saveAccount(element.id, account);
+                printTableData(currentPageNumber, countPerPage);
+                printPagination();
+            });
+
+            $("#table").find('tbody')
+                .append(row
+                    .append($('<td>').append(element.id))
+                    .append($('<td>').append(element.name))
+                    .append($('<td>').append(element.title))
+                    .append($('<td>').append(element.race))
+                    .append($('<td>').append(element.profession))
+                    .append($('<td>').append(element.level))
+                    .append($('<td>').append(new Date(element.birthday).toLocaleDateString("en-US")))
+                    .append($('<td>').append(element.banned.toString()))
+                    .append($('<td>').append(editButton).append(saveButton))
+                    .append($('<td>').append(deleteButton))
+                );
+        }
+        currentPageNumber = pageNumber;
+    }
+
+    function deleteAccount(accountId) {
+        let xmlHttp = new XMLHttpRequest();
+        xmlHttp.open("DELETE", `/rest/players/${accountId}`, false);
+        xmlHttp.send(null);
+    }
+
+    function saveAccount(accountId, account) {
+        let xmlHttp = new XMLHttpRequest();
+        xmlHttp.open("POST", `/rest/players/${accountId}`, false);
+        xmlHttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
+        xmlHttp.send(JSON.stringify(account));
+    }
+
+    function addAccount(account) {
+        let xmlHttp = new XMLHttpRequest();
+        xmlHttp.open("POST", `/rest/players`, false);
+        xmlHttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
+        xmlHttp.send(JSON.stringify(account));
+    }
+
+    function printPagination() {
+        let xmlHttp = new XMLHttpRequest();
+        xmlHttp.open("GET", "/rest/players/count", false);
+        xmlHttp.send(null);
+        let count = xmlHttp.responseText;
+        let countPerPage = $("#countPerPage option:selected").val();
+        $("#pagesLine button").remove();
+        let pagesCount = Math.ceil(count / countPerPage);
+        let pagesLineElement = $("#pagesLine");
+        for (let i = 0; i < pagesCount; i++) {
+            let button;
+            if (i === currentPageNumber) {
+                button = $('<button class="active">');
+            } else {
+                button = $('<button>');
+            }
+            button[0].addEventListener('click', (event) => {
+                let pageNumber = event.target.innerText - 1;
+                printTableData(pageNumber, countPerPage);
+                printPagination();
+            });
+            pagesLineElement.append(button.append(i + 1));
+        }
+    }
+
+    function switchToEditMode(row) {
+        $(row).find('.delete').toggle();
+        $(row).find('.edit').toggle();
+        $(row).find('.save').toggle();
+    }
+
+    function editOnClick(row) {
+        convertToInputText(row, 1);
+        convertToInputText(row, 2);
+        convertToSelect(row, 3, ['HUMAN', 'DWARF', 'ELF', 'GIANT', 'ORC', 'TROLL', 'HOBBIT']);
+        convertToSelect(row, 4, ['WARRIOR', 'ROGUE', 'SORCERER', 'CLERIC', 'PALADIN', 'NAZGUL', 'WARLOCK', 'DRUID']);
+        convertToSelect(row, 7, ['true', 'false']);
+    }
+
+    function convertToInputText(row, fieldIndex) {
+        let value = $(row).find('td')[fieldIndex].innerText;
+        $(row).find('td')[fieldIndex].innerText = '';
+        $(row).find('td').eq(fieldIndex).append($(`<input type="text" value="${value}">`));
+    }
+
+    function convertToSelect(row, fieldIndex, optionArray) {
+        let value = $(row).find('td')[fieldIndex].innerText;
+        $(row).find('td')[fieldIndex].innerText = '';
+        let select = $('<select>');
+        for (const option of optionArray) {
+            if (option === value) {
+                select.append($('<option selected>').append(option));
+            } else {
+                select.append($('<option>').append(option));
+            }
+        }
+        $(row).find('td').eq(fieldIndex).append(select);
+    }
+
+    function prepareAccountFromTableRow(row) {
+        let name = $(row).find('td').eq(1).children('input')[0].value;
+        let title = $(row).find('td').eq(2).children('input')[0].value;
+        let race = $(row).find('td').eq(3).children('select')[0].value;
+        let profession = $(row).find('td').eq(4).children('select')[0].value;
+        let banned = $(row).find('td').eq(7).children('select')[0].value;
+        return {name:name, title:title, race:race, profession:profession, banned:banned};
+    }
+
+    function prepareAccountFromForm() {
+        let form = $('#addAccountForm');
+
+        let name = form.find('#name')[0].value;
+        let title = form.find('#title')[0].value;
+        let race = form.find('#race')[0].value;
+        let profession = form.find('#profession')[0].value;
+        let level = form.find('#level')[0].value;
+        let birthday = form.find('#birthday')[0].valueAsNumber;
+        let banned = form.find('#banned')[0].value;
+        return {name:name, title:title, race:race, profession:profession, level:level, birthday:birthday, banned:banned};
+    }
+
+    function clearAccountForm() {
+        let form = $('#addAccountForm');
+
+        form.find('#name')[0].value = '';
+        form.find('#title')[0].value = '';
+        form.find('#race').val($("#race option:first").val());
+        form.find('#profession').val($("#profession option:first").val());
+        form.find('#level')[0].value = '';
+        form.find('#birthday')[0].value = '';
+        form.find('#banned').val($("#banned option:first").val());
+    }
+
+    const params = new Proxy(new URLSearchParams(window.location.search), {
+        get: (searchParams, prop) => searchParams.get(prop),
+    });
+
+    let currentPageNumber = params.pageNumber ? params.pageNumber : 0;
+    printTableData(currentPageNumber, 5);
+    printPagination();
+
+    document.getElementById("countPerPage").addEventListener('change', (event) => {
+        printTableData(0, event.target.value);
+        printPagination();
+    });
+
+    document.getElementById("submit").addEventListener('click', (event) => {
+       let account = prepareAccountFromForm();
+       addAccount(account);
+       clearAccountForm();
+       let countPerPage = $("#countPerPage option:selected").val();
+       printTableData(currentPageNumber, countPerPage);
+       printPagination();
+    });
+</script>
+
 </body>
 </html>
\ No newline at end of file