Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 35 additions & 14 deletions server/backend/citizens.lua
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,23 @@ local function safeQuery(query, params)
return rows or {}
end

-- getCitizens - pulls citizens from database with pagination support
-- getCitizens - pulls citizens from database with pagination support - this shit is broken
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.

-- this shit is now fixed.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.

ps.registerCallback(resourceName .. ':server:getCitizens', function(source, page)
local src = source
if not CheckAuth(src) then return {} end
if not CheckAuth(src) then
--added data to actually be pulled
return { data = {}, total = 0, totalPages = 1, page = 1, limit = 20 }
end

local startTime = os.clock()
page = page or 1 -- Default to page 1 if not provided
page = tonumber(page) or 1
local limit = Config.Pagination and Config.Pagination.Citizens or 20
local offset = (page - 1) * limit

-- Main query with pagination
local total = MySQL.scalar.await('SELECT COUNT(*) FROM players') or 0
local totalPages = math.max(1, math.ceil(total / limit))

local query = [[
SELECT mp.id, p.citizenid, JSON_UNQUOTE(JSON_EXTRACT(p.charinfo, '$.firstname')) AS firstname,
JSON_UNQUOTE(JSON_EXTRACT(p.charinfo, '$.lastname')) AS lastname,
Expand All @@ -104,10 +111,21 @@ ps.registerCallback(resourceName .. ':server:getCitizens', function(source, page
FROM players AS p
LEFT JOIN mdt_profiles AS mp
ON CONVERT(p.citizenid USING utf8mb4) COLLATE utf8mb4_general_ci = CONVERT(mp.citizenid USING utf8mb4) COLLATE utf8mb4_general_ci
ORDER BY JSON_UNQUOTE(JSON_EXTRACT(p.charinfo, '$.lastname')) ASC,
JSON_UNQUOTE(JSON_EXTRACT(p.charinfo, '$.firstname')) ASC
LIMIT ? OFFSET ?
]]

local result = safeQuery(query, { limit, offset })
if not result or #result == 0 then return {} end
if not result or #result == 0 then
return { --same shit different row
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.

data = {},
total = total,
totalPages = totalPages,
page = page,
limit = limit
}
end

local citizenids = {}
for _, v in ipairs(result) do
Expand All @@ -116,7 +134,7 @@ ps.registerCallback(resourceName .. ':server:getCitizens', function(source, page
end
end

-- Wrap flags in pcall since it queries mdt_reports_warrants / mdt_bolos which may not exist
-- Wrap flags in pcall since it queries mdt_reports_warrants / mdt_bolos which may not exist
local ok, flagsByCid = pcall(collectCitizenFlags, citizenids)
if not ok then
ps.warn('[getCitizens] collectCitizenFlags failed: ' .. tostring(flagsByCid))
Expand Down Expand Up @@ -167,8 +185,8 @@ ps.registerCallback(resourceName .. ':server:getCitizens', function(source, page
end
end

for _, v in ipairs(result) do
v.id = _
for i, v in ipairs(result) do
v.id = i
v.cid = v.citizenid
v.firstName = v.firstname
v.lastName = v.lastname
Expand All @@ -182,15 +200,18 @@ ps.registerCallback(resourceName .. ':server:getCitizens', function(source, page
v.arrests = arrestCounts[v.citizenid] or 0
v.flags = flagsByCid[v.citizenid] or {}
end

local endTime = os.clock()
local elapsedTime = (endTime - startTime) * 1000
ps.debug(string.format("getCitizens callback executed in %.2f ms for page %d", elapsedTime, page))

if result[1] then
ps.debug('[getCitizens] Sample citizen data structure:', result[1])
end

return result
--no more sample citizen stuff.
return {
data = result,
total = total,
totalPages = totalPages,
page = page,
limit = limit
}
end)

-- searchPlayers - searches the database for citizens by provided query (first/last name, citizenid, phone number, occupation)
Expand Down
28 changes: 18 additions & 10 deletions web/src/pages/Citizens.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,28 @@
let copyNotice = $state("");
let copyTimeout: ReturnType<typeof setTimeout> | null = null;

// im sure there's a better more streamlined way to do this, but here's a bandaid.
let citizenPage = $state(1);
let citizenPerPage = $state(25);
let citizenPerPage = $state(20);
let citizenTotalPages = $state(1); // how many pages exist

let allFilteredCitizens = $derived.by(() => {
let filteredCitizens = $derived.by(() => {
const query = searchQuery.trim().toLowerCase();
if (!query) return citizens;

return citizens.filter(({ firstName, lastName, cid, phone }) =>
[firstName, lastName, cid, phone].some((val) =>
val?.toLowerCase().includes(query),
),
);
});

let citizenTotalPages = $derived(Math.max(1, Math.ceil(allFilteredCitizens.length / citizenPerPage)));

let filteredCitizens = $derived.by(() => {
const start = (citizenPage - 1) * citizenPerPage;
return allFilteredCitizens.slice(start, start + citizenPerPage);
// auto calls fetchCitizens for citizenpage
$effect(() => {
citizenPage;
if (!isEnvBrowser()) {
fetchCitizens();
}
});

// Reset to page 1 when search changes
Expand All @@ -136,11 +140,16 @@
async function fetchCitizens() {
loading = true;
try {
const result = await fetchNui(NUI_EVENTS.CITIZEN.GET_CITIZENS);
citizens = Array.isArray(result) ? result : [];
const result = await fetchNui(NUI_EVENTS.CITIZEN.GET_CITIZENS, {
page: citizenPage
}); // this shit makes the whole world go round
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.


citizens = Array.isArray(result) ? result : []; // this shit shows you the world spinning
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment.

citizenTotalPages = Number(result?.totalPages) || 1;
} catch (error) {
globalNotifications.error("Failed to fetch citizens");
citizens = [];
citizenTotalpages = 1;
}
loading = false;
}
Expand All @@ -156,7 +165,6 @@
];
return;
}
await fetchCitizens();
});

useNuiEvent<Citizen[]>(NUI_EVENTS.CITIZEN.UPDATE_CITIZENS, (data) => {
Expand Down