Skip to content
Merged
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
37 changes: 37 additions & 0 deletions admin_app_2/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions admin_app_2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.1.3",
"prettier-plugin-organize-imports": "^3.2.4",
"typescript": "^5"
}
}
41 changes: 25 additions & 16 deletions admin_app_2/src/app/content/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use client";
import LanguageButtonBar from "@/components/LanguageButtonBar";
import { Layout } from "@/components/Layout";
import { FullAccessComponent } from "@/components/ProtectedComponent";
import { appColors, appStyles, sizes } from "@/utils";
import { apiCalls } from "@/utils/api";
import { useAuth } from "@/utils/auth";
import { ChevronLeft } from "@mui/icons-material";
import { Button, CircularProgress, TextField, Typography } from "@mui/material";
import Alert from "@mui/material/Alert";
Expand All @@ -29,12 +31,13 @@ const AddEditContentPage = () => {
const [content, setContent] = React.useState<Content | null>(null);
const [isLoading, setIsLoading] = React.useState<boolean>(true);

const { token } = useAuth();
Copy link
Collaborator

Choose a reason for hiding this comment

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

This entire page shouldn't run any code at all (including the .getContent fetch, since it's never shown) if we're readonly and instead display a "Not Authorised" message on the page.

How do we also stop the useEffects from running on page load based on auth state?

React.useEffect(() => {
if (!content_id) {
setIsLoading(false);
return;
} else {
apiCalls.getContent(content_id).then((data) => {
apiCalls.getContent(content_id, token!).then((data) => {
setContent(data);
setIsLoading(false);
});
Expand All @@ -58,17 +61,19 @@ const AddEditContentPage = () => {
);
}
return (
<Layout.FlexBox flexDirection={"column"} sx={{ p: sizes.doubleBaseGap }}>
<Header content_id={content_id} />
<Layout.FlexBox
flexDirection={"column"}
sx={{ px: sizes.doubleBaseGap, mx: sizes.smallGap }}
>
<Layout.Spacer multiplier={2} />
<ContentBox content={content} setContent={setContent} />
<Layout.Spacer multiplier={1} />
<FullAccessComponent>
<Layout.FlexBox flexDirection={"column"} sx={{ p: sizes.doubleBaseGap }}>
<Header content_id={content_id} />
<Layout.FlexBox
flexDirection={"column"}
sx={{ px: sizes.doubleBaseGap, mx: sizes.smallGap }}
>
<Layout.Spacer multiplier={2} />
<ContentBox content={content} setContent={setContent} />
<Layout.Spacer multiplier={1} />
</Layout.FlexBox>
</Layout.FlexBox>
</Layout.FlexBox>
</FullAccessComponent>
);
};

Expand All @@ -84,6 +89,8 @@ const ContentBox = ({
const [isTitleEmpty, setIsTitleEmpty] = React.useState(false);
const [isContentEmpty, setIsContentEmpty] = React.useState(false);

const { token } = useAuth();

const router = useRouter();
const saveContent = async (content: Content) => {
const body: EditContentBody = {
Expand All @@ -95,8 +102,8 @@ const ContentBox = ({

const promise =
content.content_id === null
? apiCalls.addContent(body)
: apiCalls.editContent(content.content_id, body);
? apiCalls.addContent(body, token!)
: apiCalls.editContent(content.content_id, body, token!);

const result = promise
.then((data) => {
Expand Down Expand Up @@ -162,7 +169,7 @@ const ContentBox = ({
"& .MuiFormHelperText-root": {
backgroundColor: appColors.lightGrey,
mx: 0,
my: 0, // Set your desired background color here
my: 0,
},
}}
value={content ? content.content_title : ""}
Expand All @@ -180,7 +187,7 @@ const ContentBox = ({
"& .MuiFormHelperText-root": {
backgroundColor: appColors.lightGrey,
mx: 0,
my: 0, // Set your desired background color here
my: 0,
},
}}
label="Content"
Expand Down Expand Up @@ -234,11 +241,13 @@ const ContentBox = ({
};

const Header = ({ content_id }: { content_id: number | null }) => {
const router = useRouter();

return (
<Layout.FlexBox flexDirection="row" {...appStyles.alignItemsCenter}>
<ChevronLeft
style={{ cursor: "pointer" }}
onClick={() => (window.location.href = "/content/")}
onClick={() => (content_id ? router.back() : router.push("/content"))}
/>
<Layout.Spacer multiplier={1} horizontal />
{content_id ? (
Expand Down
16 changes: 16 additions & 0 deletions admin_app_2/src/app/content/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import NavBar from "@/components/NavBar";
import { ProtectedComponent } from "@/components/ProtectedComponent";
import React from "react";

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<ProtectedComponent>
<NavBar />
{children}
</ProtectedComponent>
);
}
57 changes: 35 additions & 22 deletions admin_app_2/src/app/content/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use client";
import ContentCard from "@/components/ContentCard";
import { Layout } from "@/components/Layout";
import { LANGUAGE_OPTIONS, appColors, sizes } from "@/utils";
import { LANGUAGE_OPTIONS, sizes } from "@/utils";
import { apiCalls } from "@/utils/api";
import { useAuth } from "@/utils/auth";
import { Add, ChevronLeft, ChevronRight } from "@mui/icons-material";
import { Box, Button, CircularProgress, Grid, Typography } from "@mui/material";
import Alert from "@mui/material/Alert";
Expand All @@ -26,17 +27,19 @@ const CardsView = () => {
const [displayLanguage, setDisplayLanguage] = React.useState<string>(
LANGUAGE_OPTIONS[0].label,
);
const { accessLevel } = useAuth();

return (
<Layout.FlexBox width={"100%"}>
<Layout.Spacer multiplier={1} />
<CardsUtilityStrip />
<CardsUtilityStrip editAccess={accessLevel === "fullaccess"} />
<Layout.Spacer multiplier={1} />
<CardsGrid displayLanguage={displayLanguage} />
</Layout.FlexBox>
);
};

const CardsUtilityStrip = () => {
const CardsUtilityStrip = ({ editAccess }: { editAccess: boolean }) => {
return (
<Layout.FlexBox
key={"utility-strip"}
Expand All @@ -50,12 +53,15 @@ const CardsUtilityStrip = () => {
}}
gap={sizes.baseGap}
>
<Link href="/content/edit">
<Button variant="contained">
<Add />
New
</Button>
</Link>
<Button
variant="contained"
disabled={editAccess ? false : true}
component={Link}
href="/content/edit"
>
<Add />
New
</Button>
</Layout.FlexBox>
);
};
Expand All @@ -70,6 +76,8 @@ const CardsGrid = ({ displayLanguage }: { displayLanguage: string }) => {
const action = searchParams.get("action") || null;
const content_id = Number(searchParams.get("content_id")) || null;

const { token, accessLevel } = useAuth();

const getSnackMessage = (
action: string | null,
content_id: number | null,
Expand All @@ -90,23 +98,24 @@ const CardsGrid = ({ displayLanguage }: { displayLanguage: string }) => {
const onSuccessfulDelete = (content_id: number) => {
setIsLoading(true);
setRefreshKey((prevKey) => prevKey + 1);
console.log("hello");
setSnackMessage(`Content #${content_id} deleted successfully`);
};

React.useEffect(() => {
apiCalls
.getContentList()
.then((data) => {
setCards(data);
setMaxPages(Math.ceil(data.length / MAX_CARDS_PER_PAGE));
setIsLoading(false);
})
.catch((error) => {
console.error("Failed to fetch content:", error);
setIsLoading(false);
});
}, [refreshKey]);
if (token) {
apiCalls
.getContentList(token!)
.then((data) => {
setCards(data);
setMaxPages(Math.ceil(data.length / MAX_CARDS_PER_PAGE));
setIsLoading(false);
})
.catch((error) => {
console.error("Failed to fetch content:", error);
setIsLoading(false);
});
}
}, [refreshKey, token]);

if (isLoading) {
return (
Expand Down Expand Up @@ -180,6 +189,10 @@ const CardsGrid = ({ displayLanguage }: { displayLanguage: string }) => {
onFailedDelete={(content_id: number) => {
setSnackMessage(`Failed to delete content #${content_id}`);
}}
deleteContent={(content_id: number) => {
return apiCalls.deleteContent(content_id, token!);
}}
editAccess={accessLevel === "fullaccess"}
/>
</Grid>
))}
Expand Down
10 changes: 4 additions & 6 deletions admin_app_2/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import NavBar from "@/components/NavBar";
import theme from "@/theme";
import AuthProvider from "@/utils/auth";
import { CssBaseline, ThemeProvider } from "@mui/material";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import React from "react";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
Expand All @@ -25,8 +24,7 @@ export default function RootLayout({
<body className={inter.className}>
<ThemeProvider theme={theme}>
<CssBaseline />
<NavBar />
{children}
<AuthProvider>{children}</AuthProvider>
</ThemeProvider>
</body>
</html>
Expand Down
Loading