diff --git a/README.md b/README.md index d65912d..8cc65fc 100644 --- a/README.md +++ b/README.md @@ -1 +1,35 @@ -# compass \ No newline at end of file +# 🧭 Compass Center's Internal Resource Management App + +## 🛠 Technologies +- Next.js +- TailwindCSS +- TypeScript +- PostgreSQL + +## 📁 File Setup +``` +\compass + \components // Components organized in folders related to specific pages + \pages // Store all pages here + \api // API routes + \public // Local assets (minimize usage) + \utils // Constants, Routes, Classes, Dummy Data + \styles // CSS files +``` + +## 🚀 To Start +Follow these steps to set up your local environment: +``` +\\ Clone this repository +git clone https://github.com/cssgunc/compass.git +\\ Go into main folder +cd compass +\\ Install dependencies +npm install +\\ Run local environment +npm run dev +``` + +## 💡 Dev Notes +- For each task, create a branch in the format '[your name]-[ticket number]-[task description]' +- Only commit your work to that branch and then make a git request to '/main' \ No newline at end of file diff --git a/compass/app/auth/forgot_password/page.tsx b/compass/app/auth/forgot_password/page.tsx new file mode 100644 index 0000000..554e98a --- /dev/null +++ b/compass/app/auth/forgot_password/page.tsx @@ -0,0 +1,72 @@ +"use client" +import Button from '@/components/Button'; +import Input from '@/components/Input' +import InlineLink from '@/components/InlineLink'; +import Paper from '@/components/auth/Paper'; +import { useState, useEffect } from 'react'; + +function isValidEmail(email: string) { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + + if (email.trim() === '') { + return 'Email cannot be empty'; + } else if (!emailRegex.test(email)) { + return 'Invalid email format'; + } + else{ + return 'If your email exists in the database, you should receive a password reset in your inbox.' + } + +} + +export default function Page() { + const [isButtonDisabled, setIsButtonDisabled] = useState(true); + const [confirmEmail, setconfirmEmail] = useState(''); + const [emailError, setEmailError] = useState(''); + + useEffect(() => { + const error = isValidEmail(confirmEmail); + setEmailError(error); + setIsButtonDisabled(error !== null && !error.includes('exists in the database')); + }, [confirmEmail]); + + return ( + <> + +
+

Forgot password

+
+ { + setconfirmEmail(e.target.value); + setEmailError(''); // Reset the error when the user types + }}/> + {emailError && ( +

+ {emailError} +

+ )} +
+
+ + Back to Sign In + + + +
+
+

+ © 2024 Compass Center +

+
+ + ); +}; + diff --git a/compass/app/favicon.ico b/compass/app/favicon.ico deleted file mode 100644 index 718d6fe..0000000 Binary files a/compass/app/favicon.ico and /dev/null differ diff --git a/compass/app/globals.css b/compass/app/globals.css deleted file mode 100644 index fd81e88..0000000 --- a/compass/app/globals.css +++ /dev/null @@ -1,27 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -:root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - } -} - -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} diff --git a/compass/app/layout.tsx b/compass/app/layout.tsx index 40e027f..2509089 100644 --- a/compass/app/layout.tsx +++ b/compass/app/layout.tsx @@ -1,22 +1,20 @@ -import type { Metadata } from 'next' -import { Inter } from 'next/font/google' -import './globals.css' - -const inter = Inter({ subsets: ['latin'] }) - +import '../styles/globals.css'; +import { Metadata } from 'next' + export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', + title: 'Login', } export default function RootLayout({ + // Layouts must accept a children prop. + // This will be populated with nested layouts or pages children, }: { children: React.ReactNode }) { return ( - {children} + {children} ) -} +} \ No newline at end of file diff --git a/compass/app/page.tsx b/compass/app/page.tsx index 7a8286b..756075c 100644 --- a/compass/app/page.tsx +++ b/compass/app/page.tsx @@ -1,113 +1,41 @@ -import Image from 'next/image' +// pages/index.tsx -export default function Home() { - return ( -
-
-

- Get started by editing  - app/page.tsx -

-
- - By{' '} - Vercel Logo - -
-
- -
- Next.js Logo -
- -
- -

- Docs{' '} - - -> - -

-

- Find in-depth information about Next.js features and API. -

-
- - -

- Learn{' '} - - -> - -

-

- Learn about Next.js in an interactive course with quizzes! -

-
- - -

- Templates{' '} - - -> - -

-

- Explore the Next.js 13 playground. -

-
- - -

- Deploy{' '} - - -> - -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-
-
-
- ) +import Button from '@/components/Button'; +import Input from '@/components/Input' +import InlineLink from '@/components/InlineLink'; +import Paper from '@/components/auth/Paper'; +import { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'Login', } + +export default function Page() { + return ( + <> + +
+
+ +
+
+ +
+
+ + Forgot password? + + + +
+
+

+ © 2024 Compass Center +

+
+ + ); +}; + diff --git a/compass/components/Button.tsx b/compass/components/Button.tsx new file mode 100644 index 0000000..2436359 --- /dev/null +++ b/compass/components/Button.tsx @@ -0,0 +1,23 @@ +import { FunctionComponent, ReactNode } from 'react'; + +type ButtonProps = { + children: ReactNode; + onClick?: () => void; // make the onClick handler optional + type?: "button" | "submit" | "reset"; // specify possible values for type + disabled?: boolean; +}; + +const Button: FunctionComponent = ({ children, type, disabled, onClick}) => { + const buttonClassName = `inline-block rounded border ${disabled ? 'bg-gray-400 text-gray-600 cursor-not-allowed' : 'border-purple-600 bg-purple-600 text-white hover:bg-transparent hover:text-purple-600 focus:outline-none focus:ring active:text-purple-500'} px-4 py-1 text-md font-semibold w-20 h-10 text-center`; + return ( + + ); +}; +export default Button; diff --git a/compass/components/InlineLink.tsx b/compass/components/InlineLink.tsx new file mode 100644 index 0000000..f2e45ef --- /dev/null +++ b/compass/components/InlineLink.tsx @@ -0,0 +1,16 @@ +import React, { ReactNode } from 'react'; + +interface Link { + href?: string; + children: ReactNode; +} + +const InlineLink: React.FC = ({href = '#', children}) => { + return ( + + {children} + + ) +} + +export default InlineLink; \ No newline at end of file diff --git a/compass/components/Input.tsx b/compass/components/Input.tsx new file mode 100644 index 0000000..5997296 --- /dev/null +++ b/compass/components/Input.tsx @@ -0,0 +1,42 @@ +import { Icons } from '@/utils/constants'; +import React, { FunctionComponent, InputHTMLAttributes, ReactElement, ReactNode } from 'react'; + +type InputProps = InputHTMLAttributes & { + iconKey?: keyof typeof Icons; // Use keyof typeof to ensure the key exists in Icons + title?: string; // Assuming title is always a string + type?: string; + placeholder?: string; +}; + +const Input: FunctionComponent = ({ iconKey, type, title, placeholder, ...rest }) => { + const IconComponent = iconKey ? Icons[iconKey] : null; + + return ( +
+ {title && ( +
+ +
+ )} +
+ {IconComponent && ( + + + + )} + +
+
+ ); +}; + +export default Input; diff --git a/compass/components/auth/Paper.tsx b/compass/components/auth/Paper.tsx new file mode 100644 index 0000000..95b9ba0 --- /dev/null +++ b/compass/components/auth/Paper.tsx @@ -0,0 +1,15 @@ +import React, { ReactNode } from 'react'; + +interface PageInterface { + children: ReactNode; +} + +const Paper: React.FC = ({ children }) => { + return ( +
+ {children} +
+ ); +}; + +export default Paper; \ No newline at end of file diff --git a/compass/package-lock.json b/compass/package-lock.json index cd8e0a2..de4e361 100644 --- a/compass/package-lock.json +++ b/compass/package-lock.json @@ -8,7 +8,8 @@ "name": "compass", "version": "0.1.0", "dependencies": { - "next": "13.5.6", + "@heroicons/react": "^2.1.1", + "next": "^13.5.6", "react": "^18", "react-dom": "^18" }, @@ -113,6 +114,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@heroicons/react": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.1.tgz", + "integrity": "sha512-JyyN9Lo66kirbCMuMMRPtJxtKJoIsXKS569ebHGGRKbl8s4CtUfLnyKJxteA+vIKySocO4s1SkTkGS4xtG/yEA==", + "peerDependencies": { + "react": ">= 16" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", diff --git a/compass/package.json b/compass/package.json index 55d0404..8fac3f3 100644 --- a/compass/package.json +++ b/compass/package.json @@ -9,19 +9,20 @@ "lint": "next lint" }, "dependencies": { + "@heroicons/react": "^2.1.1", + "next": "^13.5.6", "react": "^18", - "react-dom": "^18", - "next": "13.5.6" + "react-dom": "^18" }, "devDependencies": { - "typescript": "^5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10", + "eslint": "^8", + "eslint-config-next": "13.5.6", "postcss": "^8", "tailwindcss": "^3", - "eslint": "^8", - "eslint-config-next": "13.5.6" + "typescript": "^5" } } diff --git a/compass/public/fonts/Inter-Black.ttf b/compass/public/fonts/Inter-Black.ttf new file mode 100644 index 0000000..b27822b Binary files /dev/null and b/compass/public/fonts/Inter-Black.ttf differ diff --git a/compass/public/fonts/Inter-Bold.ttf b/compass/public/fonts/Inter-Bold.ttf new file mode 100644 index 0000000..fe23eeb Binary files /dev/null and b/compass/public/fonts/Inter-Bold.ttf differ diff --git a/compass/public/fonts/Inter-ExtraBold.ttf b/compass/public/fonts/Inter-ExtraBold.ttf new file mode 100644 index 0000000..874b1b0 Binary files /dev/null and b/compass/public/fonts/Inter-ExtraBold.ttf differ diff --git a/compass/public/fonts/Inter-ExtraLight.ttf b/compass/public/fonts/Inter-ExtraLight.ttf new file mode 100644 index 0000000..c993e82 Binary files /dev/null and b/compass/public/fonts/Inter-ExtraLight.ttf differ diff --git a/compass/public/fonts/Inter-Light.ttf b/compass/public/fonts/Inter-Light.ttf new file mode 100644 index 0000000..71188f5 Binary files /dev/null and b/compass/public/fonts/Inter-Light.ttf differ diff --git a/compass/public/fonts/Inter-Medium.ttf b/compass/public/fonts/Inter-Medium.ttf new file mode 100644 index 0000000..a01f377 Binary files /dev/null and b/compass/public/fonts/Inter-Medium.ttf differ diff --git a/compass/public/fonts/Inter-Regular.ttf b/compass/public/fonts/Inter-Regular.ttf new file mode 100644 index 0000000..5e4851f Binary files /dev/null and b/compass/public/fonts/Inter-Regular.ttf differ diff --git a/compass/public/fonts/Inter-SemiBold.ttf b/compass/public/fonts/Inter-SemiBold.ttf new file mode 100644 index 0000000..ecc7041 Binary files /dev/null and b/compass/public/fonts/Inter-SemiBold.ttf differ diff --git a/compass/public/fonts/Inter-Thin.ttf b/compass/public/fonts/Inter-Thin.ttf new file mode 100644 index 0000000..fe77243 Binary files /dev/null and b/compass/public/fonts/Inter-Thin.ttf differ diff --git a/compass/styles/globals.css b/compass/styles/globals.css new file mode 100644 index 0000000..bec3b2c --- /dev/null +++ b/compass/styles/globals.css @@ -0,0 +1,47 @@ +/* globals.css */ +@import 'tailwindcss/base'; +@import 'tailwindcss/components'; +@import 'tailwindcss/utilities'; + + +:root { + /* Colors */ + --ring-color: 199, 21, 133; + /* This is the RGB value for a purple color */ + --ring-opacity: 0.5; + + /* Shadows */ + --shadow-default: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-focus: 0 0 0 3px rgba(66, 153, 225, 0.5); + + /* Borders */ + --border-radius: 0.375rem; + /* 6px */ + --border-width: 1px; + + /* Spacing */ + --spacing-px: 1px; + --spacing-2: 0.5rem; + /* 8px */ + --spacing-3: 0.75rem; + /* 12px */ + + /* Font */ + --font-color: #4a5568; + /* A shade of gray */ +} + + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + src: url('/fonts/Inter-Regular.ttf') format('ttf'), + url('/fonts/Inter-Bold.ttf') format('ttf'), + url('/fonts/Inter-Black.ttf') format('ttf'), + url('/fonts/Inter-ExtraBold.ttf') format('ttf'), + url('/fonts/Inter-ExtraLight.ttf') format('ttf'), + url('/fonts/Inter-Medium.ttf') format('ttf'), + url('/fonts/Inter-SemiBold.ttf') format('ttf'), + url('/fonts/Inter-Thin.ttf') format('ttf'); + } \ No newline at end of file diff --git a/compass/tailwind.config.ts b/compass/tailwind.config.ts index c7ead80..abab24e 100644 --- a/compass/tailwind.config.ts +++ b/compass/tailwind.config.ts @@ -1,4 +1,4 @@ -import type { Config } from 'tailwindcss' +import type { Config } from 'tailwindcss'; const config: Config = { content: [ @@ -10,11 +10,14 @@ const config: Config = { extend: { backgroundImage: { 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', - 'gradient-conic': - 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, + fontFamily: { + sans: ['Inter', 'sans-serif'], }, }, }, plugins: [], -} -export default config +}; + +export default config; diff --git a/compass/tsconfig.json b/compass/tsconfig.json index c714696..1acc222 100644 --- a/compass/tsconfig.json +++ b/compass/tsconfig.json @@ -8,7 +8,7 @@ "noEmit": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "bundler", + "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", diff --git a/compass/utils/classes/CollectionImpl.tsx b/compass/utils/classes/CollectionImpl.tsx new file mode 100644 index 0000000..8d8a46a --- /dev/null +++ b/compass/utils/classes/CollectionImpl.tsx @@ -0,0 +1,16 @@ +class CollectionImpl { + title: string; + icon: any; + data: any; + + constructor(title: string, icon: any) { + this.title = title; + this.icon = icon; + } + + // subject to change + setData(data: any){ + this.data = data; + } + +} \ No newline at end of file diff --git a/compass/utils/constants.tsx b/compass/utils/constants.tsx new file mode 100644 index 0000000..d715bb7 --- /dev/null +++ b/compass/utils/constants.tsx @@ -0,0 +1,54 @@ +import { ListBulletIcon, HashtagIcon, Bars3BottomLeftIcon, EnvelopeIcon, AtSymbolIcon, ClipboardIcon, ArrowsUpDownIcon, ChevronDoubleRightIcon, ChevronDoubleLeftIcon, ChevronRightIcon, ChevronLeftIcon, EyeIcon, EyeSlashIcon, UserIcon, BookOpenIcon, MagnifyingGlassIcon, LinkIcon } from '@heroicons/react/24/solid'; + +export const Icons = { + EmailInputIcon: EnvelopeIcon, + HidePasswordIcon: EyeSlashIcon, + UnhidePasswordIcon: EyeIcon, + UserIcon: UserIcon, + ResourceIcon: BookOpenIcon, + SearchIcon: MagnifyingGlassIcon, + ServiceIcon: ClipboardIcon, + CloseRightArrow: ChevronDoubleRightIcon, + CloseLeftArrow: ChevronDoubleLeftIcon, + LinkRightArrow:ChevronRightIcon, + LinkLeftArrow:ChevronLeftIcon, + SortIcon: ArrowsUpDownIcon, + EmailTableIcon:AtSymbolIcon, + LinkTableIcon: LinkIcon, + TextTableIcon: Bars3BottomLeftIcon, + NumberTableIcon: HashtagIcon, + MultiselectTableIcon: ListBulletIcon +}; + +export enum User { + ADMIN, + EMPLOYEE, + VOLUNTEER +} + +export enum COLLECTION { + RESOURCE, + SERVICE, + USER +} + +export enum PROGRAM { + DOMESTIC_VIOLENCE, + ECONOMIC_STABILITY, + COMMUNITY_EDUCATION +} + +export enum DATATYPE { + INTEGER, + STRING, + LINK, + EMAIL, + MULTISELECT, + SELECT +} + +// export const COLLECTION_MAP: {[key in COLLECTION]: CollectionImpl} = { +// [COLLECTION.RESOURCE]: new CollectionImpl('Resources', Icons.ResourceIcon), +// [COLLECTION.SERVICE]: new CollectionImpl('Services', Icons.ServiceIcon), +// [COLLECTION.USER]: new CollectionImpl('Users', Icons.UserIcon) +// } \ No newline at end of file diff --git a/compass/utils/routes.tsx b/compass/utils/routes.tsx new file mode 100644 index 0000000..e69de29