diff --git a/app/(Admin Dashboard)/admin/page.tsx b/app/(Admin Dashboard)/admin/page.tsx index 78e399c..0052843 100644 --- a/app/(Admin Dashboard)/admin/page.tsx +++ b/app/(Admin Dashboard)/admin/page.tsx @@ -58,11 +58,13 @@ export default function Admin() { Admin Login - - - - - + + + + + + + diff --git a/app/(Admin Dashboard)/components/navbar.tsx b/app/(Admin Dashboard)/components/navbar.tsx index 782c52d..786aadd 100644 --- a/app/(Admin Dashboard)/components/navbar.tsx +++ b/app/(Admin Dashboard)/components/navbar.tsx @@ -19,6 +19,7 @@ import { Heading, Center, Card, + StackProps, } from "@chakra-ui/react"; import { MdBrightness4 as MdMoon, @@ -63,38 +64,39 @@ export default function Navbar() { const [open, setOpen] = useState(false) // Container props - const ContainerProps = { - h: { mobile: "10dvh", tablet: "30dvh", laptop: "50dvh", xLarge: "70dvh", "2XLarge": "90dvh" }, //"2XLarge": "10dvh", + const ContainerProps: StackProps = { + h: { base: "12dvh" }, //"2XLarge": "10dvh", zIndex: 2, //2, py: { base: 5, mdTo2xl: 8 },//isFixed ? (notMobileDevice ? 8 : 2) : notMobileDevice ? 8 : 5, boxShadow: { base: "2xl" },//isFixed ? "2xl" : "none", bg: { - base: colorMode === "light" - ? "black" - : "blackAlpha.950" - , - aboveBase: colorMode === "light" - ? "black" - : "blackAlpha.950" + base: "black", }, - w: "100dvw", + w: "100%", className: openSans.className,//openSans.className, justifyContent: "space-between", - } as const; + + }; // Nav text props - const navTextProps = { + const navTextProps: StackProps = { + fontSize: "16px", + fontWeight: 600, + _light: { color: "white" }, + }; + // Mobile nav text props + const mobileNavTextProps: StackProps = { fontSize: "16px", fontWeight: 600, _light: { color: "white" }, - } as const; + }; return ( - + - + About @@ -175,9 +177,9 @@ export default function Navbar() { {/* Mobile Menu */} - setOpen(e.open)} > - - + setOpen(e.open)} > + + Menu @@ -195,24 +197,24 @@ export default function Navbar() { - About + About - Contact + Contact - Services + Services - + {/* Float the badge to the above the text */} Programs @@ -227,7 +229,7 @@ export default function Navbar() { - + {/* Float the badge to the above the text */} Resources diff --git a/app/(Public Pages)/(About)/about/page.tsx b/app/(Public Pages)/(About)/about/page.tsx index f0568d9..dedf51a 100644 --- a/app/(Public Pages)/(About)/about/page.tsx +++ b/app/(Public Pages)/(About)/about/page.tsx @@ -1,7 +1,6 @@ "use client"; import NextImage from "next/image"; import TeamMemberCard from "@/components/about/team-member-card"; -// import { GemIcon } from '@/components/ui/icons'; import { executiveBoard, teamMembers } from "@/data/team"; import { Container, @@ -9,191 +8,223 @@ import { Text, AbsoluteCenter, VStack, - HStack, + Stack, Heading, Link as ChakraLink, SimpleGrid, Image as ChakraImage, Card, Avatar, + Center, } from "@chakra-ui/react"; import { poppins } from "@/components/ui/fonts"; import NextLink from "next/link"; -import checkDeviceSize from "@/components/ui/breakpoints"; import { Icon } from "@/components/ui/icons/icon"; export default function AboutUs() { - const notMobileDevice = checkDeviceSize(); return ( - <> - {notMobileDevice ? ( - - - + + + + - - - - - About Us - - - - Our organization strives to break down barriers and stop the - stigma associated with incarceration through technical - assistance, consulting services, educational conferences, - and business support programs. - - - - - - {/* ABOUT US */} - - - - - - - - Vision - - A society where all individuals have equal opportunities to - thrive, learn, and lead. Empowered to contribute positively - to their communities without the stigma or limitations from - their past. - - - - - - - - - Mission - - To promote education, empowerment, and entrepreneurship - among incarcerated learners and individuals. Our - organization strives to break down barriers and stop the - stigma associated with incarceration through consulting - services, educational conferences, and business support - programs. - - - - - - - Executive Board Members + + + About Us + - - {executiveBoard.map((member) => ( - - ))} - - - - - Our Team + Our organization strives to break down barriers and stop the + stigma associated with incarceration through technical + assistance, consulting services, educational conferences, + and business support programs. + + + + + + + + + + + + + + + Vision - - {teamMembers.map((member) => ( - - ))} - - - - - Our Partners + + A society where all individuals have equal opportunities to + thrive, learn, and lead. Empowered to contribute positively + to their communities without the stigma or limitations from + their past. + + + + + + + + + + + Mission - - Join us in creating meaningful change through collaborative - projects and shared resources. + + To promote education, empowerment, and entrepreneurship + among incarcerated learners and individuals. Our + organization strives to break down barriers and stop the + stigma associated with incarceration through consulting + services, educational conferences, and business support + programs. - - - - - - - - - - - - - - - - - - - - - - - - ) : null} - > + + + + + + + Executive Board Members + + + + {executiveBoard.map((member) => ( + + + + ))} + + + + + + + Our Team + + + {teamMembers.map((member) => ( + + + + ))} + + + + + + Our Partners + + + Join us in creating meaningful change through collaborative + projects and shared resources. + + + + + + + + + + + + + + + + + + + + + + + + ); -} +} \ No newline at end of file diff --git a/app/(Public Pages)/(Contact)/contact/page.tsx b/app/(Public Pages)/(Contact)/contact/page.tsx index aebf4cd..0c000ca 100644 --- a/app/(Public Pages)/(Contact)/contact/page.tsx +++ b/app/(Public Pages)/(Contact)/contact/page.tsx @@ -1,23 +1,22 @@ "use client"; -import Image from "next/image"; +import NextLink from "next/link"; import ContactForm from "@/components/contact/contact-form"; import { contactInfo, socialLinks, mapEmbedUrl } from "@/data/contact"; -import NextLink from "next/link"; import { Box, Text, HStack, + Stack, Heading, Card, Link as ChakraLink, - Image as ChakraImage, Avatar, VStack, + SimpleGrid, } from "@chakra-ui/react"; -import checkDeviceSize from "@/components/ui/breakpoints"; import { HeaderTemplate, PageBuilder, @@ -25,201 +24,117 @@ import { } from "@/components/page-builder/template"; import { Icon } from "@/components/ui/icons/icon"; import { poppins } from "@/components/ui/fonts"; -import { Section } from "lucide-react"; export default function Contact() { - const notMobileDevice = checkDeviceSize(); return ( - <> - {notMobileDevice ? ( - - - - - - Get in Touch - - We're here to support you. Reach out to learn more about our - services, volunteer opportunities, and ways to contribute - - - - {socialLinks.map((link) => ( - - - - {link.platform} - - - ))} - - {/* Contact Info Cards Section */} - - {contactInfo.map((info) => { - info.value ? ( - {info.value} - ) : ( - {info.value} - ); + + - return ( - - - - - - - {info.label} - - {info.value} - - - ); - })} - - + + + + + Get in Touch + + + We're here to support you. Reach out to learn more about our + services, volunteer opportunities, and ways to contribute. + + - {/* Google Maps Embed Section */} - - - - - {/* Contact Form Section */} - - - - - - - - - ) : ( - <> - - {/* Hero Section */} - - - - - - Contact Us - - Find out how you can contribute and make a positive impact in - your community - - - - - {/* Get In Touch Section */} - - - Get in Touch - - We're here to support you. Reach out to learn more about - our services, volunteer opportunities, and ways to contribute - - - {socialLinks.map((link) => ( - + {socialLinks.map((link) => ( + + + + - - {link.platform} - - ))} - - - - - {/* Contact Info Cards Section */} - - - {contactInfo.map((info) => { - const content = info.phoneNumber ? ( - {info.value} - ) : ( - {info.value} - ); - - return ( - - hello - {info.icon} - {info.label} - {content} - - ); - })} - - + /> + + {link.platform} + + + + + ))} + - {/* Google Maps Embed Section */} - - - - - + {/* Contact Info Cards - Responsive Grid to stack on mobile, 3 columns on desktop */} + + {contactInfo.map((info) => { + return ( + + + + + + + {info.label} + + {info.phoneNumber ? ( + + {info.value} + + ) : ( + {info.value} + )} + + + ); + })} + + - {/* Contact Form Section */} - - - - - - - ) - > - )} - > + {/* Map & Form Section - Side by Side on Desktop, Stacked on Mobile */} + + + + + + + + + + ); -} +} \ No newline at end of file diff --git a/app/(Public Pages)/(Home)/components/Pictures.tsx b/app/(Public Pages)/(Home)/components/Pictures.tsx new file mode 100644 index 0000000..f39b940 --- /dev/null +++ b/app/(Public Pages)/(Home)/components/Pictures.tsx @@ -0,0 +1,69 @@ +import { Box, Center, Container, Grid, GridItem, SimpleGrid } from "@chakra-ui/react"; + +export default function Pictures() { + const ImageSrcs = ['/assets/home/IMG_1011-300x300.webp', '/assets/home/IMG_1012-300x300.webp', '/assets/home/IMG_1027-300x300.webp', '/assets/home/IMG_0995-300x300.webp'] + + return ( + + + + + + + + + + + + + + {ImageSrcs.map((src, index) => ( + + + + + + + ))} + + + ) +} \ No newline at end of file diff --git a/app/(Public Pages)/(Home)/page.tsx b/app/(Public Pages)/(Home)/page.tsx index 8bce2ef..f5c5965 100644 --- a/app/(Public Pages)/(Home)/page.tsx +++ b/app/(Public Pages)/(Home)/page.tsx @@ -22,41 +22,42 @@ import { Image as ChakraImage, HStack, AspectRatio, + Grid, } from "@chakra-ui/react"; import { poppins } from "@/components/ui/fonts"; // import { openSans } from "@/components/ui/fonts"; import { Icon } from "@/components/ui/icons/icon"; +import Pictures from "./components/Pictures"; export default function Home() { return ( - + - - + + Empowering change through @@ -64,12 +65,13 @@ export default function Home() { advocacy - + We strive to break down barriers and stop the stigma associated with incarceration through @@ -78,12 +80,12 @@ export default function Home() { - - + @@ -134,8 +136,8 @@ export default function Home() { - - + + - + - + @@ -199,7 +201,7 @@ export default function Home() { - Get Involved! - + Are you passionate about helping justice-impacted individuals? We need compassionate volunteers to assist in @@ -207,17 +209,17 @@ export default function Home() { administrative support. - + Get Involved - ( ))} - + - Donate + Donate - + + maxW={{ base: "100%", md: "100%" }} + minW={{ base: "100%", md: "100px" }} + maxH={{ base: "450px", md: "100%" }} + minH={{ base: "100%", md: "100px" }} + ratio={16 / 9}> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ); } diff --git a/app/(Public Pages)/(Programs)/programs/navigators-network/page.tsx b/app/(Public Pages)/(Programs)/programs/navigators-network/page.tsx index 2f270ab..5033309 100644 --- a/app/(Public Pages)/(Programs)/programs/navigators-network/page.tsx +++ b/app/(Public Pages)/(Programs)/programs/navigators-network/page.tsx @@ -1,6 +1,6 @@ "use client"; import { HeaderTemplate, PageBuilder, SectionTemplate } from '@/components/page-builder/template'; -import { Button, Link as ChakraLink, Text, Image, HStack, Center, VStack, Box, Heading, List, Card } from "@chakra-ui/react"; +import { Button, Link as ChakraLink, Text, Image as ChakraImage, Stack, Center, VStack, Box, Heading, List, Card } from "@chakra-ui/react"; import NextLink from "next/link"; import NextImage from "next/image"; @@ -9,127 +9,157 @@ export default function NavigatorsNetwork() { + + {/* SECTION 1: Intro */} - - - - - Navigator's Network - Navigator's Network is launching as a collaboration platform for organizations that want to improve access, coordination, and real-world outcomes. - - - - Get Launch Updates - - - - - - - - Built for Organizations That Want to Work Better Together - Navigator's Network connects: - - Service providers - Government and community agencies - Community-focused businesses - - So they can: - - Share reliable referral pathways - Coordinate support across systems - Work from the same playbook - - - - - + + + + + + + + Navigator's Network + + Navigator's Network is launching as a collaboration platform for organizations that want to improve access, coordination, and real-world outcomes. + + + + + Get Launch Updates + + + + + + + {/* SECTION 2: Built for Organizations */} - - - + + {/* Grouped the text and lists together so they form one half of the layout */} + + + Built for Organizations That Want to Work Better Together + + + + Navigator's Network connects: + + Service providers + Government and community agencies + Community-focused businesses + + + + + So they can: + + Share reliable referral pathways + Coordinate support across systems + Work from the same playbook + + + + + + - - - - - - Launching Soon — Now Onboarding Partners - - We are actively building the platform and onboarding early partners. - - - Organizations that sign up now will receive: - - - Early access opportunities - Partnership details - Feature updates as they go live - Shared resource announcements - - - + + + + - - + {/* SECTION 3: Launching Soon */} + + + + + + + + - - + + + Launching Soon — Now Onboarding Partners + + + We are actively building the platform and onboarding early partners. + + + Organizations that sign up now will receive: + + Early access opportunities + Partnership details + Feature updates as they go live + Shared resource announcements + + + + + + {/* SECTION 4: Get In Touch */} - - - - - Get In Touch - - Christiana "Sunshine" Longway - Sunshine@mokse.org - - {/*BUTTON GOES TO TOP OF PAGE */} - Launching April 23rd, 2026 - - + + + + Get In Touch + + + Christiana "Sunshine" Longway + + + Sunshine@mokse.org + - - - - - - + + Launching April 23rd, 2026 + + + + + + + + + - - - ) + + ); } \ No newline at end of file diff --git a/app/(Public Pages)/(Programs)/programs/page.tsx b/app/(Public Pages)/(Programs)/programs/page.tsx index d2c64ab..886ed15 100644 --- a/app/(Public Pages)/(Programs)/programs/page.tsx +++ b/app/(Public Pages)/(Programs)/programs/page.tsx @@ -1,181 +1,242 @@ "use client"; -import { BodyTemplate, HeaderTemplate, PageBuilder, SectionTemplate } from "@/components/page-builder/template"; -import { Box, Button, Card, Center, Container, Flex, Float, HStack, Portal, ScrollArea, Stack, Tabs, Tag, VStack, Icon as ChakraIcon, ClientOnly, Image } from "@chakra-ui/react"; +import { HeaderTemplate, PageBuilder, SectionTemplate } from "@/components/page-builder/template"; +import { Box, Button, Center, Flex, Float, HStack, Stack, Tabs, Tag, ClientOnly, Image as ChakraImage, SimpleGrid, useBreakpointValue } from "@chakra-ui/react"; import NavigatorsNetwork from "./navigators-network/page"; import StopTheStigma from "./stop-the-stigma/page"; import NextImage from "next/image"; import { Tooltip } from "@/components/ui/tooltip"; import { Icon } from "@/components/ui/icons/icon"; -import { useState, useRef } from "react"; -import { usePathname } from "next/navigation"; -import { FaAngleRight } from "react-icons/fa6"; - +import { useState } from "react"; export default function Programs() { const [showPrograms, setShowPrograms] = useState(true); + const orientation = useBreakpointValue<"horizontal" | "vertical">({ + base: "horizontal", + md: "vertical", + }); + return ( - - - - - - - All Programs - - - Stop The Stigma - - - Navigators Network - - - - - setShowPrograms(!showPrograms)}> Go Back - - + {/* 1. Mobile First Header: Tall on phones, shorter on desktops */} + + + {/* 2. Mobile First Wrapper: Auto height on phones to prevent scrolling bugs, fixed min-height on desktop */} + + + {/* 3. Mobile First Tabs: Horizontal on phones/tablets, Vertical only on large desktops */} + + + + All Programs + + + Stop The Stigma + + + Navigators Network + + + + {/* MAIN CONTENT PANE */} + + + {/* Universal Toggle Button - Hidden on mobile/tablet, only appears on large screens */} + + setShowPrograms(!showPrograms)} + > + + {showPrograms ? "Collapse" : "Expand"} Menu + + + + + - - - - - - - - }> - - - - - - - - - Stop The Stigma - - description - - - - - - Label - - - - - {"Category"} - - - - - - - - }> - - - - - - - - Navigators Network - - description - - - - - - Label - - - - - {"Category"} - - - - - - - - - + title="Programs" + description="Discover our innovative programs designed to empower and support justice-impacted individuals on their journey to reintegration and success. Explore our range of services, resources, and opportunities to get involved and make a positive impact in your community." + > + {/* 4. Mobile First Grid: 1 column on phones, 2 columns on tablets/desktops */} + + + {/* Program Card 1 */} + + + }> + + + + + + + + Stop The Stigma + + An annual conference centered on the stigma of disability and incarceration. + + + + + Conference + + + + Advocacy + + + + + + + {/* Program Card 2 */} + + + }> + + + + + + + + Navigators Network + + A collaboration platform for organizations that want to improve access and coordination. + + + + + Network + + + + Collaboration + + + + + + + - + - - - setShowPrograms(!showPrograms)} > Go Back - - - - - - - - - + + {/* Sub-Components */} + + + + - - - setShowPrograms(!showPrograms)} > Go Back - - - - - - - - - - - - + + + + + - - - - - ) + + + + + ); } \ No newline at end of file diff --git a/app/(Public Pages)/(Programs)/programs/stop-the-stigma/page.tsx b/app/(Public Pages)/(Programs)/programs/stop-the-stigma/page.tsx index fef2ee2..367b48b 100644 --- a/app/(Public Pages)/(Programs)/programs/stop-the-stigma/page.tsx +++ b/app/(Public Pages)/(Programs)/programs/stop-the-stigma/page.tsx @@ -9,7 +9,7 @@ import { Text, VStack, HStack, - Image, + Image as ChakraImage, Heading, Button, Strong, @@ -17,8 +17,6 @@ import { Float, Box, Container, - Flex, - AbsoluteCenter, SimpleGrid, } from "@chakra-ui/react"; import NextImage from "next/image"; @@ -27,206 +25,201 @@ import { poppins } from "@/components/ui/fonts"; import { HeaderTemplate, PageBuilder, - BodyTemplate, SectionTemplate, } from "@/components/page-builder/template"; import FeatureCard from "@/components/home/feature-card"; -import { - FaRegObjectGroup as FaObjectGroup, - FaRegListAlt as FaListAlt, - FaRegNewspaper as FaNewspaper, - FaRegKeyboard as FaKeyboard, -} from "react-icons/fa"; -import { MdBrightness5 as MdSun } from "react-icons/md"; export default function StopTheStigma() { - const [countdownTarget, setCountdownTarget] = useState<{ - target: number; - }>({ - // Set the date we're counting down to + const [countdownTarget] = useState({ target: new Date("Feb 19, 2026 00:00:00").getTime(), }); - const [countdown, setCountdown] = useState<{ - days: number | string; - hours: number | string; - minutes: number | string; - seconds: number | string; - }>({ - // Initial time values - days: 0, - hours: 0, - minutes: 0, - seconds: 0, + + const [countdown, setCountdown] = useState({ + days: 0 as number | string, + hours: 0 as number | string, + minutes: 0 as number | string, + seconds: 0 as number | string, }); useEffect(() => { const updateTimer = setInterval(() => { - // Get today's date and time const now = new Date().getTime(); - // Find the distance between now and the countdown date const distance = countdownTarget.target - now; - // If the count down is over, write some text + if (distance < 0) { clearInterval(updateTimer); - setCountdown((prev) => ({ - ...prev, + setCountdown({ days: "O", hours: "V", minutes: "E", seconds: "R", - })); + }); return; } - setCountdown((prev) => ({ - ...prev, + + setCountdown({ days: Math.floor(distance / (1000 * 60 * 60 * 24)), - hours: Math.floor( - (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60), - ), + hours: Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)), minutes: Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)), seconds: Math.floor((distance % (1000 * 60)) / 1000), - })); + }); }, 1000); return () => clearInterval(updateTimer); - }, []); + }, [countdownTarget.target]); - const { colorMode, toggleColorMode } = useColorMode(); return ( - <> - - - - - - {({ - label, - value, - }: { - label: string; - value: number | string; - }) => { - return ( - - - - - {value} - {label} - - - - - ); - }} - - - - + + + {/* Adjusted the Float offset and card sizing so it doesn't break mobile viewports */} + + + + {({ label, value }) => ( + + + + + + {value} + + + {label} + + + + + + )} + + + + - - - - - - - - - - What is STOP THE STIGMA? - - - STOP THE STIGMA is an annual conference centered - on the stigma of disability and incarceration. Now in its fourth - year the conference continues to provide a space for justice - impacted individuals to have their voices and stories heard. - Presented by Mokse and The Community, STOP THE STIGMA integrates - innovative media, storytelling, and design to engage audiences and - amplify impact. Together, we build an inclusive platform to - challenge assumptions and inspire action. - - - - - Register Here - - - - - - - - {/* + {/* SECTION: What is Stop The Stigma */} + + + {/* Replaced fixed Flex with a responsive Stack that stacks vertically on mobile */} + + + + + + - */} - + + + What is STOP THE STIGMA? + + + STOP THE STIGMA is an annual conference centered + on the stigma of disability and incarceration. Now in its fourth + year the conference continues to provide a space for justice + impacted individuals to have their voices and stories heard. + Presented by Mokse and The Community, STOP THE STIGMA integrates + innovative media, storytelling, and design to engage audiences and + amplify impact. Together, we build an inclusive platform to + challenge assumptions and inspire action. + + + + + Register Here + + + + + + + - - Conference Highlights + {/* SECTION: Highlights */} + {/* Moved background color to the Section wrapper to ensure it spans full bleed organically */} + + + + + Conference Highlights - - - - - - - - - - - - + {/* Replaced 40vw with fluid widths and updated columns to stack on mobile */} + + + + + + + + + - - - > + {/* FOOTER BANNER */} + + ); -} +} \ No newline at end of file diff --git a/app/(Public Pages)/(Resources)/resources/Navigators.tsx b/app/(Public Pages)/(Resources)/resources/Navigators.tsx index bbef404..6e1f88e 100644 --- a/app/(Public Pages)/(Resources)/resources/Navigators.tsx +++ b/app/(Public Pages)/(Resources)/resources/Navigators.tsx @@ -1,4 +1,5 @@ "use client"; + import { Box, Card, @@ -7,87 +8,69 @@ import { Portal, useFilter, useListCollection, - Group, ScrollArea, Center, Tag, - Stack, Image, + Stack, + Image, ClientOnly, } from "@chakra-ui/react"; -import NextImage from "next/image"; import { Tooltip } from "@/components/ui/tooltip"; import { AllResources } from "./mockIndex"; import { Icon } from "@/components/ui/icons/icon"; - import { resourceCollectionRegistry } from "./mockResourceRegistry"; - -import { useEffect, useRef, useState } from "react"; +import { useEffect, useState } from "react"; export default function Navigators() { - //Retrieve mock data from json file - const [searchlist, setSearchlist] = useState(null); - const { contains } = useFilter({ sensitivity: "base" }); - const [value, setValue] = useState("Initial value"); - const inputRef = useRef(null); - - const [formData, setFormData] = useState<{ - searchRegion: string; - searchCategory: string; - searchQuery: string; - }>({ - searchQuery: "", + const [formData, setFormData] = useState({ searchRegion: "", searchCategory: "", + searchQuery: "", }); - const regionCollection = resourceCollectionRegistry.Regions; - const categoryCollection = resourceCollectionRegistry.Categories; - const titleCollection = resourceCollectionRegistry.Titles; - - const { collection: regionDropDown, filter: filterRegions } = - useListCollection({ - initialItems: regionCollection.items, - itemToString: (item) => item.label, - filter: contains, - }); - const { collection: categoryDropDown, filter: filterCategories } = - useListCollection({ - initialItems: categoryCollection.items, - itemToString: (item) => item.label, - filter: contains, - }); - const { collection: titleDropDown, filter: filterTitles } = useListCollection( - { - initialItems: titleCollection.items, - itemToString: (item) => item.label, - filter: contains, - }, - ); - const [regionInput, setRegionInput] = useState(""); - const [categoryInput, setCategoryInput] = useState(""); - const [titleInput, setTitleInput] = useState(""); - + // Data States const [allResources, setAllResources] = useState(AllResources); const [filteredItems, setFilteredItems] = useState(AllResources); + // Dynamic Dropdown States const [dynamicRegions, setDynamicRegions] = useState(resourceCollectionRegistry.Regions.items); const [dynamicCategories, setDynamicCategories] = useState(resourceCollectionRegistry.Categories.items); const [dynamicTitles, setDynamicTitles] = useState(resourceCollectionRegistry.Titles.items); + // Chakra UI Collections (bound to dynamic state) + const { collection: regionDropDown, filter: filterRegions } = useListCollection({ + initialItems: dynamicRegions, + itemToString: (item) => item.label, + filter: contains, + }); + + const { collection: categoryDropDown, filter: filterCategories } = useListCollection({ + initialItems: dynamicCategories, + itemToString: (item) => item.label, + filter: contains, + }); + + const { collection: titleDropDown, filter: filterTitles } = useListCollection({ + initialItems: dynamicTitles, + itemToString: (item) => item.label, + filter: contains, + }); + + const [regionInput, setRegionInput] = useState(""); + const [categoryInput, setCategoryInput] = useState(""); + const [titleInput, setTitleInput] = useState(""); + // --- SILENT BACKGROUND FETCH TO UPGRADE DATA --- useEffect(() => { const fetchResources = async () => { try { const res = await fetch("/api/notion/database", { method: "POST" }); if (!res.ok) throw new Error("Failed to fetch Notion data"); - const data = await res.json(); - const formattedData = data.payload; - // Extract unique values const uniqueRegions = Array.from(new Set(formattedData.flatMap((item: any) => item.region))) .filter(Boolean) .map((region) => ({ label: String(region), value: String(region) })); @@ -100,313 +83,210 @@ export default function Navigators() { label: String(item.title), value: String(item.title) })); - // Overwrite the mock state with live Notion state setAllResources(formattedData); setFilteredItems(formattedData); setDynamicRegions(uniqueRegions); setDynamicCategories(uniqueCategories); setDynamicTitles(uniqueTitles); - } catch (error) { console.error("Notion fetch failed, falling back to mock JSON data:", error); - // We don't need to do anything here; the UI is already populated with AllResources! } }; - fetchResources(); }, []); + const applyFilters = () => { - const noFilters = - !formData.searchRegion && - !formData.searchCategory && - !formData.searchQuery; + const noFilters = !formData.searchRegion && !formData.searchCategory && !formData.searchQuery; + if (noFilters) { - setFilteredItems(AllResources); + setFilteredItems(allResources); return; } - let results = AllResources; + + let results = allResources; + if (formData.searchRegion) { - results = results.filter((resources) => - resources.region.includes(formData.searchRegion), - ); + results = results.filter((r) => r.region.includes(formData.searchRegion)); } if (formData.searchCategory) { - results = results.filter((resources) => - resources.category.includes(formData.searchCategory), - ); + results = results.filter((r) => r.category.includes(formData.searchCategory)); } if (formData.searchQuery) { const q = formData.searchQuery.toLowerCase(); results = results.filter( - (resources) => - resources.title.toLowerCase().includes(q) || - resources.description.toLowerCase().includes(q), + (r) => r.title.toLowerCase().includes(q) || r.description.toLowerCase().includes(q) ); } setFilteredItems(results); }; + return ( - - - { - const value = event?.inputValue; - setRegionInput(value); - setFormData((previousInfo) => ({ - ...previousInfo, - searchRegion: value, - })); - if (!value) { - filterRegions(""); - setFilteredItems(AllResources); - } else { - filterRegions(value); - applyFilters(); - } - }} - > - - { - const { value } = details?.currentTarget; - setRegionInput(value); - setFormData((previousInfo) => ({ - ...previousInfo, - searchRegion: value, - })); - if (!value) { - filterRegions(""); - setFilteredItems(AllResources); - } else { - filterRegions(value); - applyFilters(); - } - }} - onChange={(event) => { - const { value } = event?.target; - setRegionInput(value); - setFormData((previousInfo) => ({ - ...previousInfo, - searchRegion: value, - })); - if (!value) { - filterRegions(""); - setFilteredItems(AllResources); - } else { - filterRegions(value); - applyFilters(); - } - }} - /> - - - - - - - - - No items found - {regionDropDown.items.map((item) => ( - - {item.label} - - - ))} - - - - - { - const value = event?.inputValue; - setCategoryInput(value); - setFormData((previousInfo) => ({ - ...previousInfo, - searchCategory: value, - })); - if (!value) { - filterCategories(""); - setFilteredItems(AllResources); - } else { - filterCategories(value); - applyFilters(); - } - }} - > - - { - const { value } = details?.currentTarget; - setCategoryInput(value); - setFormData((previousInfo) => ({ - ...previousInfo, - searchCategory: value, - })); - if (!value) { - filterCategories(""); - setFilteredItems(AllResources); - } else { - filterCategories(value); - applyFilters(); - } - }} - onChange={(event) => { - const { value } = event?.target; - setCategoryInput(value); - setFormData((previousInfo) => ({ - ...previousInfo, - searchCategory: value, - })); - if (!value) { - filterCategories(""); - setFilteredItems(AllResources); - } - filterCategories(value); - applyFilters(); - }} - /> - - - - - - - - - No items found - {categoryDropDown.items.map((item) => ( - - {item.label} - - - ))} - - - - - { - const value = event?.inputValue; - setTitleInput(value); - setFormData((previousInfo) => ({ - ...previousInfo, - searchQuery: value, - })); - if (!value) { - filterTitles(""); - setFilteredItems(AllResources); - } - filterTitles(value); - applyFilters(); - }} - > - - { - const { value } = event?.target; - setTitleInput(value); - setFormData((prev) => ({ - ...prev, - searchQuery: value, - })); - if (!value) { - filterTitles(""); - setFilteredItems(AllResources); - } - filterTitles(value); - applyFilters(); - }} - onSelect={(details) => { - const { value } = details?.currentTarget; - setTitleInput(value); - setFormData((prev) => ({ - ...prev, - searchQuery: value, - })); - if (!value) { - filterTitles(""); - setFilteredItems(AllResources); - } - filterTitles(value); - applyFilters(); - }} - /> - - - - - - - - No items found - {titleDropDown.items.map((item) => ( - - {item.label} - - - ))} - - - - + + + {/* Responsive Layout Fix: Stacks vertically on mobile, horizontally on desktop */} + + + + { + const value = event?.inputValue || ""; + setRegionInput(value); + setFormData((prev) => ({ ...prev, searchRegion: value })); + if (!value) setFilteredItems(allResources); + else { filterRegions(value); applyFilters(); } + }} + > + + + + + + + + + + + No items found + {regionDropDown.items.map((item) => ( + + {item.label} + + + ))} + + + + + + + + { + const value = event?.inputValue || ""; + setCategoryInput(value); + setFormData((prev) => ({ ...prev, searchCategory: value })); + if (!value) setFilteredItems(allResources); + else { filterCategories(value); applyFilters(); } + }} + > + + + + + + + + + + + No items found + {categoryDropDown.items.map((item) => ( + + {item.label} + + + ))} + + + + + + + + { + const value = event?.inputValue || ""; + setTitleInput(value); + setFormData((prev) => ({ ...prev, searchQuery: value })); + if (!value) setFilteredItems(allResources); + else { filterTitles(value); applyFilters(); } + }} + > + + + + + + + + + + No items found + {titleDropDown.items.map((item) => ( + + {item.label} + + + ))} + + + + + + { + w={{ base: "100%", md: "auto" }} + onClick={() => { if (!titleInput && !categoryInput && !regionInput) { - filterTitles(""); - filterCategories(""); - filterRegions(""); - setFilteredItems(AllResources); + setFilteredItems(allResources); + } else { + applyFilters(); } - applyFilters(); - // await searchNotion(); }} aria-label="Search Resources" > + Search - + + {/* CARD TABLE SECTION */} - + {filteredItems.map((item) => ( - + }> - + - - - {item.title} + + + + {item.title} {item.description} - + - + - {item.region.length > 0 + {item.region.length > 1 ? `+${item.region.length} Regions` - : item.region} + : item.region[0]} - + {item.category.join(", ")} @@ -423,4 +303,4 @@ export default function Navigators() { ); -} +} \ No newline at end of file diff --git a/app/(Public Pages)/(Resources)/resources/page.tsx b/app/(Public Pages)/(Resources)/resources/page.tsx index 623b8ef..4859fcb 100644 --- a/app/(Public Pages)/(Resources)/resources/page.tsx +++ b/app/(Public Pages)/(Resources)/resources/page.tsx @@ -7,22 +7,12 @@ import { Input, InputGroup, Card, - HStack, + Stack, Heading, - Button, - Combobox, - Portal, useFilter, useListCollection, - Group, - ScrollArea, - Center, - Tag, - Stack, - Tabs, } from "@chakra-ui/react"; import { useRef, useState } from "react"; -import checkDeviceSize from "@/components/ui/breakpoints"; import { Icon } from "@/components/ui/icons/icon"; import { BodyTemplate, @@ -32,19 +22,14 @@ import { import { resourceCollectionRegistry } from "./mockResourceRegistry"; import { AllResources } from "./mockIndex"; -import { Tooltip } from "@/components/ui/tooltip"; import Navigators from "./Navigators"; -import Networks from "./Networks"; -import Calendar from "./Calendar"; + export default function SearchResources() { - //Retrieve mock data from json file const [searchlist, setSearchlist] = useState(null); - const { contains } = useFilter({ sensitivity: "base" }); - const [value, setValue] = useState("Initial value"); + const [value, setValue] = useState(""); const inputRef = useRef(null); - const notMobileDevice = checkDeviceSize(); const endElement = value ? ( item.label, filter: contains, - }, + } ); + const [regionInput, setRegionInput] = useState(""); const [categoryInput, setCategoryInput] = useState(""); const [titleInput, setTitleInput] = useState(""); @@ -107,12 +93,12 @@ export default function SearchResources() { let results = AllResources; if (formData.searchRegion) { results = results.filter((resources) => - resources.region.includes(formData.searchRegion), + resources.region.includes(formData.searchRegion) ); } if (formData.searchCategory) { results = results.filter((resources) => - resources.category.includes(formData.searchCategory), + resources.category.includes(formData.searchCategory) ); } if (formData.searchQuery) { @@ -120,55 +106,40 @@ export default function SearchResources() { results = results.filter( (resources) => resources.title.toLowerCase().includes(q) || - resources.description.toLowerCase().includes(q), + resources.description.toLowerCase().includes(q) ); } setFilteredItems(results); }; + return ( - <> - {notMobileDevice ? ( - <> - - - - - - - - - - - > - ) : ( - // This is a placeholder for the mobile view to be updated later - // Search - - - - - - Search - - { - setValue(e.currentTarget.value); - }} - /> - - - - + + + + + + {/* Unified Layout: Stacks vertically on mobile, horizontally on desktop */} + + + {/* Search/Filter Sidebar Area */} + + + {/* Main Content Area (Navigators / Results) */} + + + + + {/* Future implementation: Render your filteredItems here */} + + + + + - )} - > + + ); -} +} \ No newline at end of file diff --git a/app/(Public Pages)/(Services)/services/page.tsx b/app/(Public Pages)/(Services)/services/page.tsx index e041902..4a9d10d 100644 --- a/app/(Public Pages)/(Services)/services/page.tsx +++ b/app/(Public Pages)/(Services)/services/page.tsx @@ -1,10 +1,12 @@ +"use client"; + import Image from "next/image"; import NextLink from "next/link"; import ServiceCard from "@/components/services/service-card"; import SupportCard from "@/components/services/support-card"; import FaqItem from "@/components/services/faq-item"; import { services, supportOptions, faqItems } from "@/data/services"; -import { Link as ChakraLink, HStack, SimpleGrid } from "@chakra-ui/react"; +import { Link as ChakraLink, SimpleGrid, Stack } from "@chakra-ui/react"; import { HeaderTemplate, PageBuilder, @@ -14,49 +16,55 @@ import { export default function Services() { return ( - <> - - - - - - {services.map((service) => ( - - ))} - - - - + + + + + + {/* Swapped array syntax for explicit object mapping to ensure clean mobile scaling */} + + {services.map((service) => ( + + ))} + + + + {/* Converted HStack to a responsive Stack to ensure cards stack naturally on mobile rather than squishing */} + + {supportOptions.map((option) => ( + + ))} + + - - - - - - {supportOptions.map((option) => ( - - ))} - - - + {/* Wrapped the FAQ section in the template to maintain unified padding and margins */} + - - - > + + + ); -} +} \ No newline at end of file diff --git a/app/(Public Pages)/layout.tsx b/app/(Public Pages)/layout.tsx index 1ab212b..b5edd1c 100644 --- a/app/(Public Pages)/layout.tsx +++ b/app/(Public Pages)/layout.tsx @@ -1,4 +1,4 @@ -import type { Metadata } from "next"; +import type { Metadata, Viewport } from "next"; import { Open_Sans } from "next/font/google"; // import Footer from "@/components/common/footer"; import Footer from "@/app/(Admin Dashboard)/components/footer"; @@ -16,7 +16,13 @@ export const metadata: Metadata = { title: "Mokse - Empowering Change Through Education and Advocacy", description: "We strive to break down barriers and stop the stigma associated with incarceration through consulting services, educational conferences, and business support programs.", + }; +export const viewport: Viewport = { + width: "device-width", + initialScale: 1, + maximumScale: 1 +} export default function RootLayout({ children, diff --git a/components/home/feature-card.tsx b/components/home/feature-card.tsx index 9a77433..88eabfd 100644 --- a/components/home/feature-card.tsx +++ b/components/home/feature-card.tsx @@ -17,14 +17,27 @@ export default function FeatureCard({ icon, }: FeatureCardProps) { return ( - - - - + + + {/* bg="transparent" removes the default gray circle if your icon already has color */} + + - {title} - {description} + + + {title} + + + {/* Added line height and muted color for better readability on long paragraphs */} + + {description} + ); -} +} \ No newline at end of file diff --git a/components/page-builder/template.tsx b/components/page-builder/template.tsx index 718978c..921232b 100644 --- a/components/page-builder/template.tsx +++ b/components/page-builder/template.tsx @@ -3,43 +3,39 @@ import { Box, Text, Stack, - AbsoluteCenter, VStack, Heading, - SimpleGrid, Link, - GridItem, - // Float, + Center, } from "@chakra-ui/react"; import NextLink from "next/link"; - import { poppins } from "../ui/fonts"; export function HeaderTemplate({ title, - titleAlignment = 1, titleLocation = 75, image, imageHeight, imageLabel, description, - direction, + direction = "column", children, }: { title?: string; - titleAlignment?: number; + titleAlignment?: number; // Kept for backwards compatibility if used elsewhere titleLocation?: number; image?: string; - imageHeight?: string; + imageHeight?: any; // Changed to 'any' to accept Chakra responsive objects like { base: "40vh", md: "58vh" } imageLabel?: string; description?: string; - direction?: "row" | "column"; children?: React.ReactNode; + direction?: "row" | "column"; + children?: React.ReactNode; }) { return ( {children} - - - - - - - {title} - - - - {description} - - - - - - + + + + {title} + + + + {description} + + + + ); } + export function BodyTemplate({ children }: { children: React.ReactNode }) { return ( - + {children} ); } + export function SectionTemplate({ title, description, - direction, + direction = "column", children, }: { title?: string; @@ -102,26 +102,41 @@ export function SectionTemplate({ children: React.ReactNode; }) { return ( - <> - - - - {title} - - + + {/* Removed the invalid 'direction' prop from Container */} + + + {title && ( + + + {title} + + + )} + {description && ( + + {description} + + )} + + + {/* Applied the requested direction strictly to the children via Stack */} + + {children} + - - {description} - - {children} - > + ); } @@ -133,26 +148,31 @@ export function PageBuilder({ children: React.ReactNode; }>) { return ( - + {children} ); } -/** -* @param linkTo The URL to link to -* @param props The props for the text element -* @param displayText The text to display -*/ -export function LinkBuilder( - { linkTo, props, displayText } - : Readonly<{ - linkTo: string; - props: React.ComponentProps - displayText: string; - }>) { - return - - {displayText} - ; +/** + * @param linkTo The URL to link to + * @param props The props for the text element + * @param displayText The text to display + */ +export function LinkBuilder({ + linkTo, + props, + displayText, +}: Readonly<{ + linkTo: string; + props: React.ComponentProps; + displayText: string; +}>) { + return ( + + + {displayText} + + + ); } \ No newline at end of file diff --git a/components/services/faq-item.tsx b/components/services/faq-item.tsx index ada8b74..ff93906 100644 --- a/components/services/faq-item.tsx +++ b/components/services/faq-item.tsx @@ -1,58 +1,38 @@ "use client"; -// import { useState } from "react"; import { Accordion, - // Button, Card, - // Container, Span, - Text, } from "@chakra-ui/react"; import { Icon } from "../ui/icons/icon"; import { faqItems } from "@/data/services"; -import { SectionTemplate } from "../page-builder/template"; -// interface FaqItemProps { -// index: string; -// question: string; -// answer: string; -// } export default function FaqItem() { - // const [isOpen, setIsOpen] = useState(false); - return ( - - - - Frequently Asked Questions - - - - - - {faqItems.map((item) => { - const { index, question, answer } = item; - return ( - - - {question} - - - - {answer} - - - ); - })} - - - - - - + + + + {faqItems.map((item) => { + const { index, question, answer } = item; + return ( + + + + {question} + + {/* The parent trigger automatically handles standard open/close states, + but if you are using a custom icon, it stays here */} + + + + {answer} + + + ); + })} + + + ); -} +} \ No newline at end of file diff --git a/components/services/service-card.tsx b/components/services/service-card.tsx index 1ab7d38..e37324d 100644 --- a/components/services/service-card.tsx +++ b/components/services/service-card.tsx @@ -4,9 +4,7 @@ import NextLink from "next/link"; import { IconName } from "../ui/icons/icon-registry"; import { Icon } from "../ui/icons/icon"; -import { Card, Image as ChakraImage, Float, Heading } from "@chakra-ui/react"; -import { Link as ChakraLink } from "@chakra-ui/react"; -// import { SimpleGrid } from "@chakra-ui/react"; +import { Box, Card, Float, Heading, Link as ChakraLink } from "@chakra-ui/react"; interface ServiceCardProps { icon: IconName; @@ -26,33 +24,47 @@ export default function ServiceCard({ iconLink, }: ServiceCardProps) { return ( - - - - - - - - + + + + + + + - + + + + - - - {title} - {description} + + + {title} + + + {description} + ); -} +} \ No newline at end of file diff --git a/components/ui/theme.ts b/components/ui/theme.ts index 1883eee..4caf642 100644 --- a/components/ui/theme.ts +++ b/components/ui/theme.ts @@ -3,11 +3,13 @@ import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react" const config = defineConfig({ theme: { breakpoints: { - mobile: "375px", - tablet: "768px", - laptop: "1024px", - xLarge: "1440px", - "2XLarge": "2560px", + xs: "320px", + sm: "375px", + md: "425px", + lg: "768px", + xl: "1024px", + "2xl": "1440px", + "4k": "2560px", }, tokens: { colors: { diff --git a/package.json b/package.json index be5ea36..b53402c 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "build": "next build", "start": "next start", "lint": "eslint . 2>&1", - "typecheck": "tsc --noEmit 2>&1" + "typecheck": "tsc --noEmit 2>&1", + "postinstall": "npx @chakra-ui/cli typegen ./components/ui/theme.ts" }, "dependencies": { "@chakra-ui/react": "^3.34.0", @@ -33,4 +34,4 @@ "tailwindcss": "^4", "typescript": "^5" } -} +} \ No newline at end of file
- Find out how you can contribute and make a positive impact in - your community -
- We're here to support you. Reach out to learn more about - our services, volunteer opportunities, and ways to contribute -
{info.value}