diff --git a/.gitignore b/.gitignore index 0872c36c..f46d8600 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules app.js app.js.map + diff --git a/app.ts b/app.ts new file mode 100644 index 00000000..cb9a6c69 --- /dev/null +++ b/app.ts @@ -0,0 +1,333 @@ +let fromNumber = 0; +let recordNumberTotal: number; +let count = 0; +let timeout = 0; + +function checkResponseError(response: Response) { + if (!response.ok) { + throw Error(response.statusText); + } + return response; +} + +function debounce(func: () => void, delay: number) { + return function () { + clearTimeout(timeout); + + timeout = setTimeout(() => { + func(); + }, delay); + }; +} + +function createNavigation() { + let recordNav: HTMLElement | null = document.getElementById("record-navigation-container"); // Navigation area + if (recordNav) { + recordNav.innerHTML = ` + +
+

+
+ `; + } +} + +function getRecords(fromNumber: number, toNumber: number): Promise { + return fetch(`http://localhost:2050/records?from=${fromNumber}&to=${toNumber}`, { + method: "GET", + headers: { "Content-Type": "application/json" }, + }) + .then(checkResponseError) + .then((response: Response) => response.json()) + .then((data: string[]) => { + + let infoColumns: HTMLElement | null = document.getElementById("info-columns-container"); // Information + let currentPage: HTMLElement | null = document.getElementById("current-page"); + + if (infoColumns) { + infoColumns.innerHTML = ""; + + for (let i of data) { + dynamicGrid(i); + } + } + + if (currentPage) { + currentPage.innerHTML = `${fromNumber} / ${toNumber}.`; + } + }) + .catch((error: Error) => { + console.log(error); + }); +} + +function recordSelection() { + let recordNav: HTMLElement | null = document.getElementById("record-navigation-container"); // Navigation area + if (!recordNav) { + alert("The navigation is not working correctly refresh the page"); + return; + + } + + let singleRecordSelection = ` + +
+ +

+
+ `; + + recordNav.innerHTML = singleRecordSelection; + + let returnBtn: HTMLElement | null = document.getElementById("return-btn"); + let recordIdInput = document.getElementById("record-id"); + let numberOfRows = Math.floor(window.innerHeight / 50); + let getSingleRecord: HTMLElement | null = document.getElementById("get-record-btn"); + + if (returnBtn) { + // Resets to the first page + returnBtn.addEventListener("click", () => { + createNavigation(); + resizeScreenData(); + fromNumber = 0; + getRecords(fromNumber, fromNumber + numberOfRows); + new PageNavigation(); + }); + } + + if (getSingleRecord) { + getSingleRecord.addEventListener("click", () => { + if (recordIdInput) { + + let recordIdValue = recordIdInput.value; + fromNumber = Number(recordIdValue); + + let toNumber = fromNumber + numberOfRows; + let finalRecord = recordNumberTotal - 1; + + if (toNumber > finalRecord) { + toNumber = finalRecord; + fromNumber = toNumber - numberOfRows; + } + + let check = ["undefined", "string", ""]; + + if (check.includes(typeof fromNumber) || fromNumber < 0) { + alert("Does not exists"); + recordIdValue = "0"; + } else if (typeof fromNumber === "number" && fromNumber >= 0) { + getRecords(fromNumber, toNumber); + } + } + }); + } +} + +function createHeadingGrid(headings: string) { + let headingColumns: HTMLElement | null = document.getElementById("column-headings-container"); // Headings + let headingsData = `

${headings}

`; + + if (headingColumns) { + headingColumns.innerHTML += headingsData; + } +} + +function recordCount(): Promise { + return fetch("http://localhost:2050/recordCount", { + method: "GET", + headers: { "Content-Type": "application/json" }, + }) + .then(checkResponseError) + .then((response: Response) => response.json()) + .then((data: number) => { + recordNumberTotal = data; + }) + .catch((error: Error) => { + console.log(error); + }); +} + +function headingRowCreation(): Promise { + return fetch("http://localhost:2050/columns", { + method: "GET", + headers: { "Content-Type": "application/json" }, + }) + .then(checkResponseError) + .then((response: Response) => response.json()) + .then((data: string[]) => { + for (let i of data) { + createHeadingGrid(i); + } + resizeScreenData(); + }) + .catch((error: Error) => { + console.log(error); + }); +} + +function dynamicGrid(columnData: string) { + let infoColumns: HTMLElement | null = document.getElementById("info-columns-container"); // Information + // Creates the row that the info will display and adds it to the infoColumnsArea. + let infoDataRow = `
`; + + if (infoColumns) { + infoColumns.innerHTML += infoDataRow; + // Gets the created rows. + let finalInfoDataRow = document.getElementById("info-row-" + columnData[0]); + if (finalInfoDataRow) { + // Loops through + for (let x of columnData) { + let infoData = `

${x}

`; + finalInfoDataRow.innerHTML += infoData; + } + } + } +} + +function resizeScreenData() { + let toNumber: number; + let recordNav: HTMLElement | null = document.getElementById("record-navigation-container"); + let nextBtn = document.getElementById("next-records-btn"); + let previousBtn = document.getElementById("previous-records-btn"); + let navBtns = document.getElementById("navigation-btns"); + if (recordNav) { + if (recordNav.contains(navBtns as HTMLDivElement) && nextBtn && previousBtn) { + let numberOfRows = Math.floor(window.innerHeight / 50); + + nextBtn.disabled = false; + previousBtn.disabled = false; + + let finalRecord = recordNumberTotal - 1; + + if (fromNumber + numberOfRows >= finalRecord) { + fromNumber = finalRecord - numberOfRows; + + nextBtn.disabled = true; + previousBtn.disabled = false; + } else if (fromNumber <= 0) { + fromNumber = 0; + + nextBtn.disabled = false; + previousBtn.disabled = true; + } + + toNumber = fromNumber + numberOfRows; + + getRecords(fromNumber, toNumber); + } + } +} + +class PageNavigation { + nextBtn: HTMLButtonElement | null; + previousBtn: HTMLButtonElement | null; + firstPageBtn: HTMLButtonElement | null; + lastPageBtn: HTMLButtonElement | null; + confirmationBtn: HTMLButtonElement | null; + + constructor() { + + function navigationDebounce(func: (argOne: number, argTwo: number) => void, delay: number) { + return function (argOne: number, argTwo: number) { + clearTimeout(timeout); + + timeout = setTimeout(() => { + func(argOne, argTwo); + }, delay); + }; + } + + this.nextBtn = document.getElementById("next-records-btn"); + this.previousBtn = document.getElementById("previous-records-btn"); + this.firstPageBtn = document.getElementById("first-page-btn"); + this.lastPageBtn = document.getElementById("last-page-btn"); + this.confirmationBtn = document.getElementById("confirmation-btn"); + + if (this.confirmationBtn) { + this.confirmationBtn.addEventListener("click", recordSelection); + } + + if (this.nextBtn && this.previousBtn && this.firstPageBtn && this.lastPageBtn) { + let nextPage = () => { + let numberOfRows = Math.floor(window.innerHeight / 50); + fromNumber = fromNumber + numberOfRows; + let toNumber = fromNumber + numberOfRows; + + let finalRecord = recordNumberTotal - 1; + this.previousBtn!.disabled = false; + + if (toNumber >= finalRecord) { + this.nextBtn!.disabled = true; + fromNumber = finalRecord - numberOfRows; + } + + console.log(fromNumber, toNumber); + + navigationDebounce(getRecords, 50)(fromNumber, toNumber) + }; + + + this.nextBtn.addEventListener("click", nextPage); + + let previousPage = () => { + let numberOfRows = Math.floor(window.innerHeight / 50); + fromNumber = fromNumber - numberOfRows; + let toNumber = fromNumber + numberOfRows; + + this.nextBtn!.disabled = false; + + if (fromNumber <= 0) { + this.previousBtn!.disabled = true; + fromNumber = 0; + } + + navigationDebounce(getRecords, 50)(fromNumber, toNumber) + }; + + this.previousBtn.addEventListener("click", previousPage); + + let firstPage = () => { + fromNumber = 0; + let numberOfRows = Math.floor(window.innerHeight / 50); + let toNumber = fromNumber + numberOfRows; + + this.nextBtn!.disabled = false; + this.previousBtn!.disabled = true; + + getRecords(fromNumber, toNumber); + }; + + this.firstPageBtn.addEventListener("click", firstPage); + + let lastPage = () => { + let finalRecord = recordNumberTotal - 1; + let numberOfRows = Math.floor(window.innerHeight / 50); + fromNumber = finalRecord - numberOfRows; + + this.nextBtn!.disabled = true; + this.previousBtn!.disabled = false; + + getRecords(fromNumber, finalRecord); + }; + + this.lastPageBtn.addEventListener("click", lastPage); + } + } +} + +window.onload = () => { + createNavigation(); + headingRowCreation(); + fromNumber = 0; + new PageNavigation(); + window.addEventListener("resize", debounce(resizeScreenData, 500)); +} diff --git a/index.html b/index.html index add5e736..f8aeae0b 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,17 @@ + JS Onboard Project + + -

Hello

+
+
+
- diff --git a/package.json b/package.json new file mode 100644 index 00000000..99313e35 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "onboard-javascript", + "version": "1.0.0", + "description": "This is a JavaScript project for all new developers to complete before venturing into our web frontend codebase.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc --build" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/AshtonMar/onboard-javascript.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/AshtonMar/onboard-javascript/issues" + }, + "homepage": "https://github.com/AshtonMar/onboard-javascript#readme", + "dependencies": { + "@types/jquery": "^3.5.14" + } +} diff --git a/style.css b/style.css new file mode 100644 index 00000000..656cd3af --- /dev/null +++ b/style.css @@ -0,0 +1,119 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: sans-serif; + overflow-y: hidden; + overflow-x: hidden; + border-color: black; +} + +/*Removing Browser scrollbar*/ +::-webkit-scrollbar { + display: none; +} + +/* */ + +/* Body */ +body { + display: flex; + flex-direction: column; + align-items: center; + min-height: 50vh; + min-width: 30%; + height: 100vh; +} + +/* */ + +/* Buttons, selects and inputs */ +button, +select, +input { + width: 125px; + padding: 5px; +} + +/* */ + +/* Navigation */ +#record-navigation-container { + display: flex; + justify-content: space-around; + align-items: center; + flex-direction: row; + height: 10vh; + width: 100%; + padding: 20px; + border-bottom: 1px solid; +} + +/* Next and previous controls */ +.navigation-btns { + display: flex; + justify-content: space-around; + width: 80%; +} + +.current-page-container { + text-align: center; + width: 20%; +} + +/* */ + +/* Headings */ +#column-headings-container { + display: flex; + justify-content: space-between; + align-items: center; + flex-direction: row; + height: 10vh; + width: 100%; + border-bottom: 1px solid; +} + +.column-heading { + display: flex; + align-items: center; + justify-content: center; + font-size: 15px; + padding: 10px; + border-right: 1px solid; + height: 100%; + width: 100%; +} + +/* */ + +/* Info grid */ +#info-columns-container { + display: flex; + flex-direction: column; + height: 80vh; + width: 100%; +} + +.info-rows { + display: flex; + justify-content: space-between; + align-items: center; + flex-direction: row; + height: 100%; + width: 100%; + border-bottom: 1px solid; +} + +.info-row-data { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + padding: 10px; + font-size: 10px; + border-right: 1px solid; +} + +/* */