diff --git a/frontend/pages/app/create-account.vue b/frontend/pages/app/create-account.vue index 31a76e77..5b83aa18 100644 --- a/frontend/pages/app/create-account.vue +++ b/frontend/pages/app/create-account.vue @@ -2,8 +2,172 @@ definePageMeta({ layout: "auth-layout", }); + +// user inputs +const firstName =ref('') +const lastName =ref('') +const password = ref('') +const confirmPassword = ref('') +const birthDate = ref('') +const phoneNumberInput = ref('') +const phoneNumber = ref('') +const email = ref('') +const yearsOfExp = 0 + +// error messages if needed +const first_errorMessage = ref('') +const last_errorMessage = ref('') +const pass_errorMessage = ref('') +const birthday_errorMessage = ref('') +const phone_errorMessage = ref('') +const email_errorMessage = ref('') + const createAccount = () => { - useRouter().push('/app') + pass_errorMessage.value = '' + birthday_errorMessage.value = '' + phone_errorMessage.value = '' + email_errorMessage.value = '' + + const isFirstValid = validateFirst() + const isLastValid = validateLast() + const isPasswordValid = validatePassword() + const isPhoneValid = validatePhone() + const isBirthdayValid = validateBirthday() + const isEmailValid = validateEmail() + + if (isPasswordValid && isPhoneValid && isBirthdayValid && isEmailValid) { + // All validations passed + + //TODO: figure out backend post requests and reroute user to login page + // useRouter().push('/app') + } +} +function validateFirst(){ +if(firstName.value == ''){ + first_errorMessage.value = 'Please enter your first name!' +} + +} +function validateLast(){ + if(lastName.value == ''){ + first_errorMessage.value = 'Please enter your last name!' +} +} + +function validatePassword() { + if (password.value !== confirmPassword.value) { + pass_errorMessage.value = "Your password doesn't match!" + return false + } + if (password.value.length < 8) { + pass_errorMessage.value = "Your password must be at least 8 characters long!" + return false + } + + const specialCharacters = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '{', '}', '[', ']', '|', '\\', ':', ';', '"', "'", '<', '>', ',', '.', '/'] + const specialChar = password.value.split('').some(char => specialCharacters.includes(char)) + + if (!specialChar) { + pass_errorMessage.value = "Your password must contain a special character!" + return false + } + + return true +} + +function validatePhone() { + phoneNumber.value = '' + phone_errorMessage.value = '' + + const charCodeZero = '0'.charCodeAt(0) + const charCodeNine = '9'.charCodeAt(0) + + for (let i = 0; i < phoneNumberInput.value.length; i++) { + const char = phoneNumberInput.value[i] + if (char.charCodeAt(0) >= charCodeZero && char.charCodeAt(0) <= charCodeNine) { + phoneNumber.value += char + } + } + + if (phoneNumber.value.length !== 10) { + phone_errorMessage.value = "The phone number you entered is invalid!" + return false + } + + return true +} + +function validateBirthday() { + birthday_errorMessage.value = '' + if (birthDate.value === '') { + birthday_errorMessage.value = 'Please enter your birthday!' + return false + } + + const [year, month, day] = birthDate.value.split('-').map(part => parseInt(part, 10)) + const currentDate = new Date() + const currentYear = currentDate.getFullYear() + const currentMonth = currentDate.getMonth() + 1 + const currentDay = currentDate.getDate() + + if (year > currentYear || (year === currentYear && (month > currentMonth || (month === currentMonth && day > currentDay)))) { + birthday_errorMessage.value = 'Invalid birthday entered!' + return false + } + + if(isUnderage()){ + birthday_errorMessage.value = 'Sorry! You must be 18 years or older to play!' + } + + return true +} + +function isUnderage() { + const [year, month, day] = birthDate.value.split('-').map(part => parseInt(part, 10)) + const currentDate = new Date() + const birthDateObj = new Date(year, month - 1, day) + const age = currentDate.getFullYear() - birthDateObj.getFullYear() + const monthDiff = currentDate.getMonth() - birthDateObj.getMonth() + const dayDiff = currentDate.getDate() - birthDateObj.getDate() + + if(age > 18){ + return false + } + + console.log(age+" "+monthDiff+" "+dayDiff) + if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { + return age - 1 < 18 + } + + return false +} + +function validateEmail() { + email_errorMessage.value = '' + const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + if (!emailPattern.test(email.value)|| !email.value.endsWith(".com")) { + email_errorMessage.value = 'Invalid email!' + return false + } + return true +} + +function validateIsAlphaOnly() { + first_errorMessage.value = '' + last_errorMessage.value = '' + + const regex = /^[A-Za-z]+$/ + if (!regex.test(firstName.value)&& firstName.value != '') { + first_errorMessage.value= 'Name can only contain letters!' + } + if (!regex.test(lastName.value) && lastName.value != '') { + last_errorMessage.value= 'Name can only contain letters!' + } + } + +function validateYearsOfExp(){ + //TODO: Validate Years of experience ei) not negative or decimal numbers + } @@ -13,31 +177,49 @@ const createAccount = () => {
- + +
+
+

{{ first_errorMessage }}

- + +
+
+

{{ last_errorMessage }}

- + +
+
+

{{ email_errorMessage }}

- +
- + +
+
+

{{ pass_errorMessage }}

- + +
+
+

{{ phone_errorMessage }}

- + +
+
+

{{ birthday_errorMessage }}

@@ -57,4 +239,4 @@ const createAccount = () => { Sign In
- + \ No newline at end of file diff --git a/site/cypress/e2e/createUser.cy.ts b/site/cypress/e2e/createUser.cy.ts new file mode 100644 index 00000000..fc1f1faf --- /dev/null +++ b/site/cypress/e2e/createUser.cy.ts @@ -0,0 +1,57 @@ +export {} + +describe('template spec', () => { + it('Check page exists', () => { + cy.visit('http://localhost:9000/#/create-user') + }) + + it('Check valid input fields', () => { + cy.visit('http://localhost:9000/#/create-user') + + cy.get('.input-first').type('John') + cy.get('.input-last').type('Smith') + cy.get('.input-email').type('johnsmith@gmail.com') + cy.get('.input-password').type('123456789!') + cy.get('.input-confirm-password').type('123456789!') + cy.get('.input-phone').type('(123) 435-1111') + cy.get('.input-birthday').type('2000-01-01') + cy.get('.input-exp').type('4') + cy.get('.input-level').click(); + + // Select an option from the dropdown + cy.get('.q-menu .q-item') + .contains('High School') // Replace 'Option Text' with the text of the option you want to select + .click(); + + // Verify the selected value + cy.get('.input-level').should('contain', 'High School'); // Ensure the correct value is displayed + }) + + + + it('Check valid invalid input fields', () => { + cy.visit('http://localhost:9000/#/create-user') + + cy.get('.input-first').type('John1') + cy.get('#first-error').should('be.visible'); + cy.get('.input-last').type('Smith1') + cy.get('#last-error').should('be.visible'); + + cy.get('.input-email').type('johnsmith@gmail') + cy.get('.input-password').type('123456789!') + cy.get('.input-confirm-password').type('1234') + cy.get('.input-phone').type('435-1111') + cy.get('.input-birthday').type('2047-01-01') + + cy.get('#submitButton').click() + cy.get('#phone-error').should('be.visible'); + cy.get('#password-error').should('be.visible'); + cy.get('#birthday-error').should('be.visible'); + cy.get('#exp-error').should('be.visible'); + cy.get('#level-error').should('be.visible'); + + }) + + + +}) \ No newline at end of file diff --git a/site/src/pages/createUser.vue b/site/src/pages/createUser.vue new file mode 100644 index 00000000..6a9fb8b1 --- /dev/null +++ b/site/src/pages/createUser.vue @@ -0,0 +1,349 @@ + + + + + diff --git a/site/src/router/routes.ts b/site/src/router/routes.ts index 2d34fc1c..c21cc624 100644 --- a/site/src/router/routes.ts +++ b/site/src/router/routes.ts @@ -4,8 +4,13 @@ const routes: RouteRecordRaw[] = [ { path: '/', component: () => import('layouts/MainLayout.vue'), - children: [{ path: '', component: () => import('pages/IndexPage.vue') }], + children: [{ path: '', component: () => import('pages/IndexPage.vue') } // Home page + ,{ + path: '/create-user', + component: () => import('pages/createUser.vue')} // Create user + ], }, + // Always leave this as last one, // but you can also remove it