diff --git a/.eslintrc.json b/.eslintrc.json
index 87cf6fe..e9323e2 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -2,6 +2,7 @@
"extends": ["next/core-web-vitals", "prettier"],
"rules": {
"indent": ["error", 2],
- "quotes": ["error", "single"]
+ "quotes": ["error", "single"],
+ "no-unused-vars": "error"
}
}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index a2867dd..9129a0b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"name": "rayfoundation",
"version": "0.1.0",
"dependencies": {
+ "@chakra-ui/icons": "^2.1.1",
"@chakra-ui/next-js": "^2.2.0",
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.11.1",
@@ -1033,6 +1034,18 @@
"react": ">=18"
}
},
+ "node_modules/@chakra-ui/icons": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.1.1.tgz",
+ "integrity": "sha512-3p30hdo4LlRZTT5CwoAJq3G9fHI0wDc0pBaMHj4SUn0yomO+RcDRlzhdXqdr5cVnzax44sqXJVnf3oQG0eI+4g==",
+ "dependencies": {
+ "@chakra-ui/icon": "3.2.0"
+ },
+ "peerDependencies": {
+ "@chakra-ui/system": ">=2.0.0",
+ "react": ">=18"
+ }
+ },
"node_modules/@chakra-ui/image": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/image/-/image-2.1.0.tgz",
diff --git a/package.json b/package.json
index 9f3b2c5..979eab9 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"test:watch": "jest --watch"
},
"dependencies": {
+ "@chakra-ui/icons": "^2.1.1",
"@chakra-ui/next-js": "^2.2.0",
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.11.1",
diff --git a/src/app/components/CTAButton.tsx b/src/app/components/CTAButton.tsx
new file mode 100644
index 0000000..91af449
--- /dev/null
+++ b/src/app/components/CTAButton.tsx
@@ -0,0 +1,46 @@
+'use client'
+import { Button } from '@chakra-ui/react'
+import React, { useEffect, useState } from 'react'
+
+export default function CTAButton({
+ type,
+ variant,
+ size,
+ colorScheme = 'brand',
+}: {
+ type: string
+ variant: string
+ size: string
+ colorScheme: string
+}) {
+ const [text, setText] = useState('')
+ const [url, setUrl] = useState('')
+
+ useEffect(() => {
+ if (type === 'cta_donate') {
+ setText('Donate Now')
+ }
+ }, [type])
+
+ useEffect(() => {
+ if (type === 'cta_donate') {
+ setUrl('https://www.paypal.com/donate/?hosted_button_id=WT7WGSCGNCF9U')
+ }
+ }, [type])
+
+ const onClick = () => {
+ window.open(url, '_blank')
+ }
+
+ return (
+
+ )
+}
diff --git a/src/app/components/Navbar.tsx b/src/app/components/Navbar.tsx
new file mode 100644
index 0000000..45649da
--- /dev/null
+++ b/src/app/components/Navbar.tsx
@@ -0,0 +1,62 @@
+'use client'
+import { Box, Flex, HStack, Text, useDisclosure } from '@chakra-ui/react'
+import React, { useRef } from 'react'
+import NavbarLinkToggle from './NavbarLinkToggle'
+import NavbarLinks from './NavbarLinks'
+import Link from 'next/link'
+import CTAButton from './CTAButton'
+
+const links = [
+ { to: '/about', text: 'About Us' },
+ { to: '/contact', text: 'Contact' },
+ { to: '/projects', text: 'Our Projects' },
+ { to: '/team', text: 'Team' },
+]
+
+export default function Navbar() {
+ const { isOpen, onOpen, onClose } = useDisclosure()
+ const btnRef = useRef(null)
+
+ return (
+
+ {/* Logo */}
+
+
+
+ Ray Foundation
+
+
+
+ {/* Links */}
+
+
+
+ {/* Toggle */}
+
+
+
+ )
+}
diff --git a/src/app/components/NavbarLink.tsx b/src/app/components/NavbarLink.tsx
new file mode 100644
index 0000000..4793ee2
--- /dev/null
+++ b/src/app/components/NavbarLink.tsx
@@ -0,0 +1,13 @@
+import React from 'react'
+import Link from 'next/link'
+import { Button } from '@chakra-ui/react'
+
+export default function NavbarLink({ to, text }: { to: string; text: string }) {
+ return (
+
+
+
+ )
+}
diff --git a/src/app/components/NavbarLinkToggle.tsx b/src/app/components/NavbarLinkToggle.tsx
new file mode 100644
index 0000000..84d7161
--- /dev/null
+++ b/src/app/components/NavbarLinkToggle.tsx
@@ -0,0 +1,22 @@
+'use client'
+import { Box, Button } from '@chakra-ui/react'
+import React, { RefObject } from 'react'
+import { CloseIcon, HamburgerIcon } from '@chakra-ui/icons'
+
+export default function NavbarLinkToggle({
+ isOpen,
+ toggle,
+ btnRef,
+}: {
+ isOpen: boolean
+ toggle: () => void
+ btnRef: RefObject
+}) {
+ return (
+
+
+
+ )
+}
diff --git a/src/app/components/NavbarLinks.tsx b/src/app/components/NavbarLinks.tsx
new file mode 100644
index 0000000..0f7caf1
--- /dev/null
+++ b/src/app/components/NavbarLinks.tsx
@@ -0,0 +1,59 @@
+'use client'
+import React from 'react'
+import {
+ Box,
+ Drawer,
+ DrawerBody,
+ DrawerCloseButton,
+ DrawerContent,
+ DrawerHeader,
+ DrawerOverlay,
+ Stack,
+ StackDivider,
+} from '@chakra-ui/react'
+import NavbarLink from './NavbarLink'
+
+export default function NavbarLinks({
+ links,
+ isOpen,
+ onClose,
+ btnRef,
+}: {
+ links: { to: string; text: string }[]
+ isOpen: boolean
+ onClose: () => void
+ btnRef: React.RefObject
+}) {
+ return (
+ <>
+
+
+ {links.map((link) => {
+ return
+ })}
+
+
+
+
+
+
+ Menu
+
+ }>
+ {links.map((link) => {
+ return (
+
+ )
+ })}
+
+
+
+
+ >
+ )
+}
diff --git a/src/app/components/__tests__/CTAButton.test.tsx b/src/app/components/__tests__/CTAButton.test.tsx
new file mode 100644
index 0000000..dafa8f6
--- /dev/null
+++ b/src/app/components/__tests__/CTAButton.test.tsx
@@ -0,0 +1,29 @@
+import { screen, render } from '@testing-library/react'
+import '@testing-library/jest-dom'
+import CTAButton from '../CTAButton'
+import React from 'react'
+
+describe('CTAButton', () => {
+ it('should render the donate button', () => {
+ render(
+
+ )
+ expect(screen.getByText('Donate Now')).toBeInTheDocument()
+ })
+ it('should render Button when type is incorrect', () => {
+ render(
+
+ )
+ expect(screen.getByText('CTA Button')).toBeInTheDocument()
+ })
+})
diff --git a/src/app/components/__tests__/Navbar.test.tsx b/src/app/components/__tests__/Navbar.test.tsx
new file mode 100644
index 0000000..d397ae7
--- /dev/null
+++ b/src/app/components/__tests__/Navbar.test.tsx
@@ -0,0 +1,15 @@
+import { screen, render } from '@testing-library/react'
+import '@testing-library/jest-dom'
+import React from 'react'
+import Navbar from '../Navbar'
+
+describe('NavBar', () => {
+ it('should render the logo', () => {
+ render()
+ expect(screen.getByText('Ray Foundation')).toBeInTheDocument()
+ })
+ it('should render the call to action button', () => {
+ render()
+ expect(screen.getByText('Donate Now')).toBeInTheDocument()
+ })
+})
diff --git a/src/app/components/__tests__/NavbarLink.test.tsx b/src/app/components/__tests__/NavbarLink.test.tsx
new file mode 100644
index 0000000..b44b6b3
--- /dev/null
+++ b/src/app/components/__tests__/NavbarLink.test.tsx
@@ -0,0 +1,12 @@
+import { screen, render } from '@testing-library/react'
+import '@testing-library/jest-dom'
+import React from 'react'
+import NavbarLink from '../NavbarLink'
+
+describe('NavbarLink', () => {
+ it('should render the link', () => {
+ render()
+ expect(screen.getByText('Home')).toBeInTheDocument()
+ expect(screen.getByRole('link')).toHaveAttribute('href', '/')
+ })
+})
diff --git a/src/app/components/__tests__/NavbarLinkToggle.test.tsx b/src/app/components/__tests__/NavbarLinkToggle.test.tsx
new file mode 100644
index 0000000..396cde9
--- /dev/null
+++ b/src/app/components/__tests__/NavbarLinkToggle.test.tsx
@@ -0,0 +1,18 @@
+import { screen, render, fireEvent } from '@testing-library/react'
+import '@testing-library/jest-dom'
+import React from 'react'
+import NavbarLinkToggle from '../NavbarLinkToggle'
+
+describe('NavbarLinkToggle', () => {
+ it('should render the toggle button', () => {
+ render()
+ expect(screen.getByRole('button')).toBeInTheDocument()
+ })
+ it('should call the toggle button when clicked', () => {
+ const toggle = jest.fn()
+ render()
+ expect(screen.getByRole('button')).toBeInTheDocument()
+ fireEvent.click(screen.getByRole('button'))
+ expect(toggle).toHaveBeenCalled()
+ })
+})
diff --git a/src/app/components/__tests__/NavbarLinks.test.tsx b/src/app/components/__tests__/NavbarLinks.test.tsx
new file mode 100644
index 0000000..e8c9e9f
--- /dev/null
+++ b/src/app/components/__tests__/NavbarLinks.test.tsx
@@ -0,0 +1,33 @@
+import { screen, render } from '@testing-library/react'
+import '@testing-library/jest-dom'
+import React from 'react'
+import NavbarLinks from '../NavbarLinks'
+
+describe('NavbarLinks', () => {
+ it('should render one link if drawer is closed', () => {
+ render(
+
+ )
+ expect(screen.getByText('Home')).toBeInTheDocument()
+ })
+
+ it('should render two links if drawer is open', () => {
+ render(
+
+ )
+ expect(screen.getAllByText('Home')).toHaveLength(2)
+ })
+})
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index a75cd11..6a2f141 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,9 +1,6 @@
import type { Metadata } from 'next'
-import { Inter } from 'next/font/google'
-import './globals.css'
import ThemeProvider from './_providers/ThemeProvider'
-
-const inter = Inter({ subsets: ['latin'] })
+import Navbar from './components/Navbar'
export const metadata: Metadata = {
title: 'Ray Foundation',
@@ -17,8 +14,11 @@ export default function RootLayout({
}) {
return (
-
- {children}
+
+
+
+
+
)
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 2176ae0..a9847cf 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,5 +1,3 @@
-import Image from 'next/image'
-
export default function Home() {
return Ray Foundation
}
diff --git a/src/app/team/[id]/page.tsx b/src/app/team/[id]/page.tsx
index 4f18fd1..9071030 100644
--- a/src/app/team/[id]/page.tsx
+++ b/src/app/team/[id]/page.tsx
@@ -1,14 +1,14 @@
-import { Metadata, ResolvingMetadata } from 'next'
+import { Metadata } from 'next'
import React from 'react'
type MetadataProps = {
params: { id: string }
}
-export async function generateMetadata(
- { params }: MetadataProps,
- parent: ResolvingMetadata
-): Promise {
+export async function generateMetadata({
+ params,
+}: MetadataProps): // parent: ResolvingMetadata
+Promise {
const id = params.id
// Fetch Team Member Information Here