([]);
+
+ useEffect(() => {
+ const fetchAllOrgs = async () => {
+ const { data, error } = await supabase
+ .from("organizations")
+ .select("*");
+ if (error || !data) {
+ enqueueSnackbar(
+ "Failed to load organizations. Contact it@stuysu.org for support.",
+ { variant: "error" },
+ );
+ return;
+ }
+ setAllOrgs(data);
+ };
+
+ fetchAllOrgs();
+ }, [enqueueSnackbar]);
+
+ useEffect(() => {
+ if (searchInput) {
+ setFilteredOrgs(
+ allOrgs.filter((org) =>
+ org.name.toLowerCase().includes(searchInput.toLowerCase()),
+ ),
+ );
+ } else {
+ setFilteredOrgs([]);
+ }
+ }, [searchInput, allOrgs]);
+
+ useEffect(() => {
+ if (!orgId) return;
+
+ const fetchOrgStrikes = async () => {
+ const { data, error } = await supabase
+ .from("strikes")
+ .select(
+ `
+ id,
+ reason,
+ created_at,
+ organizations (name),
+ users (first_name, last_name, picture)
+ `,
+ )
+ .eq("organization_id", orgId);
+
+ if (error || !data) {
+ return enqueueSnackbar(
+ "Failed to load strikes. Contact it@stuysu.org for support.",
+ { variant: "error" },
+ );
+ }
+
+ setOrgStrikes(data as Strike[]);
+ };
+
+ fetchOrgStrikes();
+ }, [orgId, enqueueSnackbar]);
+
+ const issueStrike = async () => {
+ const { data, error } = await supabase.functions.invoke(
+ "issue-strike",
+ {
+ body: {
+ organization_id: orgId,
+ reason,
+ },
+ },
+ );
+
+ if (error) {
+ enqueueSnackbar(
+ "Error issuing strike. Contact it@stuysu.org for support",
+ { variant: "error" },
+ );
+ return;
+ }
+
+ setOrgStrikes([...orgStrikes, data as Strike]);
+ enqueueSnackbar("Strike issued!", { variant: "success" });
+ setReason("");
+ };
+
+ return (
+
+
+ Strikes
+
+
+ setSearchInput(e.target.value)}
+ />
+
+ {filteredOrgs.length > 0 && (
+
+ {filteredOrgs.map((org) => (
+ {
+ setOrgId(org.id);
+ setOrgName(org.name);
+ setSearchInput("");
+ setFilteredOrgs([]);
+ }}
+ sx={{ margin: "5px" }}
+ >
+ {org.name}
+
+ ))}
+
+ )}
+ {orgId && (
+ <>
+
+
+ Org: {orgName}
+
+
+
+ Give Strike
+
+ setReason(e.target.value)}
+ multiline
+ rows={4}
+ />
+
+ Issue
+
+
+
+
+
+ {orgStrikes.map((strike, i) => (
+
+
+
+ {strike.reason}
+
+
+ Issued by {strike.users?.first_name}{" "}
+ {strike.users?.last_name}
+
+ {
+ const { error } = await supabase
+ .from("strikes")
+ .delete()
+ .eq("id", strike.id);
+
+ if (error) {
+ enqueueSnackbar(
+ "Error deleting strike. Contact it@stuysu.org for support",
+ { variant: "error" },
+ );
+ }
+
+ setOrgStrikes(
+ orgStrikes.filter(
+ (s) => s.id !== strike.id,
+ ),
+ );
+ enqueueSnackbar("Strike deleted!", {
+ variant: "success",
+ });
+ }}
+ >
+ Delete
+
+
+
+ ))}
+
+ >
+ )}
+
+ );
+};
+
+export default Strikes;
diff --git a/src/pages/admin/index.tsx b/src/pages/admin/index.tsx
index da3be39..c4fc30f 100644
--- a/src/pages/admin/index.tsx
+++ b/src/pages/admin/index.tsx
@@ -1,39 +1,41 @@
-import { Routes, Route } from "react-router-dom";
-
-import { useContext } from "react";
-import UserContext from "../../comps/context/UserContext";
-
-import AdminNav from "../../comps/admin/AdminNav";
-
-/* MODULES */
-import ApprovePending from "./ApprovePending";
-import ApproveEdit from "./ApproveEdit";
-import Strikes from "./Strikes";
-import SendMessage from "./SendMessage";
-import Announcements from "./Announcements";
-import Rooms from "./Rooms";
-
-const AdminRouter = () => {
- const user = useContext(UserContext);
-
- if (!user.admin) {
- return You do not have access to this page.
;
- }
-
- return (
-
- );
-};
-
-export default AdminRouter;
+import { Routes, Route } from "react-router-dom";
+
+import { useContext } from "react";
+import UserContext from "../../comps/context/UserContext";
+
+import AdminNav from "../../comps/admin/AdminNav";
+
+/* MODULES */
+import ApprovePending from "./ApprovePending";
+import ApproveEdit from "./ApproveEdit";
+import Strikes from "./Strikes";
+import SendMessage from "./SendMessage";
+import Announcements from "./Announcements";
+import Rooms from "./Rooms";
+import ClubAdminEmails from "./ClubAdminEmails";
+
+const AdminRouter = () => {
+ const user = useContext(UserContext);
+
+ if (!user.admin) {
+ return You do not have access to this page.
;
+ }
+
+ return (
+
+ );
+};
+
+export default AdminRouter;
diff --git a/src/pages/orgs/Posts.tsx b/src/pages/orgs/Posts.tsx
new file mode 100644
index 0000000..db36769
--- /dev/null
+++ b/src/pages/orgs/Posts.tsx
@@ -0,0 +1,38 @@
+import { useContext, useState, useEffect } from "react";
+import OrgContext from "../../comps/context/OrgContext";
+import { Box, Grid, Typography } from "@mui/material";
+import Post from "../../comps/pages/orgs/Post";
+
+const Posts = () => {
+ const [posts, setPosts] = useState([]);
+
+ const organization: OrgContextType = useContext(OrgContext);
+
+ useEffect(() => {
+ setPosts(organization.posts.reverse());
+ }, []);
+
+ return (
+
+
+ Posts
+
+
+ {posts.map((post) => (
+
+
+
+
+
+ ))}
+
+
+ );
+};
+
+export default Posts;
diff --git a/src/pages/orgs/admin/MemberRequests.tsx b/src/pages/orgs/admin/MemberRequests.tsx
index 29e3c26..2dc40fd 100644
--- a/src/pages/orgs/admin/MemberRequests.tsx
+++ b/src/pages/orgs/admin/MemberRequests.tsx
@@ -1,40 +1,67 @@
-import { useContext } from "react";
-import OrgContext from "../../../comps/context/OrgContext";
-
-import PendingMember from "../../../comps/pages/orgs/admin/PendingMember";
-import { Box, Typography } from "@mui/material";
-
-const MemberRequests = () => {
- const organization = useContext(OrgContext);
- const pendingMembers = organization.memberships
- ?.filter((member) => !member.active)
- .map((member) => {
- return {
- first_name: member.users?.first_name,
- last_name: member.users?.last_name,
- email: member.users?.email,
- membershipId: member.id,
- picture: member.users?.picture,
- };
- });
-
- return (
-
-
- Member Requests
-
- {pendingMembers?.map((member, i) => (
-
- ))}
-
- );
-};
-
-export default MemberRequests;
+import { useContext, useState } from "react";
+import OrgContext from "../../../comps/context/OrgContext";
+
+import PendingMember from "../../../comps/pages/orgs/admin/PendingMember";
+import { Box, Typography } from "@mui/material";
+import AsyncButton from "../../../comps/ui/AsyncButton";
+
+const MemberRequests = () => {
+ const organization = useContext(OrgContext);
+ const [autoApprove, setAutoApprove] = useState(false);
+
+ const pendingMembers = organization.memberships
+ ?.filter((member) => !member.active)
+ .map((member) => {
+ return {
+ first_name: member.users?.first_name,
+ last_name: member.users?.last_name,
+ email: member.users?.email,
+ membershipId: member.id,
+ picture: member.users?.picture,
+ };
+ });
+
+ const handleApproveAll = () => {
+ setAutoApprove(true);
+ };
+
+ return (
+
+
+ Member Requests
+
+
+
+ Approve ALL
+
+
+
+ {pendingMembers?.map((member, i) => (
+
+ ))}
+
+ );
+};
+
+export default MemberRequests;
diff --git a/src/pages/orgs/index.tsx b/src/pages/orgs/index.tsx
index 5e9d577..efe3275 100644
--- a/src/pages/orgs/index.tsx
+++ b/src/pages/orgs/index.tsx
@@ -1,188 +1,190 @@
-/* ORG ROUTING INFORMATION HERE */
-import { useEffect, useState } from "react";
-import { Routes, Route, useParams, useNavigate } from "react-router-dom";
-import OrgContext from "../../comps/context/OrgContext";
-import Loading from "../../comps/ui/Loading";
-import { supabase } from "../../supabaseClient";
-
-import OrgNav from "../../comps/pages/orgs/OrgNav";
-
-import NotFound from "./NotFound";
-import Overview from "./Overview";
-import Charter from "./Charter";
-import Meetings from "./Meetings";
-import Members from "./Members";
-import OrgAdminRouter from "./admin";
-import { useSnackbar } from "notistack";
-import { Box, useMediaQuery } from "@mui/material";
-import AsyncButton from "../../comps/ui/AsyncButton";
-
-const OrgRouter = () => {
- const { enqueueSnackbar } = useSnackbar();
- const { orgUrl } = useParams();
-
- const isMobile = useMediaQuery("(max-width: 1000px)");
- const navigate = useNavigate();
-
- const [org, setOrg] = useState({
- id: -1,
- name: "",
- url: "",
- picture: "",
- mission: "",
- purpose: "",
- goals: "",
- appointment_procedures: "",
- uniqueness: "",
- meeting_description: "",
- meeting_schedule: "",
- meeting_days: [],
- commitment_level: "NONE",
- state: "PENDING",
- joinable: false,
- join_instructions: "",
- memberships: [],
- meetings: [],
- posts: [],
- });
- const [loading, setLoading] = useState(true);
-
- useEffect(() => {
- const getOrgData = async () => {
- const { data, error } = await supabase
- .from("organizations")
- .select(
- `
- id,
- name,
- socials,
- url,
- picture,
- purpose,
- goals,
- appointment_procedures,
- uniqueness,
- meeting_description,
- meeting_schedule,
- meeting_days,
- commitment_level,
- keywords,
- tags,
- faculty_email,
- fair,
- state,
- joinable,
- join_instructions,
- memberships (
- id,
- role,
- role_name,
- active,
- users (
- id,
- first_name,
- last_name,
- email,
- picture,
- is_faculty
- )
- ),
- meetings (
- id,
- is_public,
- title,
- description,
- start_time,
- end_time,
- rooms (
- id,
- name,
- floor
- )
- ),
- posts (
- id,
- title,
- description,
- created_at,
- updated_at,
- organizations (
- name,
- picture,
- id
- )
- )
- `,
- )
- .ilike("url", orgUrl || "");
-
- if (error) {
- enqueueSnackbar("Error fetching organization.", {
- variant: "error",
- });
- return;
- }
-
- if (data?.length === 0) {
- return;
- }
-
- setOrg(data[0] as OrgContextType);
- };
-
- getOrgData().then(() => setLoading(false));
- }, [orgUrl, enqueueSnackbar]);
-
- if (loading) return ;
- return (
-
- {org.id === -1 ? (
-
- ) : (
- <>
-
- navigate("/catalog")}
- variant="contained"
- sx={{ width: "80px" }}
- >
- Back
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- )}
-
- );
-};
-
-export default OrgRouter;
+/* ORG ROUTING INFORMATION HERE */
+import { useEffect, useState } from "react";
+import { Routes, Route, useParams, useNavigate } from "react-router-dom";
+import OrgContext from "../../comps/context/OrgContext";
+import Loading from "../../comps/ui/Loading";
+import { supabase } from "../../supabaseClient";
+
+import OrgNav from "../../comps/pages/orgs/OrgNav";
+
+import NotFound from "./NotFound";
+import Overview from "./Overview";
+import Charter from "./Charter";
+import Meetings from "./Meetings";
+import Members from "./Members";
+import Posts from "./Posts";
+import OrgAdminRouter from "./admin";
+import { useSnackbar } from "notistack";
+import { Box, useMediaQuery } from "@mui/material";
+import AsyncButton from "../../comps/ui/AsyncButton";
+
+const OrgRouter = () => {
+ const { enqueueSnackbar } = useSnackbar();
+ const { orgUrl } = useParams();
+
+ const isMobile = useMediaQuery("(max-width: 1000px)");
+ const navigate = useNavigate();
+
+ const [org, setOrg] = useState({
+ id: -1,
+ name: "",
+ url: "",
+ picture: "",
+ mission: "",
+ purpose: "",
+ goals: "",
+ appointment_procedures: "",
+ uniqueness: "",
+ meeting_description: "",
+ meeting_schedule: "",
+ meeting_days: [],
+ commitment_level: "NONE",
+ state: "PENDING",
+ joinable: false,
+ join_instructions: "",
+ memberships: [],
+ meetings: [],
+ posts: [],
+ });
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ const getOrgData = async () => {
+ const { data, error } = await supabase
+ .from("organizations")
+ .select(
+ `
+ id,
+ name,
+ socials,
+ url,
+ picture,
+ purpose,
+ goals,
+ appointment_procedures,
+ uniqueness,
+ meeting_description,
+ meeting_schedule,
+ meeting_days,
+ commitment_level,
+ keywords,
+ tags,
+ faculty_email,
+ fair,
+ state,
+ joinable,
+ join_instructions,
+ memberships (
+ id,
+ role,
+ role_name,
+ active,
+ users (
+ id,
+ first_name,
+ last_name,
+ email,
+ picture,
+ is_faculty
+ )
+ ),
+ meetings (
+ id,
+ is_public,
+ title,
+ description,
+ start_time,
+ end_time,
+ rooms (
+ id,
+ name,
+ floor
+ )
+ ),
+ posts (
+ id,
+ title,
+ description,
+ created_at,
+ updated_at,
+ organizations (
+ name,
+ picture,
+ id
+ )
+ )
+ `,
+ )
+ .ilike("url", orgUrl || "");
+
+ if (error) {
+ enqueueSnackbar("Error fetching organization.", {
+ variant: "error",
+ });
+ return;
+ }
+
+ if (data?.length === 0) {
+ return;
+ }
+
+ setOrg(data[0] as OrgContextType);
+ };
+
+ getOrgData().then(() => setLoading(false));
+ }, [orgUrl, enqueueSnackbar]);
+
+ if (loading) return ;
+ return (
+
+ {org.id === -1 ? (
+
+ ) : (
+ <>
+
+ navigate("/catalog")}
+ variant="contained"
+ sx={{ width: "80px" }}
+ >
+ Back
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+ );
+};
+
+export default OrgRouter;