Index: imaps-frontend/src/pages/AdminPage/AdminPage.jsx
===================================================================
--- imaps-frontend/src/pages/AdminPage/AdminPage.jsx	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/src/pages/AdminPage/AdminPage.jsx	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,228 @@
+import React, {useEffect, useState} from "react";
+import styles from "./AdminPage.module.css";
+import {TilesContainer} from "react-tiles-dnd";
+import HttpService from "../../scripts/net/HttpService.js";
+import config from "../../scripts/net/netconfig.js";
+import card from "../../assets/card-map.png";
+import MapInfoModal from "../../components/MapInfoModal/MapInfoModal.jsx";
+import {useAppContext} from "../../components/AppContext/AppContext.jsx";
+import PublishForm from "../../components/PublishForm/PublishForm.jsx";
+import Logo from "../../components/Logo/Logo.jsx";
+import Profile from "../../components/Profile/Profile.jsx";
+import Toast from "../../components/Toast/Toast.jsx";
+
+const renderTile = ({data, isDragging}, handleApprove, handleDeny, openMapInfoModal, openPublishForm) => (
+    <div className={`${styles.tile} ${isDragging ? styles.dragging : ""}`} onClick={() => openMapInfoModal(data)}>
+        <img src={card} className={styles.imgStyle} alt="Map Thumbnail"/>
+        <div className={styles.mapTitle}>{data.mapName}</div>
+        <button className={styles.viewPublishFormButton} onClick={(e) => {
+            e.stopPropagation();
+            openPublishForm(data);
+        }}>
+            View Form
+        </button>
+        <div className={styles.buttonContainer}>
+            {/*<input*/}
+            {/*    type="text"*/}
+            {/*    placeholder="Reason"*/}
+            {/*    className={styles.reasonInput}*/}
+            {/*    onClick={(e) => e.stopPropagation()}*/}
+            {/*/>*/}
+            {/*<div className={styles.buttonsGroup}>*/}
+            {/*    <button className={styles.approveButton} onClick={(e) => {*/}
+            {/*        e.stopPropagation();*/}
+            {/*        handleApprove(data.mapName);*/}
+            {/*    }}>*/}
+            {/*        Approve*/}
+            {/*    </button>*/}
+            {/*    <button className={styles.denyButton} onClick={(e) => {*/}
+            {/*        e.stopPropagation();*/}
+            {/*        const reason = e.target.closest('div').previousSibling.value;*/}
+            {/*        handleDeny(data.mapName, reason);*/}
+            {/*    }}>*/}
+            {/*        Deny*/}
+            {/*    </button>*/}
+
+            {/*</div>*/}
+        </div>
+    </div>
+);
+
+const tileSize = (tile) => ({
+    colSpan: tile.cols,
+    rowSpan: tile.rows,
+});
+
+export default function AdminPage() {
+    const [pendingMaps, setPendingMaps] = useState([]);
+    const [selectedMap, setSelectedMap] = useState(null);
+    const [isMapInfoModalOpen, setIsMapInfoModalOpen] = useState(false);
+    const [publishFormMap, setPublishFormMap] = useState(null);
+    const [publishRequests, setPublishRequests] = useState([]);
+    const [currentForm, setCurrentForm] = useState({});
+    const {username} = useAppContext();
+
+    const [toastMessage, setToastMessage] = useState(null);
+    const [toastType, setToastType] = useState(1);
+
+    useEffect(() => {
+        const loadPendingMaps = async () => {
+            const httpService = new HttpService();
+            httpService.setAuthenticated();
+
+            const respMaps = await httpService.get(`${config.admin.display}`);
+
+            const mapTiles = respMaps.map((elem) => ({
+                mapName: elem.mapName,
+                cols: 1,
+                rows: 1,
+                status: elem.mapStatus,
+                created_at: elem.createdAt,
+                modified_at: elem.modifiedAt,
+                gmaps_url: elem.gmaps_url,
+                image_url: card,
+            })).filter((tile) => tile.status === "INVALID");
+
+            setPendingMaps(mapTiles);
+        };
+
+        loadPendingMaps();
+    }, [username]);
+
+    useEffect(() => {
+        const loadPublishRequests = async () => {
+            const httpService = new HttpService(true);
+            const respPr = await httpService.get(`${config.admin.load_pr}`)
+
+            setPublishRequests(respPr);
+        }
+
+        loadPublishRequests();
+    }, []);
+
+    const handleApprove = async (id,mapName) => {
+        const httpService = new HttpService();
+        httpService.setAuthenticated();
+        const url = `${config.admin.approve_pr}?id=${id}`;
+        closePublishForm()
+        try {
+            await httpService.post(url);
+            setPendingMaps((prev) => prev.filter((map) => map.mapName !== mapName));
+            showToast(`Publish Request "${id}" approved.`, 1)
+        } catch (error) {
+            console.error("Error approving pr:", error);
+            // alert("Failed to approve pr.");
+            showToast("Failed to approve pr.", 0)
+        }
+    };
+
+    const showToast = (message, type = 1) => {
+        setToastMessage(message);
+        setToastType(type);
+        setTimeout(() => setToastMessage(null), 3000); // Automatically hide the toast after 3 seconds
+    };
+
+    const handleDeny = async (id, mapName,reason) => {
+        const httpService = new HttpService();
+        httpService.setAuthenticated();
+        const url = `${config.admin.deny_pr}?id=${id}&reason=${encodeURIComponent(reason)}`;
+        closePublishForm()
+        try {
+            await httpService.post(url);
+            setPendingMaps((prev) => prev.filter((map) => map.mapName !== mapName));
+            showToast(`Publish request ${id} denied.`, 1)
+        } catch (error) {
+            console.error("Error denying pr:", error);
+            alert("Failed to deny pr.");
+            showToast("Failed to deny pr.", 0)
+        }
+    };
+
+    const handlePublishFormSubmit = async (formData) => {
+        const httpService = new HttpService();
+        httpService.setAuthenticated();
+        const url = `${config.admin.approve_pr}?mapName=${formData.mapName}`;
+
+        try {
+            await httpService.post(url, formData); // Assuming formData contains all required fields
+            setPendingMaps((prev) => prev.filter((map) => map.mapName !== formData.mapName));
+            alert(`Map "${formData.mapName}" published successfully.`);
+            closePublishForm();
+        } catch (error) {
+            console.error("Error publishing map:", error);
+            alert("Failed to publish map. Please try again.");
+        }
+    };
+
+
+    const openMapInfoModal = (map) => {
+        setSelectedMap(map);
+        setIsMapInfoModalOpen(true);
+    };
+
+    const closeMapInfoModal = () => {
+        setIsMapInfoModalOpen(false);
+        setSelectedMap(null);
+    };
+
+    const openPublishForm = (data) => {
+        console.log("DATA MAP NAME", data.mapName)
+        publishRequests.forEach(pr => {
+            console.log("PR: " + JSON.stringify(pr))
+        })
+
+        const pr = publishRequests.find(p => p.mapName === data.mapName);
+        console.log("FOUND PR: " + pr)
+        setCurrentForm(pr)
+        setPublishFormMap(data);
+    };
+
+    const closePublishForm = () => {
+        setPublishFormMap(null);
+    };
+
+    return (
+        <div className={styles.container}>
+            <Logo></Logo>
+            <Profile></Profile>
+            <h1>Pending Maps for Approval</h1>
+
+            {publishFormMap && (
+                <PublishForm
+                    isAdmin={true}
+                    formData={currentForm}
+                    onSubmit={handlePublishFormSubmit}
+                    onCancel={closePublishForm}
+                    onApprove={handleApprove}
+                    onDeny={handleDeny}
+
+                />
+            )}
+
+
+            <div className={styles.mapsContainer}>
+                <TilesContainer
+                    data={pendingMaps}
+                    renderTile={(tileProps) => renderTile(tileProps, handleApprove, handleDeny, openMapInfoModal, openPublishForm)}
+                    tileSize={tileSize}
+                    forceTileWidth={200}
+                    forceTileHeight={250}
+                />
+            </div>
+            {isMapInfoModalOpen && (
+                <MapInfoModal
+                    isOpen={isMapInfoModalOpen}
+                    onClose={closeMapInfoModal}
+                    map={selectedMap}
+                    onUpdate={() => {
+                    }}
+                    onDelete={() => {
+                    }}
+                    published={true}
+                />
+            )}
+            {toastMessage && <Toast message={toastMessage} type={toastType} onClose={() => setToastMessage(null)}/>}
+
+        </div>
+    );
+}
Index: imaps-frontend/src/pages/AdminPage/AdminPage.module.css
===================================================================
--- imaps-frontend/src/pages/AdminPage/AdminPage.module.css	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/src/pages/AdminPage/AdminPage.module.css	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,138 @@
+.container {
+    max-width: 1200px;
+    margin: 0 auto;
+    padding: 20px;
+    text-align: center;
+    font-family: "Roboto", sans-serif;
+    overflow: hidden;
+}
+
+h1 {
+    font-size: 2.5rem;
+    color: black;
+    margin-bottom: 20px;
+}
+
+.mapsContainer {
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+    margin-top: 30px;
+}
+
+.tile {
+    width: 90%;
+    margin: 0 auto;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    color: #2c3e50;
+    background-color: #ffffff;
+    box-shadow: rgba(0, 0, 0, 0.1) 0px 5px 15px;
+    transition: all 300ms ease-in-out;
+    padding: 10px;
+    border: 2px solid #232323;
+    border-radius: 12px;
+    margin-bottom: 20px;
+}
+
+.tile:hover {
+    transform: scale(1.05);
+    box-shadow: rgba(0, 0, 0, 0.4) 0px 8px 18px;
+    background: #eeeeee;
+}
+
+.imgStyle {
+    width: 80%;
+    margin-top: 10px;
+    margin-bottom: 5px;
+}
+
+.mapTitle {
+    color: #2c2f33;
+    text-transform: uppercase;
+    margin-bottom: 10px;
+    font-size: 1.2rem;
+}
+
+.buttonContainer {
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+    width: 100%;
+}
+
+.buttonsGroup {
+    display: flex;
+    justify-content: space-between;
+    gap: 10px;
+    width: 100%;
+}
+
+.approveButton, .denyButton {
+    padding: 8px 16px;
+    font-size: 14px;
+    border: none;
+    border-radius: 8px;
+    cursor: pointer;
+    transition: background-color 0.3s ease, transform 0.2s ease;
+}
+
+.approveButton {
+    background-color: #4caf50;
+    color: white;
+}
+
+.approveButton:hover {
+    background-color: #388e3c;
+    transform: translateY(-2px);
+}
+
+.denyButton {
+    background-color: #f44336;
+    color: white;
+}
+
+.denyButton:hover {
+    background-color: #d32f2f;
+    transform: translateY(-2px);
+}
+
+.viewPublishFormButton{
+    margin-bottom: 10px;
+}
+
+.reasonInput {
+    width: 100%;
+    padding: 8px;
+    font-size: 14px;
+    border: 1px solid #ccc;
+    border-radius: 8px;
+    outline: none;
+    margin-bottom: 10px;
+}
+
+.reasonInput:focus {
+    border-color: #1e90ff;
+    box-shadow: 0 0 8px rgba(30, 144, 255, 0.5);
+}
+
+@media (max-width: 768px) {
+    .mapsContainer {
+        flex-direction: column;
+    }
+
+    .tile {
+        width: 100%;
+    }
+
+    .reasonInput {
+        width: 100%;
+    }
+
+    .buttonsGroup {
+        flex-direction: column;
+        gap: 10px;
+    }
+}
