├── client └── client.lua ├── config.lua ├── fxmanifest.lua ├── server ├── server.lua └── utils.lua └── ui ├── css ├── style.css ├── style.css.map └── style.scss ├── index.html └── js └── main.js /client/client.lua: -------------------------------------------------------------------------------- 1 | Framework = Config.Framework == "esx" and exports['es_extended']:getSharedObject() or exports['qb-core']:GetCoreObject() 2 | Admins = {} 3 | Reports = {} 4 | PlayerData = {} 5 | local loggedIn = false 6 | local uiLoaded = false 7 | 8 | RegisterNUICallback("uiLoaded", function(_, cb) 9 | uiLoaded = true 10 | cb(Config.Framework == "esx" and PlayerData.firstName or PlayerData.charinfo.firstname) 11 | end) 12 | 13 | CreateThread(function() 14 | while true do 15 | PlayerData = Config.Framework == "esx" and Framework.GetPlayerData() or Framework.Functions.GetPlayerData() 16 | 17 | if uiLoaded and not loggedIn and next(PlayerData) then 18 | loggedIn = true 19 | TriggerServerEvent("codev-report:server:loaded") 20 | end 21 | 22 | Wait(200) 23 | end 24 | end) 25 | 26 | -- EVENTS -- 27 | RegisterNetEvent("codev-report:client:loaded", function(admins, reports) 28 | Admins = admins 29 | Reports = reports 30 | 31 | RegisterCommand("reports", function() 32 | if loggedIn then 33 | SetNuiFocus(1, 1) 34 | SendNUIMessage({ 35 | action = "openAdminMenu", 36 | }) 37 | end 38 | end, false) 39 | end) 40 | 41 | RegisterNetEvent("codev-report:client:updateAdmins", function(admins) 42 | Admins = admins 43 | end) 44 | 45 | RegisterNetEvent("codev-report:removeAdmin", function(order) 46 | table.remove(Admins, order) 47 | end) 48 | 49 | RegisterNetEvent("codev-report:client:sendReport", function(data) 50 | table.insert(Reports, data) 51 | Config.Notification(Config.Translations["report"], Config.Translations["report_alert"], "primary", 5000) 52 | end) 53 | 54 | RegisterNetEvent('codev-report:client:alertPlayer', function(alertType) 55 | if alertType == "bring" then 56 | Config.Notification(Config.Translations[alertType], Config.Translations["admin_bringed"], "primary", 5000) 57 | elseif alertType == "goto" then 58 | Config.Notification(Config.Translations[alertType], Config.Translations["admin_came"], "primary", 5000) 59 | end 60 | end) 61 | 62 | RegisterNetEvent('codev-report:client:updateReports', function(reports) 63 | Reports = reports 64 | end) 65 | 66 | -- NUI CALLBACKS -- 67 | RegisterNUICallback("sendReport", function(data) 68 | SetNuiFocus(0,0) 69 | TriggerServerEvent("codev-report:server:sendReport", data) 70 | Config.Notification(Config.Translations["sent"], Config.Translations["report_sent"], "success", 5000) 71 | end) 72 | 73 | RegisterNUICallback("getReports", function(_, cb) 74 | cb(Reports) 75 | end) 76 | 77 | RegisterNUICallback("bring", function(serverId) 78 | TriggerServerEvent("codev-report:server:bringPlayer", serverId) 79 | end) 80 | 81 | RegisterNUICallback("goto", function(serverId) 82 | TriggerServerEvent("codev-report:server:gotoPlayer", serverId) 83 | end) 84 | 85 | RegisterNUICallback("concludeReport", function(reportId) 86 | TriggerServerEvent("codev-report:server:concludeReport", reportId, Config.Framework == "esx" and PlayerData.firstName.." "..PlayerData.lastName or PlayerData.charinfo.firstname.." "..PlayerData.charinfo.lastname) 87 | end) 88 | 89 | RegisterNUICallback("deleteReport", function(reportId) 90 | Config.Notification(Config.Translations["deleted"], Config.Translations["report_deleted"], "success", 5000) 91 | TriggerServerEvent("codev-report:server:deleteReport", reportId) 92 | end) 93 | 94 | RegisterNUICallback("close", function(data) 95 | SetNuiFocus(0,0) 96 | end) 97 | 98 | -- COMMANDS -- 99 | RegisterCommand("report", function() 100 | if loggedIn then 101 | SetNuiFocus(1, 1) 102 | SendNUIMessage({ 103 | action = "openReportMenu", 104 | }) 105 | end 106 | end, false) -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = { 2 | Framework = "qb", -- Framework name (esx or qb) 3 | 4 | BotName = "CodeV Report", -- Name of the bot that will send the reports to the discord channel 5 | Webhook = "", -- Discord webhook link 6 | 7 | Admins = { -- Discord IDs of the admins 8 | "discord:397032581326962689", 9 | }, 10 | 11 | Translations = { 12 | ["report"] = "Report", 13 | ["report_alert"] = "There is a new report!", 14 | ["sent"] = "Sent", 15 | ["report_sent"] = "Report successfully sent.", 16 | ["deleted"] = "Deleted", 17 | ["report_deleted"] = "Report successfully deleted.", 18 | ["bring"] = "Admin", 19 | ["admin_bringed"] = "An admin bringed you.", 20 | ["goto"] = "Admin", 21 | ["admin_came"] = "An admin teleported to help you.", 22 | ["concluded"] = "Concluded", 23 | }, 24 | 25 | Notification = function(title, message, msgType, length) 26 | -- Your notification here 27 | end 28 | } -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | author 'CodeVerse' 4 | description 'CodeV Report' 5 | lua54 'yes' 6 | 7 | shared_script 'config.lua' 8 | 9 | client_scripts{ 10 | 'client/client.lua', 11 | } 12 | 13 | server_scripts{ 14 | 'server/utils.lua', 15 | 'server/server.lua', 16 | } 17 | 18 | ui_page 'ui/index.html' 19 | 20 | files { 21 | 'ui/**/*.*', 22 | 'ui/*.*', 23 | } -------------------------------------------------------------------------------- /server/server.lua: -------------------------------------------------------------------------------- 1 | Framework = Config.Framework == "esx" and exports['es_extended']:getSharedObject() or exports['qb-core']:GetCoreObject() 2 | Admins = {} 3 | Reports = {} 4 | local reportId = 0 5 | 6 | RegisterServerEvent('codev-report:server:loaded', function() 7 | local src = source 8 | 9 | for i, identifier in pairs(Config.Admins) do 10 | if _GetPlayerIdentifier(src) == identifier then 11 | 12 | table.insert(Admins, src) 13 | 14 | for _, admin in pairs(Admins) do 15 | TriggerClientEvent("codev-report:client:loaded", admin, Admins, Reports) 16 | end 17 | end 18 | end 19 | end) 20 | 21 | RegisterServerEvent('codev-report:server:sendReport', function(data) 22 | local src = source 23 | reportId = reportId + 1 24 | data.reporter = {} 25 | data.reporter.id = src 26 | 27 | if Config.Framework == "esx" then 28 | local xPlayer = Framework.GetPlayerFromId(src) 29 | data.reporter.name = xPlayer.getName() 30 | else 31 | local xPlayer = Framework.Functions.GetPlayer(src) 32 | data.reporter.name = xPlayer.PlayerData.charinfo.firstname.." "..xPlayer.PlayerData.charinfo.lastname 33 | end 34 | 35 | data.reportId = reportId 36 | 37 | table.insert(Reports, data) 38 | 39 | for _, admin in pairs(Admins) do 40 | TriggerClientEvent("codev-report:client:sendReport", admin, data) 41 | end 42 | 43 | local id = _GetPlayerIdentifier(src, 0) 44 | local plyName = GetPlayerName(src) 45 | local msgData = { 46 | message = 47 | '**[Player]: **'..plyName..'\n'.. 48 | '**[ID]: **'..src..'\n'.. 49 | '**[License]: **'..id..'\n'.. 50 | '**[Subject]: **'..data.subject..'\n'.. 51 | '**[Message]: **'..data.message..'\n' 52 | } 53 | 54 | SendWebhook(Config.BotName, msgData, Config.Translations["report_alert"], Config.Webhook) 55 | end) 56 | 57 | RegisterServerEvent('codev-report:server:concludeReport', function(reportId) 58 | for _, admin in pairs(Admins) do 59 | TriggerClientEvent("codev-report:client:concludeReport", admin, reportId) 60 | end 61 | end) 62 | 63 | RegisterServerEvent('codev-report:server:concludeReport', function(reportId, asister) 64 | local src = source 65 | local id = _GetPlayerIdentifier(src) 66 | local plyName = GetPlayerName(src) 67 | local msgData = { 68 | message = 69 | '**[Player]: **'..plyName..'\n'.. 70 | '**[License]: **'..id..'\n'.. 71 | '**[Report ID]: **'..reportId..'\n'.. 72 | '**[Concluded By]: **'..asister..'\n' 73 | } 74 | 75 | SendWebhook(Config.BotName, msgData, Config.Translations["concluded"], Config.Webhook) 76 | 77 | for i, report in pairs(Reports) do 78 | if report.reportId == reportId then 79 | report.concluded = true 80 | report.concludedby = asister 81 | 82 | for _, admin in pairs(Admins) do 83 | TriggerClientEvent("codev-report:client:updateReports", admin, Reports) 84 | end 85 | end 86 | end 87 | end) 88 | 89 | RegisterServerEvent('codev-report:server:deleteReport', function(reportId) 90 | local src = source 91 | local id = _GetPlayerIdentifier(src, 0) 92 | local plyName = GetPlayerName(src) 93 | local msgData = { 94 | message = 95 | '**[Player]: **'..plyName..'\n'.. 96 | '**[License]: **'..id..'\n'.. 97 | '**[Report ID]: **'..reportId..'\n' 98 | } 99 | 100 | SendWebhook(Config.BotName, msgData, Config.Translations["deleted"], Config.Webhook) 101 | 102 | for i, report in pairs(Reports) do 103 | if report.reportId == reportId then 104 | table.remove(Reports, i) 105 | 106 | for _, admin in pairs(Admins) do 107 | TriggerClientEvent("codev-report:client:updateReports", admin, Reports) 108 | end 109 | end 110 | end 111 | end) 112 | 113 | RegisterServerEvent('codev-report:server:alertPlayer', function(player, alertType) 114 | TriggerClientEvent("codev-report:client:alertPlayer", player, alertType) 115 | end) 116 | 117 | RegisterServerEvent('codev-report:server:gotoPlayer', function(player) 118 | local src = source 119 | local targetPed = GetPlayerPed(player) 120 | 121 | if not targetPed then return end 122 | local myPed = GetPlayerPed(src) 123 | local targetCoords = GetEntityCoords(targetPed) 124 | 125 | TriggerEvent('codev-report:server:alertPlayer', player, "goto") 126 | 127 | SetEntityCoords(myPed, targetCoords) 128 | end) 129 | 130 | RegisterServerEvent('codev-report:server:bringPlayer', function(player) 131 | local src = source 132 | local targetPed = GetPlayerPed(player) 133 | 134 | if not targetPed then return end 135 | local myPed = GetPlayerPed(src) 136 | local myCoords = GetEntityCoords(myPed) 137 | 138 | TriggerEvent('codev-report:server:alertPlayer', player, "bring") 139 | 140 | SetEntityCoords(targetPed, myCoords) 141 | end) 142 | 143 | AddEventHandler('playerDropped', function() 144 | local src = source 145 | local admin = IsAdmin(src) 146 | 147 | if admin then 148 | for i, admin2 in pairs(Admins) do 149 | if admin2 == admin then 150 | table.remove(Admins, i) 151 | TriggerClientEvent("codev-report:client:updateAdmins", admin, Admins) 152 | end 153 | end 154 | end 155 | end) -------------------------------------------------------------------------------- /server/utils.lua: -------------------------------------------------------------------------------- 1 | function IsAdmin(src) 2 | for _, admin in pairs(Admins) do 3 | if src == admin then 4 | return admin 5 | end 6 | end 7 | 8 | return false 9 | end 10 | 11 | function SendWebhook(botname, data, title, webhook) 12 | local embedMsg = {} 13 | local title = title 14 | local message = data.message 15 | 16 | timestamp = os.date("%c") 17 | embedMsg = { 18 | { 19 | ["color"] = 16711689, 20 | ["title"] = title, 21 | ["description"] = ""..message.."", 22 | ["footer"] ={ 23 | ["text"] = timestamp.." (Server Time).", 24 | }, 25 | } 26 | } 27 | PerformHttpRequest(webhook, 28 | function(err, text, headers)end, 'POST', json.encode({username = botname, avatar_url= "" , embeds = embedMsg}), { ['Content-Type']= 'application/json' }) 29 | end 30 | 31 | function _GetPlayerIdentifier(player) 32 | for i = 0, GetNumPlayerIdentifiers(player) - 1 do 33 | local license = GetPlayerIdentifier(player, i) 34 | 35 | if string.sub(license, 1, string.len("discord:")) == "discord:" then 36 | return license 37 | end 38 | end 39 | 40 | return false 41 | end -------------------------------------------------------------------------------- /ui/css/style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Istok+Web:wght@400;700&display=swap"); 2 | @import url("https://fonts.cdnfonts.com/css/satoshi"); 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | user-select: none; 8 | letter-spacing: -0.36px; 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | text-rendering: optimizeLegibility; 12 | } 13 | 14 | body { 15 | width: 100vw; 16 | height: 100vh; 17 | overflow: hidden; 18 | color: #fff; 19 | font-family: "Istok Web"; 20 | display: none; 21 | } 22 | 23 | main { 24 | width: 960px; 25 | height: fit-content; 26 | position: absolute; 27 | top: 50%; 28 | left: 50%; 29 | transform: translate(-50%, -50%); 30 | } 31 | main .bottom { 32 | border-radius: 10px; 33 | background: #1A1A1D; 34 | padding: 38px; 35 | width: 100%; 36 | position: absolute; 37 | bottom: -150px; 38 | left: 0; 39 | display: flex; 40 | gap: 23px; 41 | } 42 | main .bottom .btn { 43 | width: 100%; 44 | display: none; 45 | justify-content: center; 46 | align-items: center; 47 | height: 55px; 48 | cursor: pointer; 49 | gap: 6px; 50 | font-family: "Satoshi" !important; 51 | font-size: 16px; 52 | font-weight: 900; 53 | letter-spacing: -0.16px; 54 | text-transform: uppercase; 55 | border-radius: 5px; 56 | } 57 | main .bottom .btn.disabled { 58 | opacity: 0.5; 59 | pointer-events: none; 60 | } 61 | main .bottom .btn#sendBtn { 62 | display: none; 63 | } 64 | main .bottom .btn.primary { 65 | background: #2E2E31; 66 | } 67 | main .bottom .btn.primary:hover { 68 | background: #39393c; 69 | } 70 | main .bottom .btn.secondary { 71 | background: linear-gradient(132deg, #4E972B 0%, #478A28 100%); 72 | } 73 | main .bottom .btn.secondary:hover { 74 | background: linear-gradient(132deg, #54a32f 0%, #4E972B 100%); 75 | } 76 | main .bottom .btn.third { 77 | background: linear-gradient(132deg, #8A2828 0%, #7D2424 100%); 78 | } 79 | main .bottom .btn.third:hover { 80 | background: linear-gradient(132deg, #982d2d 0%, #8A2828 100%); 81 | } 82 | main .box { 83 | border-radius: 10px; 84 | background: #1A1A1D; 85 | padding: 48px; 86 | width: 100%; 87 | } 88 | main .box .header { 89 | width: 100%; 90 | position: relative; 91 | margin-bottom: 1.5rem; 92 | } 93 | main .box .header .close-btn { 94 | position: absolute; 95 | right: 0px; 96 | top: 0; 97 | width: 31px; 98 | height: 31px; 99 | border-radius: 5px; 100 | background: #2E2E31; 101 | display: flex; 102 | justify-content: center; 103 | align-items: center; 104 | cursor: pointer; 105 | } 106 | main .box .header .close-btn:hover { 107 | background: #3a3a3e; 108 | } 109 | main .box .header .back-btn { 110 | position: absolute; 111 | right: 40px; 112 | top: 0; 113 | width: 31px; 114 | height: 31px; 115 | border-radius: 5px; 116 | background: #2E2E31; 117 | display: none; 118 | justify-content: center; 119 | align-items: center; 120 | cursor: pointer; 121 | } 122 | main .box .header .back-btn:hover { 123 | background: #3a3a3e; 124 | } 125 | main .box .header .title { 126 | font-size: 36px; 127 | font-weight: 700; 128 | line-height: 120%; 129 | } 130 | main .box .header .subtitle { 131 | color: #858585; 132 | font-size: 14px; 133 | font-weight: 700; 134 | letter-spacing: -0.14px; 135 | } 136 | main .box .container { 137 | position: relative; 138 | height: 55px; 139 | transition: height 0.5s; 140 | overflow: hidden; 141 | } 142 | main .box .container.report-cont .categories { 143 | display: flex; 144 | } 145 | main .box .container.report-cont .reports-wrapper { 146 | display: none; 147 | } 148 | main .box .container.admin-cont { 149 | height: 420px; 150 | } 151 | main .box .container.admin-cont .categories { 152 | display: none; 153 | } 154 | main .box .container.admin-cont .reports-wrapper { 155 | display: flex; 156 | } 157 | main .box .container.wide { 158 | height: 420px !important; 159 | } 160 | main .box .container .categories { 161 | height: 48px; 162 | position: relative; 163 | } 164 | main .box .container .categories .category { 165 | transition: width 0.5s, left 0.5s; 166 | width: 33.33%; 167 | display: flex; 168 | justify-content: center; 169 | align-items: center; 170 | height: 48px; 171 | position: absolute; 172 | background: #252528; 173 | border-right: 1px solid #19191C; 174 | border-left: 1px solid #19191C; 175 | cursor: pointer; 176 | } 177 | main .box .container .categories .category:hover { 178 | background: #2E2E31; 179 | } 180 | main .box .container .categories .category.active { 181 | background: #2E2E31; 182 | z-index: 999; 183 | } 184 | main .box .container .categories .category.selected { 185 | left: 0% !important; 186 | width: 100% !important; 187 | border-radius: 5px !important; 188 | } 189 | main .box .container .categories .category:first-child { 190 | border-radius: 5px 0px 0px 5px; 191 | border: 0; 192 | } 193 | main .box .container .categories .category:nth-child(2) { 194 | left: 33.33%; 195 | } 196 | main .box .container .categories .category:last-child { 197 | border-radius: 0px 5px 5px 0px; 198 | border: 0; 199 | left: 66.66%; 200 | } 201 | main .box .container .categories .category span { 202 | font-size: 20px; 203 | font-weight: 600; 204 | letter-spacing: -0.2px; 205 | } 206 | main .box .container .categories .category .icon { 207 | position: absolute; 208 | left: 20px; 209 | top: 50%; 210 | transform: translateY(-50%); 211 | height: 22px; 212 | } 213 | main .box .container .reports-wrapper { 214 | display: flex; 215 | flex-direction: column; 216 | } 217 | main .box .container .reports-wrapper .reports-header { 218 | margin-bottom: 24px; 219 | display: flex; 220 | width: 100%; 221 | font-size: 20px; 222 | font-weight: 700; 223 | line-height: 100%; 224 | letter-spacing: -0.2px; 225 | align-items: center; 226 | border-radius: 5px; 227 | background: #292929; 228 | padding: 14px 19px; 229 | } 230 | main .box .container .reports-wrapper .reports-header div { 231 | display: flex; 232 | justify-content: center; 233 | } 234 | main .box .container .reports-wrapper .reports-header .id { 235 | width: 10%; 236 | justify-content: start; 237 | } 238 | main .box .container .reports-wrapper .reports-header .player { 239 | width: 25%; 240 | } 241 | main .box .container .reports-wrapper .reports-header .asister { 242 | width: 25%; 243 | } 244 | main .box .container .reports-wrapper .reports-header .category-a { 245 | width: 20%; 246 | } 247 | main .box .container .reports-wrapper .reports-header .action { 248 | width: 20%; 249 | justify-content: end; 250 | } 251 | main .box .container .reports-wrapper .reports { 252 | overflow-y: scroll; 253 | width: 100%; 254 | display: flex; 255 | flex-direction: column; 256 | gap: 18px; 257 | height: 349px; 258 | } 259 | main .box .container .reports-wrapper .reports::-webkit-scrollbar { 260 | width: 0px; 261 | } 262 | main .box .container .reports-wrapper .reports .report { 263 | display: flex; 264 | width: 100%; 265 | font-size: 20px; 266 | font-weight: 700; 267 | line-height: 100%; 268 | letter-spacing: -0.2px; 269 | align-items: center; 270 | border-radius: 5px; 271 | background: #2C2C2D; 272 | padding: 20px 19px; 273 | } 274 | main .box .container .reports-wrapper .reports .report div { 275 | display: flex; 276 | justify-content: center; 277 | } 278 | main .box .container .reports-wrapper .reports .report .id { 279 | width: 10%; 280 | justify-content: start; 281 | } 282 | main .box .container .reports-wrapper .reports .report .player { 283 | width: 25%; 284 | } 285 | main .box .container .reports-wrapper .reports .report .asister { 286 | width: 25%; 287 | } 288 | main .box .container .reports-wrapper .reports .report .category-a { 289 | width: 20%; 290 | } 291 | main .box .container .reports-wrapper .reports .report .action { 292 | width: 20%; 293 | justify-content: end; 294 | } 295 | main .box .container .reports-wrapper .reports .report .action .btn { 296 | padding: 10px 18px; 297 | border-radius: 5px; 298 | background: #1A1A1D; 299 | cursor: pointer; 300 | } 301 | main .box .container .reports-wrapper .reports .report .action .btn:hover { 302 | background: #141416; 303 | } 304 | main .box .container .text-box-wrapper { 305 | width: 100%; 306 | display: none; 307 | flex-direction: column; 308 | position: absolute; 309 | top: 70px; 310 | gap: 25px; 311 | } 312 | main .box .container .text-box-wrapper .text-box .title { 313 | font-size: 24px; 314 | font-weight: 700; 315 | letter-spacing: -0.24px; 316 | } 317 | main .box .container .text-box-wrapper .text-box .disabled { 318 | pointer-events: none; 319 | } 320 | main .box .container .text-box-wrapper .text-box input { 321 | font-family: "Satoshi"; 322 | font-size: 16px; 323 | font-weight: 500; 324 | line-height: 100%; 325 | letter-spacing: -0.16px; 326 | color: #fff; 327 | padding: 16px 20px; 328 | outline: none; 329 | width: 100%; 330 | border-radius: 5px; 331 | border: 1px solid #2E2E31; 332 | background: linear-gradient(170deg, rgba(46, 46, 49, 0.1) 0%, rgba(46, 46, 49, 0) 99.44%); 333 | } 334 | main .box .container .text-box-wrapper .text-box textarea { 335 | resize: none; 336 | height: 200px; 337 | font-family: "Satoshi"; 338 | font-size: 16px; 339 | font-weight: 500; 340 | line-height: 100%; 341 | letter-spacing: -0.16px; 342 | color: #fff; 343 | padding: 16px 20px; 344 | outline: none; 345 | width: 100%; 346 | border-radius: 5px; 347 | border: 1px solid #2E2E31; 348 | background: linear-gradient(170deg, rgba(46, 46, 49, 0.1) 0%, rgba(46, 46, 49, 0) 99.44%); 349 | } 350 | 351 | /*# sourceMappingURL=style.css.map */ 352 | -------------------------------------------------------------------------------- /ui/css/style.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["style.scss"],"names":[],"mappings":"AAAQ;AACA;AAER;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAEA;EACI;;AAIR;EACI;;AAEA;EACI;;AAIR;EACI;;AAEA;EACI;;AAMhB;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;;AAGI;EACI;;AAGJ;EACI;;AAIR;EACI;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;;AAGJ;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAKZ;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAEA;EACI;;AASxB;EACI;EACA;EACA;EACA;EACA;EACA;;AAGI;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA","file":"style.css"} -------------------------------------------------------------------------------- /ui/css/style.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Istok+Web:wght@400;700&display=swap'); 2 | @import url('https://fonts.cdnfonts.com/css/satoshi'); 3 | 4 | *{ 5 | margin: 0; 6 | padding: 0; 7 | box-sizing: border-box; 8 | user-select: none; 9 | letter-spacing: -0.36px; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | text-rendering: optimizeLegibility; 13 | } 14 | 15 | body{ 16 | width: 100vw; 17 | height: 100vh; 18 | overflow: hidden; 19 | color: #fff; 20 | font-family: 'Istok Web'; 21 | display: none; 22 | } 23 | 24 | main{ 25 | width: 960px; 26 | height: fit-content; 27 | position: absolute; 28 | top: 50%; 29 | left: 50%; 30 | transform: translate(-50%, -50%); 31 | 32 | .bottom{ 33 | border-radius: 10px; 34 | background: #1A1A1D; 35 | padding: 38px; 36 | width: 100%; 37 | position: absolute; 38 | bottom: -150px; 39 | left: 0; 40 | display: flex; 41 | gap: 23px; 42 | 43 | .btn{ 44 | width: 100%; 45 | display: none; 46 | justify-content: center; 47 | align-items: center; 48 | height: 55px; 49 | cursor: pointer; 50 | gap: 6px; 51 | font-family: 'Satoshi' !important; 52 | font-size: 16px; 53 | font-weight: 900; 54 | letter-spacing: -0.16px; 55 | text-transform: uppercase; 56 | border-radius: 5px; 57 | 58 | &.disabled{ 59 | opacity: 0.5; 60 | pointer-events: none; 61 | } 62 | 63 | sendBtn{ 64 | display: none; 65 | } 66 | 67 | &.primary{ 68 | background: #2E2E31; 69 | 70 | &:hover{ 71 | background: #39393c; 72 | } 73 | } 74 | 75 | &.secondary{ 76 | background: linear-gradient(132deg, #4E972B 0%, #478A28 100%); 77 | 78 | &:hover{ 79 | background: linear-gradient(132deg, #54a32f 0%, #4E972B 100%); 80 | } 81 | } 82 | 83 | &.third{ 84 | background: linear-gradient(132deg, #8A2828 0%, #7D2424 100%); 85 | 86 | &:hover{ 87 | background: linear-gradient(132deg, #982d2d 0%, #8A2828 100%); 88 | } 89 | } 90 | } 91 | } 92 | 93 | .box{ 94 | border-radius: 10px; 95 | background: #1A1A1D; 96 | padding: 48px; 97 | width: 100%; 98 | 99 | .header{ 100 | width: 100%; 101 | position: relative; 102 | margin-bottom: 1.5rem; 103 | 104 | .close-btn{ 105 | position: absolute; 106 | right: 0px; 107 | top: 0; 108 | width: 31px; 109 | height: 31px; 110 | border-radius: 5px; 111 | background: #2E2E31; 112 | display: flex; 113 | justify-content: center; 114 | align-items: center; 115 | cursor: pointer; 116 | 117 | &:hover{ 118 | background: #3a3a3e; 119 | } 120 | } 121 | 122 | .back-btn{ 123 | position: absolute; 124 | right: 40px; 125 | top: 0; 126 | width: 31px; 127 | height: 31px; 128 | border-radius: 5px; 129 | background: #2E2E31; 130 | display: none; 131 | justify-content: center; 132 | align-items: center; 133 | cursor: pointer; 134 | 135 | &:hover{ 136 | background: #3a3a3e; 137 | } 138 | } 139 | 140 | .title{ 141 | font-size: 36px; 142 | font-weight: 700; 143 | line-height: 120%; 144 | } 145 | 146 | .subtitle{ 147 | color: #858585; 148 | font-size: 14px; 149 | font-weight: 700; 150 | letter-spacing: -0.14px; 151 | } 152 | } 153 | 154 | .container{ 155 | position: relative; 156 | height: 55px; 157 | transition: height 0.5s; 158 | overflow: hidden; 159 | 160 | &.report-cont{ 161 | .categories{ 162 | display: flex; 163 | } 164 | 165 | .reports-wrapper{ 166 | display: none; 167 | } 168 | } 169 | 170 | &.admin-cont{ 171 | height: 420px; 172 | 173 | .categories{ 174 | display: none; 175 | } 176 | 177 | .reports-wrapper{ 178 | display: flex; 179 | } 180 | } 181 | 182 | &.wide{ 183 | height: 420px !important; 184 | } 185 | 186 | .categories{ 187 | height: 48px; 188 | position: relative; 189 | 190 | .category{ 191 | transition: width 0.5s, left 0.5s; 192 | width: 33.33%; 193 | display: flex; 194 | justify-content: center; 195 | align-items: center; 196 | height: 48px; 197 | position: absolute; 198 | background: #252528; 199 | border-right: 1px solid #19191C; 200 | border-left: 1px solid #19191C; 201 | cursor: pointer; 202 | 203 | &:hover{ 204 | background: #2E2E31; 205 | } 206 | 207 | &.active{ 208 | background: #2E2E31; 209 | z-index: 999; 210 | } 211 | 212 | &.selected{ 213 | left: 0% !important; 214 | width: 100% !important; 215 | border-radius: 5px !important; 216 | } 217 | 218 | &:first-child{ 219 | border-radius: 5px 0px 0px 5px; 220 | border: 0; 221 | } 222 | 223 | &:nth-child(2){ 224 | left: 33.33%; 225 | } 226 | 227 | &:last-child{ 228 | border-radius: 0px 5px 5px 0px; 229 | border: 0; 230 | left: 66.66%; 231 | } 232 | 233 | span{ 234 | font-size: 20px; 235 | font-weight: 600; 236 | letter-spacing: -0.2px; 237 | } 238 | 239 | .icon{ 240 | position: absolute; 241 | left: 20px; 242 | top: 50%; 243 | transform: translateY(-50%); 244 | height: 22px; 245 | } 246 | } 247 | } 248 | 249 | .reports-wrapper{ 250 | display: flex; 251 | flex-direction: column; 252 | 253 | .reports-header{ 254 | margin-bottom: 24px; 255 | display: flex; 256 | width: 100%; 257 | font-size: 20px; 258 | font-weight: 700; 259 | line-height: 100%; 260 | letter-spacing: -0.2px; 261 | align-items: center; 262 | border-radius: 5px; 263 | background: #292929; 264 | padding: 14px 19px; 265 | 266 | div{ 267 | display: flex; 268 | justify-content: center; 269 | } 270 | 271 | .id{ 272 | width: 10%; 273 | justify-content: start; 274 | } 275 | 276 | .player{ 277 | width: 25%; 278 | } 279 | 280 | .asister{ 281 | width: 25%; 282 | } 283 | 284 | .category-a{ 285 | width: 20%; 286 | } 287 | 288 | .action{ 289 | width: 20%; 290 | justify-content: end; 291 | } 292 | } 293 | 294 | .reports{ 295 | overflow-y: scroll; 296 | width: 100%; 297 | display: flex; 298 | flex-direction: column; 299 | gap: 18px; 300 | height: 349px; 301 | 302 | &::-webkit-scrollbar { 303 | width: 0px; 304 | } 305 | 306 | .report{ 307 | display: flex; 308 | width: 100%; 309 | font-size: 20px; 310 | font-weight: 700; 311 | line-height: 100%; 312 | letter-spacing: -0.2px; 313 | align-items: center; 314 | border-radius: 5px; 315 | background: #2C2C2D; 316 | padding: 20px 19px; 317 | 318 | div{ 319 | display: flex; 320 | justify-content: center; 321 | } 322 | 323 | .id{ 324 | width: 10%; 325 | justify-content: start; 326 | } 327 | 328 | .player{ 329 | width: 25%; 330 | } 331 | 332 | .asister{ 333 | width: 25%; 334 | } 335 | 336 | .category-a{ 337 | width: 20%; 338 | } 339 | 340 | .action{ 341 | width: 20%; 342 | justify-content: end; 343 | 344 | .btn{ 345 | padding: 10px 18px; 346 | border-radius: 5px; 347 | background: #1A1A1D; 348 | cursor: pointer; 349 | 350 | &:hover{ 351 | background: #141416; 352 | } 353 | } 354 | } 355 | } 356 | } 357 | } 358 | 359 | 360 | .text-box-wrapper{ 361 | width: 100%; 362 | display: none; 363 | flex-direction: column; 364 | position: absolute; 365 | top: 70px; 366 | gap: 25px; 367 | 368 | .text-box{ 369 | .title{ 370 | font-size: 24px; 371 | font-weight: 700; 372 | letter-spacing: -0.24px; 373 | } 374 | 375 | .disabled{ 376 | pointer-events: none; 377 | } 378 | 379 | input{ 380 | font-family: 'Satoshi'; 381 | font-size: 16px; 382 | font-weight: 500; 383 | line-height: 100%; 384 | letter-spacing: -0.16px; 385 | color: #fff; 386 | padding: 16px 20px; 387 | outline: none; 388 | width: 100%; 389 | border-radius: 5px; 390 | border: 1px solid #2E2E31; 391 | background: linear-gradient(170deg, rgba(46, 46, 49, 0.10) 0%, rgba(46, 46, 49, 0.00) 99.44%); 392 | } 393 | 394 | textarea{ 395 | resize: none; 396 | height: 200px; 397 | font-family: 'Satoshi'; 398 | font-size: 16px; 399 | font-weight: 500; 400 | line-height: 100%; 401 | letter-spacing: -0.16px; 402 | color: #fff; 403 | padding: 16px 20px; 404 | outline: none; 405 | width: 100%; 406 | border-radius: 5px; 407 | border: 1px solid #2E2E31; 408 | background: linear-gradient(170deg, rgba(46, 46, 49, 0.10) 0%, rgba(46, 46, 49, 0.00) 99.44%); 409 | } 410 | } 411 | } 412 | } 413 | } 414 | } -------------------------------------------------------------------------------- /ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |