diff --git a/src/Constants/ErrorMessageInterface.ts b/src/Constants/ErrorMessageInterface.ts new file mode 100644 index 0000000..96798a5 --- /dev/null +++ b/src/Constants/ErrorMessageInterface.ts @@ -0,0 +1,6 @@ +interface ErrorMessage { + status: string, + messages: string[] +} + +export default ErrorMessage \ No newline at end of file diff --git a/src/Constants/ErrorMessages.ts b/src/Constants/ErrorMessages.ts new file mode 100644 index 0000000..90d4f01 --- /dev/null +++ b/src/Constants/ErrorMessages.ts @@ -0,0 +1,14 @@ +import ErrorMessage from './ErrorMessageInterface' + +const ErrorMessages: ErrorMessage[] = [ + { + status: 'Err', + messages: ['Issue getting User data'] + }, + { + status: 'Err', + messages: ['Issue getting Project data'] + } +] + +export default ErrorMessages \ No newline at end of file diff --git a/src/Entities/Harvest.ts b/src/Entities/Harvest.ts new file mode 100644 index 0000000..6e4d66c --- /dev/null +++ b/src/Entities/Harvest.ts @@ -0,0 +1,35 @@ +import HarvestInterface from "./Interfaces/HarvestInterface"; + +let instance: Harvest | null = null + +class Harvest { + accountId: string + accessToken: string + organization: string + + constructor (props?: HarvestInterface) { + if (!instance) instance = this + this.accountId = props?.accountId || '' + this.accessToken = props?.accessToken || '' + this.organization = props?.organization || '' + + return instance + } + + get headers () { + return { + 'Harvest-Account-ID': this.accountId, + 'Authorization': `Bearer ${this.accessToken}` + } + } + + get props (): HarvestInterface { + return { + accountId: this.accountId, + accessToken: this.accessToken, + organization: this.organization + } + } +} + +export default Harvest \ No newline at end of file diff --git a/src/Entities/Interfaces/HarvestInterface.ts b/src/Entities/Interfaces/HarvestInterface.ts new file mode 100644 index 0000000..cce1fe0 --- /dev/null +++ b/src/Entities/Interfaces/HarvestInterface.ts @@ -0,0 +1,7 @@ +interface HarvestInterface { + accountId?: string + accessToken?: string + organization?: string +} + +export default HarvestInterface diff --git a/src/Entities/Interfaces/ProjectInterface.ts b/src/Entities/Interfaces/ProjectInterface.ts new file mode 100644 index 0000000..0ce5bcc --- /dev/null +++ b/src/Entities/Interfaces/ProjectInterface.ts @@ -0,0 +1,9 @@ +import TaskInterface from "./TaskInterface"; + +interface ProjectInterface { + id: string, + name: string, + tasks: TaskInterface[] +} + +export default ProjectInterface diff --git a/src/Entities/Interfaces/TaskInterface.ts b/src/Entities/Interfaces/TaskInterface.ts new file mode 100644 index 0000000..31b4281 --- /dev/null +++ b/src/Entities/Interfaces/TaskInterface.ts @@ -0,0 +1,6 @@ +interface TaskInterface { + id: string, + name: string +} + +export default TaskInterface diff --git a/src/Entities/Interfaces/UserInterface.ts b/src/Entities/Interfaces/UserInterface.ts new file mode 100644 index 0000000..d48f3fb --- /dev/null +++ b/src/Entities/Interfaces/UserInterface.ts @@ -0,0 +1,9 @@ +interface UserInterface { + id: number, + firstName: string, + lastName: string, + email: string, + avatar: string +} + +export default UserInterface diff --git a/src/Entities/Project.ts b/src/Entities/Project.ts new file mode 100644 index 0000000..d6f0421 --- /dev/null +++ b/src/Entities/Project.ts @@ -0,0 +1,24 @@ +import ProjectInterface from './Interfaces/ProjectInterface' +import TaskInterface from './Interfaces/TaskInterface' + +class Project { + public id: string + public name: string + public tasks: TaskInterface[] + + constructor (props: ProjectInterface) { + this.id = props.id + this.name = props.name + this.tasks = props.tasks + } + + get props (): ProjectInterface { + return { + id: this.id, + name: this.name, + tasks: this.tasks + } + } +} + +export default Project diff --git a/src/Entities/ProjectCollection.ts b/src/Entities/ProjectCollection.ts new file mode 100644 index 0000000..89f5417 --- /dev/null +++ b/src/Entities/ProjectCollection.ts @@ -0,0 +1,36 @@ +import Project from './Project' + +let instance: ProjectCollection | null = null + +class ProjectCollection { + elements: Project[] = [] + + constructor () { + if (!instance) instance = this + return instance + } + + addOne = (project: Project): void => { + this.elements.push(project) + } + + addMany = (projects: Project[]): void => { + projects.forEach((p: Project) => { + this.elements.push(p) + }) + } + + findById = (id: string): Project | undefined => { + const project = this.elements.find((p: Project) => { + return p.id === id + }) + return project + } + + findByName = (name: string): Project | undefined => { + const project = this.elements.find((p: Project) => { + return p.name === name + }) + return project + } +} \ No newline at end of file diff --git a/src/Entities/User.ts b/src/Entities/User.ts new file mode 100644 index 0000000..b147890 --- /dev/null +++ b/src/Entities/User.ts @@ -0,0 +1,34 @@ +import UserInterface from './Interfaces/UserInterface' + +let instance: User | null + +class User { + public readonly id: number + public readonly firstName: string + public readonly lastName: string + public readonly email: string + public readonly avatar: string + constructor (props: UserInterface) { + if (!instance) instance = this + + this.id = props.id + this.firstName = props.firstName + this.lastName = props.lastName + this.email = props.email + this.avatar = props.avatar + + return instance + } + + get props (): UserInterface { + return { + id: this.id, + firstName: this.firstName, + lastName: this.lastName, + email: this.email, + avatar: this.avatar + } + } +} + +export default User diff --git a/src/UseCases/getProjects.ts b/src/UseCases/getProjects.ts new file mode 100644 index 0000000..1f44332 --- /dev/null +++ b/src/UseCases/getProjects.ts @@ -0,0 +1,40 @@ +import axios from 'axios' +import Harvest from '../Entities/Harvest' +import ErrorMessage from '../Constants/ErrorMessageInterface' +import ErrorMessages from '../Constants/ErrorMessages' +import Project from '../Entities/Project' +import ProjectInterface from '../Entities/Interfaces/ProjectInterface' + +const getProjects = async (): Promise => { + const harvest = new Harvest() + let projectsResponse: any + try { + projectsResponse = await axios.get( + 'https://api.harvestapp.com/v2/users/me/project_assignments', + { headers : harvest.headers } + ) + } catch (err) { + console.log(err) + return ErrorMessages[1] + } + + const projectData = projectsResponse.data.project_assignments.map((p: any) => { + return { + id: p.project.id, + name: p.project.name, + tasks: p.task_assignments.map((t: any) => { + return { + id: t.task.id, + name: t.task.name + } + }) + } + }) + + const projects = projectData.map((p: ProjectInterface) => { + return new Project(p) + }) + return projects +} + +export default getProjects \ No newline at end of file diff --git a/src/UseCases/getUser.ts b/src/UseCases/getUser.ts new file mode 100644 index 0000000..3623ac6 --- /dev/null +++ b/src/UseCases/getUser.ts @@ -0,0 +1,32 @@ +import axios from 'axios' +import Harvest from '../Entities/Harvest' +import ErrorMessage from '../Constants/ErrorMessageInterface' +import ErrorMessages from '../Constants/ErrorMessages' +import User from "../Entities/User" + +const getUser = async (): Promise => { + const harvest = new Harvest() + let userResponse: any + try { + userResponse = await axios.get( + 'https://api.harvestapp.com/api/v2/users/me.json', + { headers : harvest.headers } + ) + } catch (err) { + console.log(err) + return ErrorMessages[0] + } + + const userData = { + id: userResponse.data.id || '', + firstName: userResponse.data.first_name || '', + lastName: userResponse.data.last_name || '', + email: userResponse.data.email || '', + avatar: userResponse.data.avatar_url || '', + } + + const user = new User(userData) + return user +} + +export default getUser \ No newline at end of file diff --git a/src/test/entityTests/HarvestTests.ts b/src/test/entityTests/HarvestTests.ts new file mode 100644 index 0000000..6dfefc5 --- /dev/null +++ b/src/test/entityTests/HarvestTests.ts @@ -0,0 +1,14 @@ +import Harvest from '../../Entities/Harvest' + +const harvest = new Harvest({ + accountId: '123', + accessToken: 'XYZ' +}) + +console.log(harvest.props) + +const harvest2 = new Harvest() + +harvest2.organization = 'ABC' + +console.log(harvest2.props) \ No newline at end of file diff --git a/src/test/useCaseTests/getProjectsTests.ts b/src/test/useCaseTests/getProjectsTests.ts new file mode 100644 index 0000000..c617f5f --- /dev/null +++ b/src/test/useCaseTests/getProjectsTests.ts @@ -0,0 +1,23 @@ +import ErrorMessage from "../../Constants/ErrorMessageInterface" +import Harvest from "../../Entities/Harvest" +import Project from "../../Entities/Project" +import getProjects from '../../UseCases/getProjects' +import env from '../env' + +async function test () { + new Harvest({ + accountId: env.accountId, + accessToken: env.accessToken, + organization: 'ABC' + }) + + const projects: Project[] | ErrorMessage = await getProjects() + + if (Array.isArray(projects)) { + console.log(projects[0]) + console.log(`${projects.length} Prpjects found`) + } + else console.log(projects) +} + +test() \ No newline at end of file diff --git a/src/test/useCaseTests/getUserTests.ts b/src/test/useCaseTests/getUserTests.ts new file mode 100644 index 0000000..bec32db --- /dev/null +++ b/src/test/useCaseTests/getUserTests.ts @@ -0,0 +1,16 @@ +import Harvest from "../../Entities/Harvest" +import getUser from '../../UseCases/getUser' +import env from '../env' + +async function test () { + new Harvest({ + accountId: env.accountId, + accessToken: env.accessToken, + organization: 'ABC' + }) + + const user = await getUser() + console.log(user) +} + +test() \ No newline at end of file