diff --git a/compass/app/auth/login/page.tsx b/compass/app/auth/login/page.tsx
index ccb8b2c..9b50a2c 100644
--- a/compass/app/auth/login/page.tsx
+++ b/compass/app/auth/login/page.tsx
@@ -60,7 +60,7 @@ export default function Page() {
{emailError && }
{passwordError && }
diff --git a/compass/utils/classes/Field.ts b/compass/utils/classes/Field.ts
new file mode 100644
index 0000000..716846e
--- /dev/null
+++ b/compass/utils/classes/Field.ts
@@ -0,0 +1,15 @@
+import { Icons } from "../constants";
+
+export class Field {
+ iconKey: keyof typeof Icons;
+ title: string;
+
+ constructor(iconKey: keyof typeof Icons, title: string) {
+ this.iconKey = iconKey;
+ this.title = title;
+}
+
+ validateInput(value: any): boolean {
+ return value !== null;
+ }
+}
diff --git a/compass/utils/classes/InputProps.ts b/compass/utils/classes/InputProps.ts
deleted file mode 100644
index 2354d62..0000000
--- a/compass/utils/classes/InputProps.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { InputHTMLAttributes } from "react";
-import { Icons } from "../constants";
-
-export 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;
- };
\ No newline at end of file
diff --git a/compass/utils/constants.tsx b/compass/utils/constants.ts
similarity index 69%
rename from compass/utils/constants.tsx
rename to compass/utils/constants.ts
index 2792d3a..cd9702a 100644
--- a/compass/utils/constants.tsx
+++ b/compass/utils/constants.ts
@@ -1,54 +1,58 @@
-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
+import { ListBulletIcon, HashtagIcon, Bars3BottomLeftIcon, EnvelopeIcon, AtSymbolIcon, ClipboardIcon, ArrowsUpDownIcon, ChevronDoubleRightIcon, ChevronDoubleLeftIcon, ChevronRightIcon, ChevronLeftIcon, EyeIcon, EyeSlashIcon, UserIcon, BookOpenIcon, MagnifyingGlassIcon, LinkIcon, ClipboardDocumentCheckIcon } 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,
+ RequirementsTableIcon: ClipboardDocumentCheckIcon
+};
+
+export enum USER {
+ ADMIN,
+ EMPLOYEE,
+ VOLUNTEER
+}
+
+export enum COLLECTION {
+ RESOURCE,
+ SERVICE,
+ USER,
+ TRAINING_MANUAL
+}
+
+export enum PROGRAM {
+ DOMESTIC_VIOLENCE,
+ ECONOMIC_STABILITY,
+ COMMUNITY_EDUCATION
+}
+
+export enum STATUS {
+ FULL,
+ CLOSED,
+ ACCEPTING_CLIENTS
+}
+
+export enum DATATYPE {
+ INTEGER,
+ STRING,
+ LINK,
+ EMAIL,
+ MULTISELECT,
+ SELECT
+}
+
+
diff --git a/compass/utils/functions/mockFetch.ts b/compass/utils/functions/mockFetch.ts
new file mode 100644
index 0000000..6f79147
--- /dev/null
+++ b/compass/utils/functions/mockFetch.ts
@@ -0,0 +1,137 @@
+import { PROGRAM, STATUS, USER } from "../constants";
+
+const serviceEntries = [
+ {
+ name: "Empowerment Workshops",
+ status: [STATUS.ACCEPTING_CLIENTS],
+ summary: "Workshops to empower victims through education and skill-building.",
+ requirements: "Resident of the community and victim of domestic violence.",
+ program: [PROGRAM.DOMESTIC_VIOLENCE, PROGRAM.COMMUNITY_EDUCATION],
+ tags: ["empowerment", "education"],
+ },
+ {
+ name: "Financial Literacy Courses",
+ status: [STATUS.ACCEPTING_CLIENTS, STATUS.FULL],
+ summary: "Courses aimed at improving financial independence for victims.",
+ requirements: "Open to all domestic violence victims.",
+ program: [PROGRAM.ECONOMIC_STABILITY],
+ tags: ["finance", "literacy"],
+ },
+ {
+ name: "Counseling Services",
+ status: [STATUS.ACCEPTING_CLIENTS],
+ summary: "Professional counseling for individuals and families affected by domestic violence.",
+ requirements: "Appointment required.",
+ program: [PROGRAM.DOMESTIC_VIOLENCE],
+ tags: ["counseling", "mental health"],
+ },
+ {
+ name: "Job Placement Program",
+ status: [STATUS.ACCEPTING_CLIENTS],
+ summary: "Assistance with job search and placement for survivors.",
+ requirements: "Must be actively seeking employment.",
+ program: [PROGRAM.ECONOMIC_STABILITY],
+ tags: ["job", "employment"],
+ },
+ {
+ name: "Legal Advocacy",
+ status: [STATUS.FULL],
+ summary: "Legal advice and representation for victims of domestic violence.",
+ requirements: "Legal documentation of domestic violence required.",
+ program: [PROGRAM.DOMESTIC_VIOLENCE],
+ tags: ["legal", "advocacy"],
+ }
+ ];
+
+const resourceEntries = [
+ {
+ name: "Legal Aid Reference",
+ summary: "Comprehensive list of legal resources for victims.",
+ link: "https://legalaid.example.com",
+ program: [PROGRAM.DOMESTIC_VIOLENCE],
+ tags: ["legal", "aid"],
+ },
+ {
+ name: "Shelter Locations",
+ summary: "Directory of safe shelters for victims escaping abuse.",
+ link: "https://shelters.example.com",
+ program: [PROGRAM.DOMESTIC_VIOLENCE],
+ tags: ["shelter", "safety"],
+ },
+ {
+ name: "Support Group Finder",
+ summary: "Find local support groups for survivors of domestic violence.",
+ link: "https://supportgroups.example.com",
+ program: [PROGRAM.COMMUNITY_EDUCATION],
+ tags: ["support", "community"],
+ },
+ {
+ name: "Employment Services",
+ summary: "Resources for job training and placement services.",
+ link: "https://employment.example.com",
+ program: [PROGRAM.ECONOMIC_STABILITY],
+ tags: ["job", "training"],
+ },
+ {
+ name: "Educational Workshops",
+ summary: "Schedule of educational workshops on various topics.",
+ link: "https://workshops.example.com",
+ program: [PROGRAM.COMMUNITY_EDUCATION],
+ tags: ["education", "workshops"],
+ }
+ ];
+
+const userEntries = [
+ {
+ name: "Alex Johnson",
+ role: [USER.VOLUNTEER],
+ email: "alex.johnson@example.com",
+ program: [PROGRAM.DOMESTIC_VIOLENCE],
+ experience: 2,
+ group: "Volunteer Group A",
+ },
+ {
+ name: "Sam Lee",
+ role: [USER.EMPLOYEE],
+ email: "sam.lee@example.com",
+ program: [PROGRAM.ECONOMIC_STABILITY],
+ experience: 5,
+ group: "Economic Support Team",
+ },
+ {
+ name: "Jordan Smith",
+ role: [USER.ADMIN, USER.VOLUNTEER],
+ email: "jordan.smith@example.com",
+ program: [PROGRAM.COMMUNITY_EDUCATION, PROGRAM.DOMESTIC_VIOLENCE],
+ experience: 3,
+ group: "Outreach and Education",
+ },
+ {
+ name: "Casey Martinez",
+ role: [USER.VOLUNTEER],
+ email: "casey.martinez@example.com",
+ program: [PROGRAM.ECONOMIC_STABILITY],
+ experience: 1,
+ group: "Financial Literacy Volunteers",
+ },
+ {
+ name: "Jamie Chung",
+ role: [USER.EMPLOYEE],
+ email: "jamie.chung@example.com",
+ program: [PROGRAM.DOMESTIC_VIOLENCE],
+ experience: 4,
+ group: "Counseling Services Team",
+ }
+ ];
+
+export const mockFetchServices = () => {
+ return serviceEntries;
+}
+
+export const mockFetchResources = () => {
+ return resourceEntries;
+}
+
+export const mockFetchUsers = () => {
+ return userEntries;
+}
\ No newline at end of file
diff --git a/compass/utils/implementations/CollectionDataImpl.ts b/compass/utils/implementations/CollectionDataImpl.ts
new file mode 100644
index 0000000..6e0ef92
--- /dev/null
+++ b/compass/utils/implementations/CollectionDataImpl.ts
@@ -0,0 +1,39 @@
+import { Field } from "../classes/Field";
+
+export class CollectionDataImpl {
+ headers: Field[];
+ rows: Record[];
+
+ constructor(headers: Field[] = [], rows: Record[] = []) {
+ this.headers = headers;
+ this.rows = rows;
+ }
+
+ addRow(row: Record): void {
+ let isValidRow = true;
+
+ for (const header of this.headers) {
+ const value = row[header.title];
+ if (!header.validateInput(value)) {
+ console.error(`Validation failed for ${header.title} with value ${value}`);
+ isValidRow = false;
+ break;
+ }
+ }
+
+ if (isValidRow) {
+ this.rows.push(row);
+ } else {
+ console.log('Row not added due to validation failure.');
+ }
+ }
+
+ getRows(): Record[] {
+ return this.rows;
+ }
+
+ getHeaders(): Field[] {
+ return this.headers;
+ }
+
+}
\ No newline at end of file
diff --git a/compass/utils/implementations/CollectionImpl.ts b/compass/utils/implementations/CollectionImpl.ts
new file mode 100644
index 0000000..a940ac9
--- /dev/null
+++ b/compass/utils/implementations/CollectionImpl.ts
@@ -0,0 +1,15 @@
+import { CollectionDataImpl } from "./CollectionDataImpl";
+
+export class CollectionImpl {
+ title: string;
+ icon: any;
+ data: CollectionDataImpl;
+
+ constructor(title: string, icon: any, data: CollectionDataImpl) {
+ this.title = title;
+ this.icon = icon;
+ this.data = data;
+ }
+
+
+}
\ No newline at end of file
diff --git a/compass/utils/implementations/FieldImpl/EmailFieldImpl.ts b/compass/utils/implementations/FieldImpl/EmailFieldImpl.ts
new file mode 100644
index 0000000..bb2640a
--- /dev/null
+++ b/compass/utils/implementations/FieldImpl/EmailFieldImpl.ts
@@ -0,0 +1,18 @@
+import { Field } from "@/utils/classes/Field";
+
+
+export class EmailFieldImpl extends Field {
+
+ constructor() {
+ super('EmailTableIcon', "Email");
+ }
+
+ validateInput(value: any) : boolean {
+ if (typeof value !== 'string') {
+ return false;
+ }
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ return emailRegex.test(value);
+ }
+
+}
\ No newline at end of file
diff --git a/compass/utils/implementations/FieldImpl/IntegerFieldImpl.ts b/compass/utils/implementations/FieldImpl/IntegerFieldImpl.ts
new file mode 100644
index 0000000..f5b7dc1
--- /dev/null
+++ b/compass/utils/implementations/FieldImpl/IntegerFieldImpl.ts
@@ -0,0 +1,15 @@
+import { Icons } from "@/utils/constants";
+import { Field } from "@/utils/classes/Field";
+
+
+export class IntegerFieldImpl extends Field {
+
+ constructor(title: string) {
+ super('NumberTableIcon', title);
+ }
+
+ validateInput(value: any) : boolean {
+ return Number.isInteger(value);
+ }
+
+}
\ No newline at end of file
diff --git a/compass/utils/implementations/FieldImpl/LinkFieldImpl.ts b/compass/utils/implementations/FieldImpl/LinkFieldImpl.ts
new file mode 100644
index 0000000..b091293
--- /dev/null
+++ b/compass/utils/implementations/FieldImpl/LinkFieldImpl.ts
@@ -0,0 +1,18 @@
+import { Field } from "@/utils/classes/Field";
+
+
+export class LinkFieldImpl extends Field {
+
+ constructor() {
+ super('LinkTableIcon', "Link");
+ }
+
+ validateInput(value: any) : boolean {
+ if (typeof value !== 'string') {
+ return false;
+ }
+ const urlRegex = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
+ return urlRegex.test(value);
+ }
+
+}
\ No newline at end of file
diff --git a/compass/utils/implementations/FieldImpl/MultiselectFieldImpl.ts b/compass/utils/implementations/FieldImpl/MultiselectFieldImpl.ts
new file mode 100644
index 0000000..478dcf0
--- /dev/null
+++ b/compass/utils/implementations/FieldImpl/MultiselectFieldImpl.ts
@@ -0,0 +1,39 @@
+import { Field } from "@/utils/classes/Field";
+
+
+export class MultiselectFieldImpl extends Field {
+
+ tags: Set;
+ selectedTags: Set;
+
+ constructor(title: string, tags: Set = new Set()) {
+ super('MultiselectTableIcon', title);
+ this.tags = tags
+ this.selectedTags = new Set();
+ }
+
+ getTags() {
+ return this.tags
+ }
+
+ addTag(tag: any) {
+ this.tags.add(tag);
+ }
+
+ removeTag(tag: any) {
+ if (this.tags.has(tag)){
+ this.tags.delete(tag);
+ }
+ }
+
+ selectTag(tag: any) {
+ this.selectedTags.add(tag);
+ }
+
+ removeSelectedTag(tag: any) {
+ if (this.selectedTags.has(tag)){
+ this.selectedTags.delete(tag);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/compass/utils/implementations/FieldImpl/StringFieldImpl.ts b/compass/utils/implementations/FieldImpl/StringFieldImpl.ts
new file mode 100644
index 0000000..49d0538
--- /dev/null
+++ b/compass/utils/implementations/FieldImpl/StringFieldImpl.ts
@@ -0,0 +1,15 @@
+import { Icons } from "@/utils/constants";
+import { Field } from "@/utils/classes/Field";
+
+
+export class StringFieldImpl extends Field {
+
+ constructor(title: string, iconKey: keyof typeof Icons = "TextTableIcon") {
+ super(iconKey, title);
+ }
+
+ validateInput(value: any) : boolean {
+ return typeof value === 'string';
+ }
+
+}
\ No newline at end of file
diff --git a/compass/utils/models/Collection.ts b/compass/utils/models/Collection.ts
new file mode 100644
index 0000000..7f581c0
--- /dev/null
+++ b/compass/utils/models/Collection.ts
@@ -0,0 +1,15 @@
+import { mockFetchResources, mockFetchServices, mockFetchUsers } from "../functions/mockFetch";
+import { CollectionDataImpl } from "../implementations/CollectionDataImpl";
+import { CollectionImpl } from "../implementations/CollectionImpl";
+import { ResourceCollectionDataType, ServiceCollectionDataType, UserCollectionDataType } from "./CollectionDataType";
+
+const ServiceCollectionData = new CollectionDataImpl(ServiceCollectionDataType, mockFetchServices());
+const ResourceCollectionData = new CollectionDataImpl(ResourceCollectionDataType, mockFetchResources());
+const UserCollectionData = new CollectionDataImpl(UserCollectionDataType, mockFetchUsers());
+
+export const ServiceCollection = new CollectionImpl('Service','ServiceIcon',new CollectionDataImpl(ServiceCollectionDataType))
+
+export const ResourceCollection = new CollectionImpl('Resource','ResourceIcon',new CollectionDataImpl(ResourceCollectionDataType))
+
+export const UserCollection = new CollectionImpl('User','UserIcon',new CollectionDataImpl(UserCollectionDataType))
+
diff --git a/compass/utils/models/CollectionDataType.ts b/compass/utils/models/CollectionDataType.ts
new file mode 100644
index 0000000..883522c
--- /dev/null
+++ b/compass/utils/models/CollectionDataType.ts
@@ -0,0 +1,26 @@
+import { Field } from "../classes/Field";
+import { PROGRAM, STATUS, USER } from "../constants";
+import { EmailFieldImpl } from "../implementations/FieldImpl/EmailFieldImpl";
+import { IntegerFieldImpl } from "../implementations/FieldImpl/IntegerFieldImpl";
+import { LinkFieldImpl } from "../implementations/FieldImpl/LinkFieldImpl";
+import { MultiselectFieldImpl } from "../implementations/FieldImpl/MultiselectFieldImpl";
+import { StringFieldImpl } from "../implementations/FieldImpl/StringFieldImpl";
+
+const programSet: Set = new Set([PROGRAM.COMMUNITY_EDUCATION, PROGRAM.DOMESTIC_VIOLENCE, PROGRAM.ECONOMIC_STABILITY]);
+const program = new MultiselectFieldImpl("program", programSet);
+const requirements = new StringFieldImpl("requirements","RequirementsTableIcon");
+const name = new StringFieldImpl("name");
+const summary = new StringFieldImpl("summary");
+const statusSet: Set = new Set([STATUS.ACCEPTING_CLIENTS, STATUS.CLOSED, STATUS.FULL])
+const status = new MultiselectFieldImpl("status", statusSet);
+const link = new LinkFieldImpl()
+const tags = new MultiselectFieldImpl("tags")
+const roleSet: Set = new Set([USER.ADMIN, USER.EMPLOYEE, USER.VOLUNTEER]);
+const role = new MultiselectFieldImpl("role", roleSet)
+const experience = new IntegerFieldImpl("yoe")
+const email = new EmailFieldImpl()
+const group = new StringFieldImpl("group")
+
+export const ServiceCollectionDataType: Field[] = [name, status, summary, requirements, program, tags]
+export const ResourceCollectionDataType: Field[] = [name, summary, link, program, tags]
+export const UserCollectionDataType: Field[] = [name, role, email, program, experience, group]
\ No newline at end of file