Configure the Client

Let’s configure the client component.

The React web client directory contains the following files:

  • The root directory of the client contains a client-package.json file, which is a configuration file defining the name, version, default home page, and redirect page of the client component.
  • The birthdaygreetings client directory contains two subfolders, per the default project structure of a React app:
    • The public folder is generally used to hold files that can be openly accessed by browsers through public URLs, such as icon files of the web app, the index.html file.
    • The src folder contains the application’s source files that will be included in the build folder when we compile the React app.
    • The client directory also contains the package.json dependency file and a hidden .gitignore file.

The files in the BirthdayGreetings/birthdaygreetings/public directory include:

  • Native React files such as Tests.js, index.js, reportWebVitals.js, logo.svg, and App.test.js.
  • index.html Contains a Catalyst web SDK that allows you to access Catalyst components.
  • Additionally, we will be creating the following files:
    • embeddediframe.css: Will contain the styling elements required for the login forms present in your application.
    • fpwd.css: Will contain the styling elements required for the forgot password screens present in your application.

The files in the BirthdayGreetings/birthdaygreetings/src directory include:

  • Native React files such as setupTests.js, reportWebVitals.js, logo.svg, and App.test.js.
  • App.js: Will contain the hash routes to your application.
  • App.css: Will contain the overall styling elements of your application.
  • index.js: Will act as the entry point of your application.
  • index.css: Contains the styling of the elements present in the index.js file.
  • We will be adding the following additional files to the src directory:
    • Layout.js: Will contain the React component for the application’s logic.
    • LoginPage.js: Will contain the React component for the login pages you generated in the Catalyst console.
    • UserProfile.js: Will contain the user profile page, which displays a top bar and a form for submitting reminder data to the server.
    • UserProfile.css: Will contain the styling elements used for the user profile page, including custom scroll bar settings and layout adjustments for the header section.
    • Signup.js: Will contain the React component for the Signup pages you generated in the Catalyst console.
    • Signup.css: Will contain the styling elements for the Signup page in the application.
    • ListUsers.js: Will contain the page that lists out all of the reminders you have set up, allows editing and deletion, and provides the ability to toggle reminder status using Axios requests.
    • Additionally, you need to create a folder called components in the src directory. The BirthdayGreetings/birthdaygreetings/src/components/ will include the following code files:
      • Form.jsx: Will contain the form component responsible for managing form data, handling input changes, and submitting the form data to the parent component via the onSubmit function.
      • Modal.jsx: Will contain the modal functionality for editing user data, including input fields for name, message, birthday, and email, along with an update button.
      • Modal.css: Will contain the styling for the modal component, including layout, input fields, and buttons for editing user data with a backdrop and centered content.
      • ToggleSwitch.jsx: Will contain the logic for the toggle switch component, allowing users to toggle between two states, such as enabling or disabling a feature.
      • Toggleswitch.css: Will contain the styling for a sliding toggle switch with transition effects for the checked and unchecked states.
      • TopBar.jsx: Will contain the structure of the top navigation bar, including links to pages like “Add User” and “List User,” a title in the center, and a “Sign-out” button on the right.
      • Topbar.css: Will contain the styling elements required to style the top navigation bar, including layout, button appearance, and sticky positioning.
      • UserList.jsx: Will contain the structure for rendering a list of reminders with the option to toggle, edit, or delete each reminder.
      • Userlist.css: Will contain the styling elements required to style the user list, including layout, item styling. Will also contain the button designs for edit and delete actions.

We will be coding the index.html, embeddediframe.css, fpwd.css, App.js, App.css, index.css, index.js, Layout.js, LoginPage.js, UserProfile.css, UserProfile.js, Signup.js, Signup.css, Form.jsx, Form.css, Modal.jsx, Modal.css, ToggleSwitch.jsx, Toggleswitch.css, TopBar.jsx, topbar.css, UserList.jsx, and Userlist.css files.

We will also be modifying the client-package.json to ensure that the homepage of the application is the login page.

Install additional React packages

Before you begin adding code to your files, you need to install the following packages:

  • react-router-dom: This package is required to perform hash routing.
  • axios: To smoothly handle client promises.

Install the react-router-dom package by executing the following command in the react-router-dom directory using your terminal:

copy
$
npm install react-router-dom
catalyst_tutorials_jobscheduling_client_router_dom

Install the axios package by executing the following command in the BirthdayGreeting/birthdaygreeting/public/ directory using your terminal:

copy
$
npm install axios
catalyst_tutorials_jobscheduling_client_axios

This is the project directory after you have created the required files and deleted the unnecessary ones.

catalyst_tutorials_jobscheduling_final_proj_dir

Copy the code given below and paste it in the respective files located in the client directory (birthdaygreetings/public/) using an IDE and save the file.

    
index.html
copy
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <script src="https://static.zohocdn.com/catalyst/sdk/js/4.5.0/catalystWebSDK.js"> </script> <script src="/__catalyst/sdk/init.js"> </script> <title>React App</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"> </div> </body> </html>
View more
    
embeddediframe.css
copy
@font-face { font-family: "Roboto Mono"; font-weight: 400; font-style: normal; src: url("https://webfonts.zohowebstatic.com/robotomonoregular/font.eot"); src: url("https://webfonts.zohowebstatic.com/robotomonoregular/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.svg#RobotoMono-Regular") format("svg"); } @font-face { font-family: "LatoLgt"; font-weight: 300; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latolight/font.eot"); src: url("https://webfonts.zohowebstatic.com/latolight/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latolight/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latolight/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latolight/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latolight/font.svg#Lato-Light") format("svg"); } @font-face { font-family: "LatoReg"; font-weight: 400; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latoregular/font.eot"); src: url("https://webfonts.zohowebstatic.com/latoregular/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latoregular/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latoregular/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latoregular/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latoregular/font.svg#Lato-Regular") format("svg"); } @font-face { font-family: "LatoSB"; font-weight: 700; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latobold/font.eot"); src: url("https://webfonts.zohowebstatic.com/latobold/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latobold/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latobold/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latobold/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latobold/font.svg#Lato-Bold") format("svg"); } @font-face { font-family: "LatoB"; font-weight: 900; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latoblack/font.eot"); src: url("https://webfonts.zohowebstatic.com/latoblack/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latoblack/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latoblack/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latoblack/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latoblack/font.svg#Lato-Black") format("svg"); } @font-face { font-family: "signinicon"; src: url(/images/signinicon.eot); src: url(/images/signinicon.eot) format("embedded-opentype"), url(/__catalyst/auth/static-file?file_name=signinicon.woff2) format("woff2"), url(/__catalyst/auth/static-file?file_name=signinicon.ttf) format("truetype"), url(/__catalyst/auth/static-file?file_name=signinicon.woff) format("woff"), url("../images/fonts/signinicon.651f82b8f8f51f33cd0b6331f95b5b4f.svg") format("svg"); font-weight: normal; font-style: normal; font-display: block; } [class^="icon-"], [class*=" icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ font-family: "signinicon" !important; speak: never; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-hide:before { content: "\e907"; } .icon-show:before { content: "\e914"; } .icon-backarrow:before { content: "\e900"; } .icon-backup:before { content: "\e901"; } .icon-support:before { content: "\e915"; } body { font-family: "Roboto", sans-serif; margin: 0px; } .bg_one { display: block; position: fixed; top: 0px; left: 0px; height: 100%; width: 100%; background: url("../images/bg.49756b7c711696d95133fa95451f8e13.svg") transparent; background-size: auto 100%; z-index: -1; } .signin_container { height: 25rem; display: block; width: 520px; background-color: #fff; box-shadow: 0px 2px 30px #ccc6; margin: auto; position: relative; z-index: 1; margin-top: auto; overflow: hidden; } .mod_container { width: 500px; } .checkbox_label { display: inline-block; font-size: 14px; margin: 0px 6px; float: left; cursor: pointer; line-height: 20px; } .signin_box { min-height: 520px; height: auto; background: #fff; box-sizing: border-box; border-radius: 2px; transition: all 0.1s ease-in-out; float: left; overflow-y: auto; display: table-cell; border-right: 2px solid #f1f1f1; width: 100%; padding: 0px 30px; height: auto; border-right: none; } .nopassword_message { display: table-cell; font-size: 14px; color: #222222; letter-spacing: 0px; line-height: 20px; height: auto; width: auto; margin-left: 10px; font-weight: 400; padding-left: 10px; } .portal_logo { display: block; height: 30px; width: auto; margin-bottom: 20px; background-size: auto 100%; } .pointer { cursor: pointer; } #forgotpassword { cursor: default; } #forgotpassword > a { cursor: pointer; } .text16 { display: block; text-align: center; margin-bottom: 30px; color: #626262; font-size: 16px; font-weight: 500; text-decoration: none; } .checkbox { float: left; z-index: 0; height: 12px; width: 12px; display: inline-block; border: 2px solid #ccc; border-radius: 2px; position: relative; top: 1.5px; overflow: hidden; background-color: #fff; } .show_hide_password { font-size: 34px; color: #a7a7a7; position: relative; top: -39px; right: 13px; float: right; cursor: pointer; height: 20px; } .pass_policy, .pass_policy_error { color: #8c8c8c; font-size: 14px; padding-top: 10px; } .pass_policy_error { color: #ed7500; display: block; } .checkbox_check { position: absolute; z-index: 1; opacity: 0; left: 50px; margin: 0px; height: 16px; cursor: pointer; width: 16px; } .checkbox_div { display: none; height: 16px; width: auto; margin-bottom: 30px; } .checkbox_div { display: block; } #terminate_session_form .checkbox_mod { margin-top: 50px; } .checkbox_tick { display: block; height: 3px; width: 8px; border-bottom: 2px solid #fff; border-left: 2px solid #fff; transform: rotate(-45deg); margin: 2px 1px; } .passexpsuccess { display: none; height: 106px; width: 178px; background: url("../images/passexpiry.db4c66debd4dd8880655f338ead6b973.png") no-repeat transparent; background-size: auto 100%; margin: 0px auto; margin-bottom: 20px; } .signin_head { display: block; font-size: 24px; font-weight: 500; margin-bottom: 30px; line-height: 30px; transition: all 0.1s ease-in-out; } .rightside_box { width: 390px; height: auto; float: right; box-sizing: border-box; padding: 40px; background-color: #fff; display: table-cell; } .service_name, .backup_desc, .pass_name { display: block; font-size: 16px; color: #000; font-weight: 400; } .titlename { display: block; font-size: 24px; color: #000; font-weight: 400; text-transform: capitalize; width: auto; margin-bottom: 20px; } .extramargin { margin-top: 10px; } .show_hide_password { font-size: 34px; color: #a7a7a7; position: relative; top: -39px; right: 13px; float: right; cursor: pointer; height: 20px; } .textbox_div { display: block; margin-bottom: 30px; position: relative; } .textbox_label { display: block; font-size: 14px; color: #626262; padding-bottom: 10px; } .textbox { display: block; width: 100%; height: 44px; box-sizing: border-box; border-radius: 2px; text-indent: 12px; font-size: 16px; outline: none; border: none; padding-right: 12px; transition: all 0.2s ease-in-out; background: #f1f1f1; border: 1px solid #e4e4e4; } .textbox:valid { border: 2px solid #f4f6f8; } .textindent42 { text-indent: 36px; } .textindent62 { text-indent: 56px; } .textintent52 { text-indent: 46px; } ::-webkit-credentials-auto-fill-button { visibility: hidden; pointer-events: none; position: absolute; right: 0px; } input[type="text"], input[type="password"], input[type="email"], input[type="number"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; } .errorborder:focus, .textbox.errorborder { border-bottom: 2px solid #ff8484; } .btn { cursor: pointer; display: block; width: 100%; height: 44px; border-radius: 4px; letter-spacing: 0.5; font-size: 14px; font-weight: 600; outline: none; border: none; margin: auto; text-transform: uppercase; margin-bottom: 30px; transition: all 0.2s ease-in-out; } .signupbtn { width: 250px; margin-left: 0px; } .blue { box-shadow: 0px 2px 2px #fff; background-color: #159aff; color: #fff; } .grey { background-color: #f3f3f3; color: #3a3a3a; letter-spacing: 0px; } .green { box-shadow: 0px 2px 2px #fff; background-color: #00c573; color: #fff; } .blue:hover { background-color: #0966c2; cursor: pointer; box-shadow: 0px 2px 2px rgba(90, 183, 254, 0.2); } .changeloadbtn { display: block; height: 44px; width: 44px; border-radius: 22px; padding: 0px; } .changeloadbtn:before { content: ""; height: 20px; width: 20px; display: inline-block; margin: 9px; border: 3px solid #fff; border-top: 3px solid #5ab7fe; border-radius: 50%; animation: spin 0.5s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .hellouser { margin-bottom: 30px; } .username { display: inline-block; max-width: 100%; font-size: 16px; font-weight: 500; line-height: 24px; overflow: hidden; text-overflow: ellipsis; padding-right: 10px; float: left; } .Notyou { display: inline-block; font-size: 16px; line-height: 24px; } .signup_text { text-align: center; margin: 20px 0px; font-size: 16px; } .backbtn { display: none; float: left; height: 28px; width: 28px; border-radius: 50%; position: absolute; padding: 0px 5px; cursor: pointer; overflow: hidden; transition: all 0.1s ease; } .zeroheight { width: 0px; height: 0px; overflow: hidden; display: block; } #captcha, #bcaptcha { background: #fff; width: 60%; display: inline-block; } #captcha_img, #bcaptcha_img { width: 40%; float: right; background-color: #ffffff; border-left: none; } #captcha_img img, #bcaptcha_img img { height: 40px; } .reloadcaptcha { float: right; clear: both; margin-top: -37px; height: 30px; width: 30px; border-radius: 50px; background: url("../images/reload.eaef7ea18b680bc07558164c918909a6.png") no-repeat transparent 5px; background-size: 50%; display: inline-block; cursor: pointer; } #captcha_container { display: none; } .options { display: block; width: 100%; max-width: 500px; min-height: 80px; padding: 0px 50px; cursor: pointer; } .options:hover { background-color: #f9f9f9; } .option_details { display: inline-block; height: auto; width: 320px; margin-left: 15px; } .option_title { display: block; font-size: 16px; font-weight: 500; } .img_option { display: table-cell; height: 24px; width: 24px; color: #499aff; font-size: 24px; vertical-align: top; } .errorlabel { color: #e92b2b; } .fielderror { display: none; font-size: 14px; margin-top: 10px; } .fielderror a { text-decoration: none; color: #309ff4; } .bluetext { color: #309ff4; cursor: pointer; } #country_code_select { width: 50px; height: 40px; position: absolute; opacity: 0; display: none; z-index: 0; } .select_country_code { width: 50px; height: 40px; display: inline-block; float: left; position: absolute; line-height: 40px; text-align: center; font-size: 16px; color: black; display: none; z-index: 0; } .pic { width: 20px; height: 14px; background-size: 280px 252px; background-image: url("../images/Flags2x.0b8394efb0ea9167cef2465fb8f63d78.png"); float: left; } .cc { float: right; color: #aeaeae; } .cn { margin-left: 10px; } .select2-results__option–highlighted { background: #f4f6f8; } .searchparent { height: auto; } .searchlbl { font-size: 10px; font-weight: bolder; display: inline-block; margin-top: 15px; margin-bottom: 10px; margin-left: 10px; } .cntrysearch { width: 380px; height: 32px; border-radius: 2px; font-size: 14px; box-sizing: border-box; padding: 8px 10px; background: #f7f7f7; outline: none; border: none; margin-top: 10px; } .select2-results__option { list-style-type: none; height: 40px; box-sizing: border-box; padding: 12px 20px; font-size: 14px; line-height: 16px; } .select2-search__field { width: 380px; height: 32px; border: none; outline: none; background: #f7f7f7; border-radius: 2px; margin: 10px 0 0 10px; font-size: 14px; padding: 10.5px 8px; } .select2-selection { display: inline-block; outline: none; /* background-color: #F4F6F8; */ height: 40px; text-align: center; padding: 10px; box-sizing: border-box; cursor: pointer; } .selection { transition: all 0.2s ease-in-out; -webkit-user-select: none; display: inline-block; white-space: nowrap; overflow: hidden; width: 0px; height: 43px; } #select2-combobox-results { padding-left: 0px; max-height: 200px; overflow-y: scroll; overflow-x: hidden; width: 400px; margin-top: 10px; margin-bottom: 0px; background: white; } .select2-container–open { z-index: 10; background: #ffffff; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.13); width: auto; box-sizing: border-box; } .select2 { position: absolute; background: transparent; box-shadow: none; display: none; margin: 2px; } .select2-results__options { overflow-y: auto; max-height: 200px; } .selection { width: auto; width: -moz-fit-content; width: -webkit-fit-content; margin: auto; display: block; } .select2-search–hide, .select2-selection__clear { display: none; } #otp_container, #enableotpoption, #mfa_ga_container, #mfa_otp_container, #mfa_totp_container, #recoverybtn, #recovery_container, #enableforgot, #enablesaml, .trustbrowser_ui, #backup_ver_container, #backup_container, #enablemore, .password_expiry_container, .terminate_session_container { display: none; } .errorlabel { color: #e92b2b; } .fielderror { display: none; font-size: 14px; margin-top: 10px; } .field_error { color: #f37272; font-size: 14px; padding-top: 10px; } #recoverybtn, #problemsignin, .tryanother { position: absolute; left: 0px; right: 0px; bottom: 40px; } .textbox_actions, .textbox_actions_saml, .textbox_actions_more { display: block; margin-top: 20px; height: 20px; } .bluetext_action { display: inline-block; float: left; font-size: 14px; color: #159aff; font-weight: 500; line-height: 16px; cursor: pointer; } .bluetext_action a { text-decoration: none; } .bluetext_action_right { float: right; } .textbox_actions { display: block; margin-top: 20px; height: 20px; } .Alert, .Errormsg { display: block; margin: auto; height: auto; min-width: 200px; width: fit-content; width: -moz-fit-content; max-width: 600px; background-color: #032239; border-radius: 6px; position: fixed; top: -100px; left: 0px; right: 0px; transition: all 0.2s ease; padding: 0px 20px; z-index: 2; } .tick_icon, .error_icon { display: inline-block; height: 20px; width: 20px; background-color: #22c856; border-radius: 50%; background-size: 60px; margin: 15px; float: left; } .tick_icon:after { display: block; content: ""; height: 5px; width: 9px; border-bottom: 2px solid #fff; border-left: 2px solid #fff; transform: rotate(-45deg); margin: 7px 6px; box-sizing: border-box; } .alert_message, .error_message { display: inline-block; font-size: 14px; color: #fff; line-height: 18px; margin: 16px 0px; margin-right: 20px; max-width: 510px; } .error_icon { background-color: #ff676f; } .error_icon:before, .error_icon:after { position: absolute; left: 44px; top: 20px; content: " "; height: 10px; width: 2px; background-color: #ffffff; } .error_icon:before { transform: rotate(45deg); } .error_icon:after { transform: rotate(-45deg); } .select2-results__options { padding-left: 0px; } .showcountry_code { width: 62px !important; } .textindent70 { text-indent: 70px; } .countrybox { width: 400px; height: 220px; overflow: auto; } .focusmanage { position: absolute; z-index: 10; width: 400px; height: 266px; box-sizing: border-box; padding: 10px; margin-top: -25px; background: #ffffff; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.13); border-radius: 2px; } .recoveryhead { margin-bottom: 10px; } .nopassword_container { display: none; background: #ebf4fb; border: 1px solid #cbe8ff; border-radius: 5px; width: 400px; height: auto; position: absolute; bottom: 50px; box-sizing: border-box; padding: 20px; } .nopassword_icon { display: table-cell; margin: 0px; height: 30px; width: 30px; color: #0091ff; font-size: 30px; vertical-align: middle; } .mailsearch { width: 400px; height: 30px; padding: 0px 0px; border: none; position: absolute; } .bolder1 { font-weight: bolder; } #ui-id-1 { height: 200px; width: auto; outline: none; border: none; overflow-x: hidden; overflow-y: scroll; } .ui-menu-item-wrapper { overflow: auto; } .nonclickelem { color: #626262; pointer-events: none; } .trustdevicebox { width: 500px; min-height: auto !important; } .trustdevice { width: auto; float: left; margin-right: 18px; min-width: 100px; margin-bottom: 0px; } .loadwithbtn { display: inline-block; height: 22px; width: 22px; border: 3px solid #fff; border-radius: 50%; position: absolute; margin: -2px; box-sizing: border-box; border-left: 3px solid transparent; animation-name: rotate1; animation-iteration-count: infinite; animation-duration: 1s; animation-timing-function: linear; } @keyframes rotate1 { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .waitbtn .waittext, .loadbtntext { display: inline-block; text-indent: 25px; } #waitbtn { display: none; } .loadwithbtn:before { display: inline-block; content: ""; height: 22px; width: 22px; border: 3px solid #ffffff30; border-radius: 50%; margin: -3px -11px; position: absolute; box-sizing: border-box; } .notnowbtn .loadwithbtn { border: 3px solid #3a3a3a; border-left: 3px solid transparent; } .trustdevice .loadwithbtn { display: none; } #recoverybtn, #problemsignin, .tryanother { display: none; bottom: 50px; width: fit-content; margin: 0px auto; cursor: pointer; } #recoverOption, #verify_totp_container, #verify_qr_container { display: none; } .backoption { width: 30px; height: 30px; font-size: 24px; display: inline-block; float: left; color: #666666; padding: 3px; box-sizing: border-box; margin-right: 5px; border-radius: 15px; cursor: pointer; } .backoption:hover { background: #f4f4f4; } .rec_head_text, .backoption { display: table-cell; } .options, .optionstry { display: table; width: 100%; height: auto; padding: 20px 50px; box-sizing: border-box; cursor: pointer; } .options:hover, .optionstry:hover { background-color: #f9f9f9; } .option_details, .option_details_try { height: auto; width: auto; padding-left: 10px; vertical-align: top; box-sizing: border-box; } .option_title_try { display: block; font-size: 16px; font-weight: 500; } .option_description { display: block; font-size: 13px; line-height: 20px; color: #696969; margin-top: 5px; } .img_option_try { margin: 12px 0px; } .img_option { font-size: 30px; color: #499aff; } .option_details { display: table-cell; } .problemsignincon, .recoverymodes, .addaptivetfalist, #recoverymodeContainer { width: auto; margin: 0px -50px; } .line { background-color: #f1f1f1; width: 100%; height: 2px; border-radius: 1px; margin-bottom: 20px; } .terminate_session_container .signin_head { margin-bottom: 20px; } #terminate_session_form .checkbox_div { position: relative; margin-bottom: 10px; } #terminate_session_form .checkbox_mod { margin-top: 30px; } #terminate_session_form .checkbox_check { left: 15px; } #terminate_session_form .checkbox_check:checked ~ .checkbox { background-color: #159aff; border-color: #159aff; } #terminate_session_form .showOneAuthLable { border: 1px solid #e7e7e7; border-radius: 10px 10px 0px 0px; box-sizing: border-box; max-width: 420px; height: auto; overflow: auto; margin-bottom: 0px; } .oneAuthLable { display: inline-flex; max-width: 420px; padding: 15px; align-items: center; margin-bottom: 10px; box-sizing: border-box; border: 1px solid #e7e7e7; border-top: none; border-radius: 0px 0px 15px 15px; } .oneauth_icon { display: inline-block; width: 40px; height: 40px; border-radius: 14px; background-size: 40px 40px; } .one_auth_icon_v2 { background-image: url(../images/oneAuth2.4b2a6945d5ecd70b703ba18f5f11eb68.png); } .oneAuthLable .text_container { flex: 1; margin: 0px 10px; } .oneAuthLable .text_header { font-size: 12px; font-weight: 500; margin-bottom: 4px; } .oneAuthLable .text_desc { font-size: 10px; line-height: 14px; } .oneAuthLable .togglebtn_div { height: 16px; padding: 4px; width: 30px; display: inline-block; position: relative; } .oneAuthLable .real_togglebtn { cursor: pointer; display: inline-block; position: relative; height: 16px; width: 30px; z-index: 1; opacity: 0; position: absolute; margin: 0px; } .real_togglebtn:checked ~ .togglebase { background-color: #10bc83; } .real_togglebtn:checked ~ .togglebase .toggle_circle { left: 16px; } .oneAuthLable .togglebase { height: 16px; width: 30px; display: inline-block; background: #ccc; border-radius: 10px; position: absolute; } .oneAuthLable .toggle_circle { transition: all 0.2s ease-in-out; height: 12px; width: 12px; background-color: #fff; border-radius: 10px; display: inline-block; position: absolute; left: 2px; top: 2px; box-shadow: 0px 0px 5px #999; } @media only screen and (-webkit-min-device-pixel-ratio: 2), not all, not all, not all, only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .google_icon { background-color: #fff; box-shadow: 0px 0px 2px #00000012, 0px 2px 2px #00000024; } .google_icon .fed_icon { background: url("../images/signin_icons@2x.c0c72f3600a6f5ec03c9119d5a7d0518.png") no-repeat transparent; background-size: 205px auto; background-position: -10px -10px; } .MS_icon { background-color: #2f2f2f; } .MS_icon .fed_icon { background: url("../images/signin_icons@2x.c0c72f3600a6f5ec03c9119d5a7d0518.png") no-repeat transparent; background-size: 205px auto; background-position: -38px -10px; } .linkedin_fed_box { background-color: #0966c2; } .linkedin_fed_box .fed_icon { background: url("../images/signin_icons@2x.c0c72f3600a6f5ec03c9119d5a7d0518.png") no-repeat transparent; background-size: 205px auto; background-position: -67px -11px; } .large_box .linked_fed_icon { background-position: -9px -174px; } .fb_fed_box { background-color: #1877f2; } .fb_fed_box .fed_icon { background: url("../images/signin_icons@2x.c0c72f3600a6f5ec03c9119d5a7d0518.png") no-repeat transparent; background-size: 205px auto; background-position: -94px -10px; } .zoho_icon { background: url(../images/signin_icons@2x.c0c72f3600a6f5ec03c9119d5a7d0518.png) no-repeat transparent; background-size: 205px auto; background-position: -152px -174px; } } @media only screen and (max-width: 600px) { body { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); } .nopassword_container { width: calc(100% - 60px); padding: 10px; box-sizing: border-box; } .signin_container { width: 100%; box-shadow: none; margin: 0 auto; position: relative; z-index: 1; margin-top: 40px; height: 27rem; overflow: hidden; } #captcha_img, #captcha, #bcaptcha_img, #bcaptcha { border: 2px solid #f4f6f8; border-radius: 2px; text-indent: 3px; width: 50%; outline: none; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .textbox, #verify_totp { background-color: transparent; border: none; border-bottom: 2px solid #f4f6f8; text-indent: 0px; border-radius: 0px; } .textbox:focus, #verify_totp { border: none; border-bottom: 2px solid #159aff; } .errorborder:focus, .textbox.errorborder { border-bottom: 2px solid #ff8484; } .backoption { margin-bottom: 10px; } .img_option { margin: 0px 10px 0px 0px !important; } .bg_one, .line { display: none; } .signin_head { margin-bottom: 30px; } .btn { margin-top: 10px; border-radius: 4px; } .changeloadbtn { border-radius: 22px; } .more { margin-right: 0px !important; } .textindent42 { text-indent: 36px; } .textindent62 { text-indent: 56px; } .textintent52 { text-indent: 46px; } .select2-selection { background-color: #f1f9ff; } .devices .select2-selection { background-color: #f1f9ff; } .select2-search__field { width: 280px; } .applynormal { width: 46% !important; min-width: 0px; } .borderless, .borderlesstry { line-height: 12px; font-size: 14px; } .alert_message, .error_message { max-width: 300px; width: 75%; } .Alert, .Errormsg { max-width: 400px !important; padding: 0px; min-width: 300px; } .error_icon:before, .error_icon:after { left: 24px; } ::placeholder { font-weight: 500; } .mobilehide { display: none !important; } #forgotpassword { margin-bottom: 0px; } #forgotpassword a { display: inline-block; } .fielderror { position: absolute; margin-top: 5px; } .trustdevicebox { width: auto; height: auto; } #recoverybtn, #problemsignin, .tryanother { position: initial !important; margin-top: 70px !important; } .problemsignincon, .recoverymodes, #recoverymodeContainer { width: 100%; margin-left: 0px; } } .hover-tool-tip { position: absolute; top: 15px; left: 335px; background: #fff; padding: 20px; box-shadow: 0px 0px 10px #0000001a; transition: opacity 0.1s; border-radius: 5px; z-index: 9; opacity: 0; } .hover-tool-tip::after { content: ""; position: absolute; width: 0; height: 0; margin-left: -8px; top: 25px; left: 0; box-sizing: border-box; border: 6px solid black; border-color: #ffffff transparent transparent #ffffff; transform-origin: 0 0; transform: rotate(-45deg); box-shadow: -6px -6px 10px 0 #0000001a; } .hover-tool-tip.no-arrow::after { content: none; } .hover-tool-tip ul { padding: 0; margin: 0px 0px 0px 15px; list-style: none; } .hover-tool-tip p { margin: 0px 0px 10px 0px; font-size: 14px; font-weight: 500; } .hover-tool-tip ul li { font-size: 12px; display: flex; align-items: center; white-space: nowrap; line-height: 25px; } .hover-tool-tip ul li.success::before { background-color: #0dbc83; } .hover-tool-tip ul li::before { content: ""; margin-right: 10px; background-color: red; width: 8px; height: 8px; border-radius: 50%; } .titlename, .service_name { display: none !important; } .signin_head { padding-top: 20px; } #login_id { text-indent: 0 !important; } .showcountry_code { display: none !important; }
View more
    
fpwd.css
copy
@font-face { font-family: "Roboto Mono"; font-weight: 400; font-style: normal; src: url("https://webfonts.zohowebstatic.com/robotomonoregular/font.eot"); src: url("https://webfonts.zohowebstatic.com/robotomonoregular/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/robotomonoregular/font.svg#RobotoMono-Regular") format("svg"); } @font-face { font-family: "LatoLgt"; font-weight: 300; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latolight/font.eot"); src: url("https://webfonts.zohowebstatic.com/latolight/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latolight/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latolight/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latolight/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latolight/font.svg#Lato-Light") format("svg"); } @font-face { font-family: "LatoReg"; font-weight: 400; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latoregular/font.eot"); src: url("https://webfonts.zohowebstatic.com/latoregular/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latoregular/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latoregular/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latoregular/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latoregular/font.svg#Lato-Regular") format("svg"); } @font-face { font-family: "LatoSB"; font-weight: 700; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latobold/font.eot"); src: url("https://webfonts.zohowebstatic.com/latobold/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latobold/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latobold/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latobold/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latobold/font.svg#Lato-Bold") format("svg"); } @font-face { font-family: "LatoB"; font-weight: 900; font-style: normal; src: url("https://webfonts.zohowebstatic.com/latoblack/font.eot"); src: url("https://webfonts.zohowebstatic.com/latoblack/font.eot?#iefix") format("eot"), url("https://webfonts.zohowebstatic.com/latoblack/font.woff2") format("woff2"), url("https://webfonts.zohowebstatic.com/latoblack/font.woff") format("woff"), url("https://webfonts.zohowebstatic.com/latoblack/font.ttf") format("truetype"), url("https://webfonts.zohowebstatic.com/latoblack/font.svg#Lato-Black") format("svg"); } @font-face { font-family: "Zoho_Puvi_Regular"; src: url("https://static.zohocdn.com/zohofonts/zohopuvi/4.0/Zoho_Puvi_Regular.eot"); src: url("https://static.zohocdn.com/zohofonts/zohopuvi/4.0/Zoho_Puvi_Regular.eot") format("embedded-opentype"), url("https://static.zohocdn.com/zohofonts/zohopuvi/4.0/Zoho_Puvi_Regular.woff2") format("woff2"), url("https://static.zohocdn.com/zohofonts/zohopuvi/4.0/Zoho_Puvi_Regular.otf") format("opentype"); font-weight: normal; font-style: normal; /* font-display: swap */ } @font-face { font-family: "signinicon"; src: url(/images/signinicon.eot); src: url(/images/signinicon.eot) format("embedded-opentype"), url(/images/signinicon.woff2) format("woff2"), url(/images/signinicon.ttf) format("truetype"), url(/images/signinicon.woff) format("woff"), url("../images/fonts/signinicon.651f82b8f8f51f33cd0b6331f95b5b4f.svg") format("svg"); font-weight: normal; font-style: normal; font-display: block; } [class^="icon-"], [class*=" icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ font-family: "signinicon" !important; speak: never; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-device:before { content: "\e90a"; } .icon-reload:before { content: "\e912"; } .icon-backarrow:before { content: "\e900"; } .icon-email:before { content: "\e904"; } .icon-hide:before { content: "\e907"; } .icon-otp:before { content: "\e90c"; } .icon-show:before { content: "\e914"; } body { margin: 0px; } ::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ color: #0003; } .bg_one { display: block; position: fixed; top: 0px; left: 0px; height: 100%; width: 100%; /* background: url("../images/bg.49756b7c711696d95133fa95451f8e13.svg") transparent; */ background-size: auto 100%; z-index: -1; } .titlename { display: block; font-size: 24px; color: #000; font-weight: 400; text-transform: capitalize; width: auto; margin-bottom: 20px; } .Alert, .Errormsg { display: flex; align-items: center; justify-content: center; margin: auto; height: auto; min-width: 200px; width: fit-content; width: -moz-fit-content; max-width: 600px; background-color: #032239; border-radius: 6px; position: fixed; top: -100px; left: 0px; right: 0px; transition: all 0.2s ease; padding: 0px 20px; z-index: 2; } .tick_icon, .error_icon { display: inline-block; height: 20px; width: 20px; background-color: #22c856; border-radius: 50%; background-size: 60px; margin: 0px 15px; float: left; position: relative; } .tick_icon:after { display: block; content: ""; height: 5px; width: 9px; border-bottom: 2px solid #fff; border-left: 2px solid #fff; transform: rotate(-45deg); margin: 7px 6px; box-sizing: border-box; } .alert_message, .error_message { display: inline-block; font-size: 14px; color: #fff; line-height: 18px; margin: 16px 0px; margin-right: 20px; max-width: 510px; } .error_icon { background-color: #ff676f; } .error_icon:before, .error_icon:after { position: absolute; left: 9px; top: 5px; content: " "; height: 10px; width: 2px; background-color: #ffffff; } .error_icon:before { transform: rotate(45deg); } .error_icon:after { transform: rotate(-45deg); } .loader { width: 36px; height: 36px; border: 4px solid #159aff; border-bottom: 4px solid transparent; border-radius: 50%; display: block; box-sizing: border-box; animation: rotate 1s linear infinite; position: absolute; top: 0px; z-index: 7; bottom: 0px; left: 0px; right: 0px; margin: auto; } @keyframes rotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .blur { top: 0px; left: 0px; bottom: 0px; background: #fff; width: 100%; height: auto; margin: auto; position: absolute; z-index: 3; opacity: 0.9; display: block; } .bold_font { font-weight: 500; } .searchparent { height: auto; } .textbox_div { display: block; margin-bottom: 30px; position: relative; } .textbox { display: block; width: 100%; height: 44px; box-sizing: border-box; border-radius: 2px; text-indent: 12px; font-size: 16px; outline: none; border: none; padding-right: 12px; transition: all 0.2s ease-in-out; background: #f9f9f9; border: 1px solid #dddddd; } .textbox:hover, .textbox:valid, .textbox:focus { border: 1px solid #b9b9b9; } #last_password { padding-right: 40px; } ::-webkit-credentials-auto-fill-button { visibility: hidden; pointer-events: none; position: absolute; right: 0px; } input[type="text"], input[type="password"], input[type="email"], input[type="number"] { -webkit-appearance: none; -moz-appearance: none; appearance: none; } .errorborder { border: 2px solid #ff8484 !important; } .textbox:-webkit-autofill, .textbox:-webkit-autofill:hover, .textbox:-webkit-autofill:focus, .textbox:-webkit-autofill:active { -webkit-box-shadow: inset 0 0 0px 9999px #f9f9f9; -webkit-text-fill-color: black; background-color: #f9f9f9 !important; } .fielderror { display: none; font-size: 14px; margin-top: 10px; } .fielderror a { text-decoration: none; color: #309ff4; } #captcha_container { display: none; border: 1px solid #dddddd; width: 250px; padding: 10px; box-sizing: border-box; margin-top: 10px; border-radius: 4px; } #captcha { width: 100%; display: inline-block; height: 40px; padding: 0px 12px; text-indent: 0px; background: #f9f9f9; } #captcha_img { background-color: #ffffff; border: none; height: 60px; width: 150px; margin-left: 20px; } #captcha_img img { height: 50px; width: 150px; box-sizing: border-box; margin: 0px; } .reloadcaptcha { height: 30px; width: 30px; border-radius: 50%; display: inline-block; cursor: pointer; position: absolute; right: 20px; top: 20px; background-color: #f2f2f2; font-size: 30px; box-sizing: border-box; color: #0006; } .reloadcaptcha:hover { color: #000000b3; } .load_captcha_btn { animation: spin 0.5s linear infinite; } #Last_password_div .head_info { margin: 0px; } .zeroheight { width: 0px; height: 0px; overflow: hidden; display: block; } .btn { cursor: pointer; display: block; width: 100%; height: 44px; border-radius: 4px; letter-spacing: 0.5; font-size: 14px; font-weight: 600; outline: none; border: none; margin: auto; text-transform: uppercase; margin-bottom: 30px; transition: width 0.2s ease-in-out; } .blue { background-color: #159aff; color: #fff; } .grey { background-color: #f3f3f3; color: #3a3a3a; letter-spacing: 0px; } .green { box-shadow: 0px 2px 2px #fff; background-color: #00c573; color: #fff; } .blue:hover { background: #118be9; } .changeloadbtn { display: block; height: 44px; width: 44px; border-radius: 22px; padding: 0px; } .changeloadbtn:before { content: ""; height: 20px; width: 20px; display: inline-block; margin: 9px; border: 3px solid #fff; border-top: 3px solid #5ab7fe; border-radius: 50%; animation: spin 0.5s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .doneBtn { position: relative; } .doneBtn:before { content: ""; opacity: 1; height: 15px; width: 6px; border: unset; border-radius: unset; transform-origin: left top; border-right: 3px solid #fff; border-top: 3px solid #fff; left: 12px; top: 23px; margin: 0px; position: absolute; transform: scaleX(-1) rotate(135deg); animation: tickmark 0.8s ease; } @keyframes tickmark { 0% { height: 0px; width: 0px; border-radius: unset; opacity: 1; } 20% { height: 0px; width: 6px; opacity: 1; border-radius: unset; } 40% { height: 15px; width: 6px; opacity: 1; border-radius: unset; } 100% { height: 15px; width: 6px; opacity: 1; border-radius: unset; } } .doneWithContent span:before { content: ""; opacity: 1; height: 14px; width: 5px; border: unset; border-radius: unset; transform-origin: left top; border-right: 3px solid #fff; border-top: 3px solid #fff; display: inline-block; margin: 0px; position: relative; transform: scaleX(-1) rotate(135deg); top: 12px; left: -21px; } .doneWithContent { padding-left: 21px; position: relative; } .doneWithContent:after { position: absolute; height: 100%; content: ""; display: block; left: 0px; top: 0px; background: #00000008; animation-name: btn_loading; animation-duration: 4.3s; animation-iteration-count: 1; animation-timing-function: linear; } .restrict_icon { display: block; height: 102px; width: 100%; background: url(../images/URLError.76c2ce33de912ad7ae9d2fbfd93ec2c1.png) no-repeat transparent; background-size: auto 100%; margin: auto; margin-top: 30px; background-position: center; } .error_portion { display: none; } .error_content { text-align: center; } .error_content .error_header { font-size: 20px; font-weight: 500; margin-top: 30px; line-height: 26px; } .error_content .error_desc { font-size: 16px; margin: 10px 0px 30px 0px; line-height: 24px; font-weight: 500; color: #000000cc; } .retry_button { line-height: 44px; } .doneWithContent:hover { background: #159aff; } .doneWithContent span { width: 100%; display: block; transition: width 0.2s ease-in-out; white-space: nowrap; } @keyframes btn_loading { 0% { width: 0%; } 100% { width: 100%; } } .resend_label { display: block; text-align: center; } .push_resend { font-size: 14px; color: #626262; font-weight: 500; line-height: 16px; cursor: none; } .bottom_option { cursor: pointer; width: max-content; font-size: 16px; font-weight: 500; text-decoration: none; color: #0091ff; } .bottom_line_opt { width: 100%; display: flex; justify-content: center; position: absolute; left: 0px; bottom: 40px; } .errorlabel { color: #e92b2b; } .show_hide_password { font-size: 24px; color: #00000066; position: relative; top: -34px; right: 13px; float: right; cursor: pointer; line-height: 23px; } .show_hide_password:hover { color: #000000b3; } .select2-results__option { list-style-type: none; height: 40px; box-sizing: border-box; padding: 12px 20px; font-size: 14px; line-height: 16px; } .select2-search__field { width: 380px; height: 32px; border: none; outline: none; background: #f7f7f7; border-radius: 2px; margin: 10px 8px; font-size: 14px; padding: 10.5px 8px; } .select2-selection { display: inline-block; outline: none; background-color: #f9f9f9; height: 40px; text-align: center; padding: 10px; box-sizing: border-box; cursor: pointer; } .selection { transition: all 0.2s ease-in-out; -webkit-user-select: none; display: inline-block; white-space: nowrap; overflow: hidden; width: 0px; height: 43px; } #select2-combobox-results { padding-left: 0px; max-height: 200px; overflow-y: scroll; overflow-x: hidden; width: 400px; margin-top: 10px; margin-bottom: 0px; background: white; } .select2-container–open { z-index: 10; background: #ffffff; box-shadow: 0px 5px 8px 2px #0000000d; width: auto; box-sizing: border-box; } .select2 { position: absolute; background: transparent; box-shadow: none; display: none; margin: 2px; } .select2-results__options { overflow-y: auto; max-height: 200px; } .selection { width: auto; width: -moz-fit-content; width: -webkit-fit-content; margin: auto; display: block; } .select2-search–hide, .select2-selection__clear { display: none; } #country_code_select { width: 50px; height: 40px; position: absolute; opacity: 0; display: none; z-index: 0; } .select_country_code { width: 50px; height: 40px; display: inline-block; float: left; position: absolute; line-height: 39px; text-align: center; font-size: 16px; color: black; display: none; z-index: 0; } .pic { width: 20px; height: 14px; background-size: 280px 252px; background-image: url("../images/Flags2x.0b8394efb0ea9167cef2465fb8f63d78.png"); float: left; } .cc { float: right; color: #aeaeae; } .cn { margin-left: 10px; } .select2-results__option–highlighted { background: #f4f6f8; } .searchparent { height: auto; } .select2-results__options { padding-left: 0px; } .optionstry { display: table; width: 100%; height: auto; padding: 20px 50px; box-sizing: border-box; cursor: pointer; } .optionstry:hover { background-color: #f9f9f9; } .img_option_try { margin: 12px 0px; } .img_option { display: table-cell; width: 30px; color: #499aff; font-size: 30px; vertical-align: top; height: 30px; } .option_details_try { height: auto; width: auto; padding-left: 12px; vertical-align: top; box-sizing: border-box; } .option_title_try { display: block; font-size: 16px; font-weight: 500; } .option_description { display: block; font-size: 13px; line-height: 20px; color: #000c; margin-top: 5px; } #email_confirm_div .optionstry, #mobile_confirm_div .optionstry { padding: 22px 40px; } #email_confirm_div .img_option, #mobile_confirm_div .img_option { font-size: 20px; width: 20px; height: 20px; } #email_confirm_div .option_details_try, #mobile_confirm_div .option_details_try { line-height: 20px; } .otp_container::after, .mini_txtbox:after { content: attr(placeholder); height: 54px; line-height: 54px; position: absolute; color: #b9bcbe; left: 15px; top: 0px; z-index: 1; } .mini_txtbox:after { line-height: 42px; height: 42px; } .hidePlaceHolder::after { z-index: -1 !important; } .otp_verify { margin-top: 10px; } .toggle_active { background: #f9f9f9; border-radius: 2px; } .optionmod { margin-left: 0px; box-sizing: border-box; } .option_title_try { color: #000000; } .mini_btn { margin-left: 10px; width: 30%; float: right; font-size: 12px; margin-bottom: 0px; margin-right: 0px; } .backoption { width: 30px; height: 30px; font-size: 21px; display: inline-block; float: left; color: #666666; padding: 4px 0px; box-sizing: border-box; margin-right: 5px; border-radius: 15px; cursor: pointer; font-weight: 500; text-align: center; } .backoption:hover { background: #f4f4f4; } #select_reocvery_mobile .fieldcontainer, #other_options_div .fieldcontainer, #select_reocvery_email .fieldcontainer { width: auto; margin: 0 -40px; margin-bottom: 40px; } .text16 { display: block; text-align: center; margin-bottom: 30px; color: #626262; font-size: 16px; font-weight: 500; text-decoration: none; } .pointer { cursor: pointer; } .pass_policy { color: #8c8c8c; font-size: 14px; padding-top: 10px; } .nomargin { display: block; margin: 0px; } .tryanother, .extra_options { width: fit-content; margin: 0 auto; cursor: pointer; margin-top: 20px; } .bluetext_action { display: inline-block; font-size: 14px; color: #159aff; font-weight: 500; line-height: 16px; cursor: pointer; margin-top: 5px; } .nonclickelem { color: #626262; pointer-events: none; cursor: none; } .bluetext_action a { text-decoration: none; } .recovery_container { display: block; width: 480px; height: 350px; background-color: #fff; box-shadow: 0px 2px 30px 0px #2b2b2b17; margin: auto; position: relative; z-index: 1; overflow: hidden; } .recovery_box { width: 480px; min-height: 500px; height: auto; background: #fff; box-sizing: border-box; padding: 40px 40px; border-radius: 2px; transition: all 0.1s ease-in-out; float: left; overflow-y: auto; display: table-cell; border-right: 2px solid #f1f1f1; } .menuicon { display: inline-block; float: left; height: 14px; width: 14px; padding: 14px; font-size: 14px; text-align: center; } .user_info { display: inline-flex; justify-content: space-between; border: 1px solid #eeeeee; margin-bottom: 20px; border-radius: 7px; cursor: pointer; box-sizing: border-box; max-width: 100%; flex-wrap: nowrap; } .user_info_space { margin-top: 20px; } .support_temp_info { margin-bottom: 30px; line-height: 24px; } .menutext { display: inline-block; font-size: 16px; padding: 12px 14px; line-height: 20px; width: auto; word-break: break-all; } .fieldcontainer { margin-bottom: 40px; } .change_user { position: relative; float: right; font-size: 14px; padding: 0px 14px 0px 0px; display: inline-block; color: #0091ff; line-height: 38px; font-weight: 500; display: flex; align-items: center; justify-content: center; } .info_head { display: block; font-size: 20px; font-weight: 500; margin-bottom: 20px; line-height: 30px; overflow: auto; transition: all 0.1s ease-in-out; } .info_head #headtitle { display: block; } .head_info { font-size: 16px; margin: 10px 0px 0px 0px; line-height: 24px; font-weight: 400; color: #000000e6; } .user_info_space + .head_info { margin: 0px; } .otp_container { display: block; width: 100%; height: 54px; box-sizing: border-box; border-radius: 2px; font-size: 16px; outline: none; padding: 0px 15px; transition: all 0.2s ease-in-out; background: #f9f9f9; border: 1px solid #dddddd; text-indent: 0px; } .customOtp { border: none; outline: none; background: transparent; height: 100%; font-size: 16px; text-align: left; width: 22px; padding: 0px; } .textindent42 { text-indent: 46px; } .textindent62 { text-indent: 56px; } .textintent52 { text-indent: 51px; } .box_header_load { display: block; height: auto; padding: 50px 0px; -webkit-animation-name: blink; /* Safari 4.0 - 8.0 / -webkit-animation-duration: 1s; / Safari 4.0 - 8.0 */ animation-name: blink; animation-duration: 1s; animation-iteration-count: infinite; animation-timing-function: linear; opacity: 0.05; } .box_head_load { display: block; width: 180px; height: 18px; border-radius: 8px; background-color: #000; } .blink_btn { -webkit-animation-name: blink; /* Safari 4.0 - 8.0 / -webkit-animation-duration: 1s; / Safari 4.0 - 8.0 */ animation-name: blink; animation-duration: 1s; animation-iteration-count: infinite; animation-timing-function: linear; opacity: 0.05; } .box_define_load { display: block; max-width: 800px; width: 100%; height: 16px; border-radius: 8px; background-color: #000; margin-top: 20px; } @keyframes blink { 0% { opacity: 0.08; } 50% { opacity: 0.01; } 100% { opacity: 0.08; } } #loading_div, #Last_password_div, #mobile_confirm_div, #email_confirm_div, #confirm_otp_div, #other_options_div, #contact_support_div, #change_password_div, #recovery_device_div, #password_matched_div, #username_div, #terminate_session_div { display: none; } #multiple_reocvery_mobile, #single_reocvery_mobile, #multiple_reocvery_email, #single_reocvery_email { display: none; } .verify_mob_container, .verify_email_container, .select_device_othermodes { display: none; } .devices { position: relative; padding: 0px; width: fit-content !important; width: -moz-fit-content !important; width: -webkit-fit-content !important; margin: auto; border-radius: 8px; box-sizing: border-box; margin-bottom: 30px; background: #fcfcfc; } .device_title { position: absolute; top: 12px; left: 48px; font-size: 10px; font-weight: 600; text-transform: uppercase; color: #000000b3; line-height: 14px; z-index: 11; } .select2-container–device_select { margin: 0px; display: block; position: relative; margin: auto; cursor: pointer; border: 1px solid #dddddd; border-radius: 8px; overflow: hidden; } #recovery_device_select + .select2-container { width: fit-content !important; width: -moz-fit-content !important; width: -webkit-fit-content !important; } .select2-container–device_select .select2-selection__arrow { position: absolute; top: 0px; right: 14px; width: auto; height: 100%; } .select2-container–device_select .select2-selection__arrow b { border-color: transparent #00000066 #00000066 transparent; border-style: solid; transform: rotate(45deg); border-width: 2px; height: 4px; width: 4px; position: relative; border-radius: 1px; display: inline-block; top: 24px; } .select2-container–device_select .selection { margin: auto; height: 60px; box-sizing: border-box; min-width: 140px; } .select2-container–device_select .select2-selection { height: unset; padding: 12px 34px 12px 14px; } .select2-container–device_select .select_con { font-weight: 400; margin-left: 12px; margin-top: 16px; } .select2-container–device_select .select_icon { margin-top: 7px; } .select2-results__options { margin: 0px; } .select2-results__options .select_con { margin: 0px; } .select2-dropdown .select_con { width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .hideArrow .select2-selection { cursor: default; padding: 12px 14px; } .hideArrow .select2-selection__arrow { display: none; } .secondary_devices { display: none; width: 150px; margin: auto; padding: 8px 18px; border-radius: 18px; background-color: #f4f6f8; border: none; overflow: hidden; max-width: 200px; text-overflow: ellipsis; font-size: 16px; outline: none; } .secondary_devices .select2-container–open { width: 200px; } .device_select { display: block; position: unset; width: auto !important; } .device_selection { padding: 8px 14px; border-radius: 18px; } .deviceparent { text-align: center; display: none; text-overflow: ellipsis; overflow: hidden; width: 100%; white-space: nowrap; } .deviceparent { display: block; } .deviceinfo { display: inline-block; } .devicetext { margin: 0 auto; margin-left: 30px; } .select_icon { float: left; font-size: 20; color: #499aff; } .select_con { float: left; width: auto; overflow: hidden; margin-left: 5px; text-overflow: ellipsis; } .options_selct { max-width: 180px; font-size: 14px; line-height: 20px; font-weight: 500; width: auto; } .contact_support_class { min-height: unset; } .contact_support_class .recovery_box { min-height: unset; } #mfa_totp_section { display: none; } /* Terminate_session page */ #terminate_session_form { overflow: auto; } #terminate_session_form .checkbox_div { position: relative; } #terminate_session_form .checkbox_check { position: absolute; z-index: 1; opacity: 0; left: 15px; margin: 0px; height: 16px; cursor: pointer; width: 16px; } #terminate_session_form .checkbox { float: left; z-index: 0; height: 12px; width: 12px; display: inline-block; border: 2px solid #ccc; border-radius: 2px; position: relative; top: 1.5px; overflow: hidden; background-color: #fff; } #terminate_session_form .checkbox_check:hover ~ .checkbox { border: 2px solid #159aff; } #terminate_session_form .checkbox_check:checked ~ .checkbox { background-color: #159aff; border-color: #159aff; } #terminate_session_form .checkbox .checkbox_tick { display: block; height: 3px; width: 8px; border-bottom: 2px solid #fff; border-left: 2px solid #fff; transform: rotate(-45deg); margin: 2px 1px; } #terminate_session_form .checkbox_label { cursor: pointer; margin: 0px 6px; line-height: 20px; width: 85%; display: inline-block; } #terminate_session_form .showOneAuthLable { border: 1px solid #e7e7e7; border-radius: 10px 10px 0px 0px; box-sizing: border-box; max-width: 420px; } .oneAuthLable { display: inline-flex; max-width: 420px; padding: 15px; align-items: center; box-sizing: border-box; border: 1px solid #e7e7e7; border-top: none; border-radius: 0px 0px 15px 15px; } .oneauth_icon { display: inline-block; width: 40px; height: 40px; border-radius: 14px; background-size: 40px 40px; } .one_auth_icon_v2 { background-image: url(../images/oneAuth2.4b2a6945d5ecd70b703ba18f5f11eb68.png); } .oneAuthLable .text_container { flex: 1; margin: 0px 10px; } .oneAuthLable .text_header { font-size: 12px; font-weight: 500; margin-bottom: 4px; } .oneAuthLable .text_desc { font-size: 10px; line-height: 14px; } .oneAuthLable .togglebtn_div { height: 16px; padding: 4px; width: 30px; display: inline-block; position: relative; } .oneAuthLable .real_togglebtn { cursor: pointer; display: inline-block; position: relative; height: 16px; width: 30px; z-index: 1; opacity: 0; position: absolute; margin: 0px; } .real_togglebtn:checked ~ .togglebase { background-color: #10bc83; } .real_togglebtn:checked ~ .togglebase .toggle_circle { left: 16px; } .oneAuthLable .togglebase { height: 16px; width: 30px; display: inline-block; background: #ccc; border-radius: 10px; position: absolute; } .oneAuthLable .toggle_circle { transition: all 0.2s ease-in-out; height: 12px; width: 12px; background-color: #fff; border-radius: 10px; display: inline-block; position: absolute; left: 2px; top: 2px; box-shadow: 0px 0px 5px #999; } #terminate_session_submit { margin-top: 30px; } @media only screen and (max-width: 600px) { body { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); } .bg_one { display: none; } .alert_message, .error_message { max-width: 300px; width: 75%; } .Alert, .Errormsg { max-width: 400px !important; padding: 0px; min-width: 300px; } .textbox, .otp_container { background-color: transparent; border: none; border-bottom: 2px solid #f4f6f8; border-radius: 0px; } .textbox { transition: unset; } .textbox:-webkit-autofill, .textbox:-webkit-autofill:hover, .textbox:-webkit-autofill:focus, .textbox:-webkit-autofill:active { -webkit-box-shadow: inset 0 0 0px 9999px white; -webkit-text-fill-color: black; } .textbox:valid, .textbox:hover { border: none; border-bottom: 2px solid #159aff; } #captcha { border-radius: 2px; outline: none; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .changeloadbtn { border-radius: 22px; } .btn { margin-top: 10px; border-radius: 4px; } .mini_btn { margin-top: 0px; } .optionstry:hover { background-color: #fff; } .img_option { margin: 0px 10px 0px 0px !important; } .option_details_try { color: #555555; display: inline-block; margin: 0px; } #multiple_reocvery_mobile .fieldcontainer, #multiple_reocvery_email .fieldcontainer, #other_options_div .fieldcontainer { margin: 0 -30px; margin-bottom: 40px; } .optionmod { margin-left: 0px; padding: 15px 30px; line-height: 24px; } .recovery_box { width: 100%; padding: 0px 30px; height: auto; border-right: none; padding-bottom: 40px; } .recovery_container { width: 100%; box-shadow: none; margin: 0 auto; position: relative; z-index: 1; margin-top: 40px; height: auto; overflow: hidden; } .info_head { margin-bottom: 30px; } } .devices .select2-container–open { background: transparent; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min–moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .restrict_icon { background: url(../images/URLError2x.5e762e74a83ee0cda60b8f7c9df299a8.png) no-repeat transparent center/auto 100%; } } .hide { display: none; } .hover-tool-tip { position: absolute; top: 15px; left: 335px; background: #fff; padding: 20px; box-shadow: 0px 0px 10px #0000001a; transition: opacity 0.1s; border-radius: 5px; z-index: 9; opacity: 0; } .hover-tool-tip::after { content: ""; position: absolute; width: 0; height: 0; margin-left: -8px; top: 25px; left: 0; box-sizing: border-box; border: 6px solid black; border-color: #ffffff transparent transparent #ffffff; transform-origin: 0 0; transform: rotate(-45deg); box-shadow: -6px -6px 10px 0 #0000001a; } .hover-tool-tip.no-arrow::after { content: none; } .hover-tool-tip ul { padding: 0; margin: 0px 0px 0px 15px; list-style: none; } .hover-tool-tip p { margin: 0px 0px 10px 0px; font-size: 14px; font-weight: 500; } .hover-tool-tip ul li { font-size: 12px; display: flex; align-items: center; white-space: nowrap; line-height: 25px; } .hover-tool-tip ul li.success::before { background-color: #0dbc83; } .hover-tool-tip ul li::before { margin-right: 10px; background-color: red; width: 8px; height: 8px; border-radius: 50%; } .titlename { display: none !important; } /* #lookup_div { display: none !important; } */ #lookup_div .head_info { font-size: 0; } #lookup_div .head_info::before { content: "Enter your email address"; font-size: 15px; } .info_head { padding-top: 20px; } .rec_modes_other_options { display: none !important; } .recovery_container { height: 29rem; } .Last_password_div { margin-top: -30px; }
View more

Copy the code given below and paste it in the respective files located in the client directory (birthdaygreetings/src/components/) using an IDE and save the file.

    
form.css
copy
.form-container { display: grid; height: 190px; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; gap: 20px; padding: 20px; max-width: 786px; margin: 75px auto; box-shadow: 0 4px 8px rgb(0 0 0 / 10%); border-radius: 8px; background-color: #fff; } .form-group { width: 100%; height: 0px; display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 42px; margin-bottom: 57px; } label { font-size: 19px; font-weight: bold; width: 123px; } input { font-size: 13px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; flex: 1; } input:focus { border-color: #007bff; outline: none; box-shadow: 0 0 4px rgba(0, 123, 255, 0.25); } .form-container > .form-group:nth-child(1) { grid-column: 1; grid-row: 1; } .form-container > .form-group:nth-child(2) { grid-column: 2; grid-row: 1; } .form-container > .form-group:nth-child(3) { grid-column: 1; grid-row: 2; } .form-container > .form-group:nth-child(4) { grid-column: 2; grid-row: 2; } .submit-form{ height: 50px; width: 100%; margin-bottom: 64px; } .submit-btn{ background-color: #58d358; border: none; border-radius: 10px; color: #fff; font-size: 20px; height: 46px; margin-left: 42%; width: 16%; }
View more
    
form.jsx
copy
import { useState } from "react"; import "./form.css"; function Form({ onSubmit }) { const [formData, setFormData] = useState({ name: "", birthday: "", message: "", email: "", }); const handleChange = (e) => { const { id, value } = e.target; setFormData({ ...formData, [id]: value }); }; const handleSubmit = (e) => { e.preventDefault(); onSubmit(formData); }; const today = new Date().toISOString().split("T")[0]; return ( <> <form onSubmit={handleSubmit}> <div className="form-container"> <div className="form-group"> <label htmlFor="name">Name</label> <input type="text" id="name" value={formData.name} onChange={handleChange} /> </div> <div className="form-group"> <label htmlFor="birthday">Birthday</label> <input type="date" id="birthday" value={formData.birthday} onChange={handleChange} max={today} /> </div> <div className="form-group"> <label htmlFor="message">Message</label> <input type="text" id="message" value={formData.message} onChange={handleChange} /> </div> <div className="form-group"> <label htmlFor="email">Email</label> <input type="email" id="email" value={formData.email} onChange={handleChange} /> </div> </div> <div className="submit-form"> <button className="submit-btn" type="submit"> Submit </button> </div> </form> </> ); } export default Form;
View more
    
modal.css
copy
.modal { display: flex; justify-content: center; align-items: center; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 1000; padding: 20px; box-sizing: border-box; } .modal-content { background-color: #fff; padding: 20px; border-radius: 8px; width: 100%; max-width: 500px; position: relative; box-shadow: 0px 2px 15px rgba(0, 0, 0, 0.1); } .edit-heade{ width: 100%; height: 60px; display: flex; } .modal-header h2{ padding-left: 185px; font-size: 1.5rem; margin-bottom: 20px; } .modal-close { position: absolute; top: 10px; right: 15px; font-size: 1.5rem; cursor: pointer; color: #333; } .modal-input-group { margin-bottom: 15px; } .modal-label { font-weight: 700; font-weight: bold; display: block; margin-bottom: 5px; } .modal-input { width: 89%; padding: 10px; border-radius: 5px; border: 1px solid #ccc; font-size: 1rem; } .modal-submit { text-align: center; } .modal-button { background-color: #4CAF50; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 1rem; transition: background-color 0.3s; } .modal-button:hover { background-color: #45a049; }
View more
    
modal.jsx
copy
import { useState } from "react"; import "./modal.css" function Modal({ editData, onUpdate, onClose }) { const [formData, setFormData] = useState(editData); const handleChange = (e) => { const { name, value } = e.target; setFormData({ ...formData, [name]: value }); }; const handleSubmit = () => { onUpdate(formData); }; const today = new Date().toISOString().split("T")[0]; return ( <div className="modal"> <div className="modal-content"> <div className="edit-header"> <div className="modal-header"> <h2>Edit Greeting</h2> </div> <div className="modal-close"> <button onClick={onClose}>×</button> </div> </div> <div className="modal-input-group"> <input name="Name" value={formData.Name} onChange={handleChange} className="modal-input" /> </div> <div className="modal-input-group"> <input name="Message" value={formData.Message} onChange={handleChange} className="modal-input" /> </div> <div className="modal-input-group"> <input name="BirthDay" type="date" value={formData.BirthDay} onChange={handleChange} className="modal-input" max={today} // Set max date to today /> </div> <div className="modal-input-group"> <input name="Email" value={formData.Email} onChange={handleChange} className="modal-input" /> </div> <div className="modal-submit"> <button className="modal-button" onClick={handleSubmit}>Update</button> </div> </div> </div> ); } export default Modal;
View more
    
toggleswitch.css
copy
.switch { display: block; position: relative; display: inline-block; width: 34px; height: 20px; } .switch input { opacity: 0; width: 0; height: 0; } .slide { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: 0.4s; border-radius: 20px; } .slide:before { position: absolute; content: ""; height: 14px; width: 14px; left: 3px; bottom: 3px; background-color: white; transition: 0.4s; border-radius: 50%; } input:checked + .slide { background-color: #2196f3; } input:checked + .slide:before { transform: translateX(14px); }
View more
    
ToggleSwitch.jsx
copy
import "./toggleswitch.css" function ToggleSwitch({ isChecked, onToggle }) { return ( <label className="switch"> <input type="checkbox" checked={isChecked} onChange={(e) => onToggle(e.target.checked)} /> <span className="slide round"> </span> </label> ); } export default ToggleSwitch;
View more
    
topbar.css
copy
body{ margin: 0; padding: 0; } .topbarContainer{ height: 50px; width: 100%; background-color: rgb(58, 58, 98); display: flex; align-items: center; position: fixed; top: 0; z-index: 999; } .topbarLeft{ flex: 1 1; display: flex; align-items: center; gap: 22%; padding-left: 29px; } .naviagtion-btn{ height: 30px; background-color: white; border: none; border-radius: 7px; font-size: 14px; font-weight: 600; } .topLogo{ font-size: 24px; margin-left: 15px; color: white; cursor: pointer; } .topBarCenter{ flex: 1 1; color: white; padding-left: 8%; } .topbarRight{ flex: 0 1; display: flex; justify-content: space-between; padding-left: 24%; } .topRight-btn{ width: 74px; height: 31px; font-size: 15px; font-weight: 650; background-color: red; color: white; margin-right: 40px; border: none; border-radius: 7px; } .topbarlink{ display: flex; margin-left: 67px; color: white; }
View more
    
TopBar.jsx
copy
import React, { useCallback } from 'react' import "./topbar.css" import { Link } from 'react-router-dom' export default function TopBar() { const logout = useCallback(() => { window.catalyst.auth.signOut('/'); }, []); return ( <> <div className="topbarContainer"> <div className="topbarLeft"> <Link to="/addUserPage"> <button className='naviagtion-btn'>Add New Greetings</button> </Link> <Link to="/ListUsers"> <button className='naviagtion-btn'>Greetings List</button> </Link> </div> <div className="topBarCenter"> <div className="seacrhbar"> <h1>Birthday Greetings</h1> </div> </div> <div className="topbarRight"> <button className="topRight-btn" onClick={logout}>Log Out</button> </div </div> </> ) }
View more
    
userlist.css
copy
.users-container { display: flex; flex-direction: column; gap: 8px; } .users-lists { width: 88%; padding: 15px; border: 1px solid #ccc; border-radius: 22px; background-color: #f9f9f9; margin-left: 80px; margin-bottom: 34px; display: flex; flex-direction: column; align-items: flex-start; } .user-item { width: 100%; display: flex; align-items: center; justify-content: space-between; } .left-content { display: flex; flex-direction: column; } .left-content span { margin-bottom: 8px; } .name { font-size: 28px; font-weight: bold; } .date, .email { font-size: 16px; } .message { font-size: 20px; } .right-button { display: flex; align-items: center; gap: 20px; width: 25%; justify-content: flex-end; } .edit-btn, .delete-btn { width: 70px; height: 34px; border-radius: 10px; color: white; border: none; } .edit-btn { background-color: black; } .delete-btn { background-color: rgb(255, 0, 0); }
View more
    
UserList.jsx
copy
import ToggleSwitch from "./ToggleSwitch"; import "./userlist.css"; function UserList({ users, onEdit, onDelete, onToggle }) { return ( <div className="users-container"> {users.map((user) => ( <div className="users-lists" key={user.ID}> <div className="user-item"> <div className="left-content"> <span className="name">{user.Name}</span> <span className="date">{user.BirthDay}</span> <span className="message">{user.Message}</span> <span className="email">{user.Email}</span> </div> <div className="right-button"> <ToggleSwitch isChecked={user.AutoSend} onToggle={(checked) => onToggle(user.ID, checked)} /> <button className="edit-btn" onClick={() => onEdit(user.ID)}>Edit</button> <button className="delete-btn" onClick={() => onDelete(user.ID)}>Delete</button> </div> </div> </div> ))} </div> ); } export default UserList;
View more

Copy the code given below and paste it in the respective files located in the client directory (birthdaygreetings/src/) using an IDE and save the file.

    
App.css
copy
body { margin: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; background-color: #ffffff; height: inherit; } .inputs { width: 90%; padding: 15px; margin: 15px 0 22px 0; display: inline-block; border: none; background: #f1f1f1; border-radius: 8px; } h1, h2, h3, h4, h5, h6, p { margin: 1; } #login { height: 29rem; } .Header{ display: flex; align-items: center; gap: 54%; }
View more
    
App.js
copy
import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; import Layout from "./Layout"; import Signup from "./SignUp"; import ListUsers from "./ListUsers"; import UserProfile from "./UserProfile"; function App() { return ( <HashRouter> <Routes> <Route path="/" element={<Layout />} /> <Route path="/signup" element={<Signup />} /> <Route path="/addUserPage" element={<UserProfile />} /> <Route path="/ListUsers" element={<ListUsers />} /> <Route path="" element={<Navigate to="/" replace />} /> <Route path="*" element={<Navigate to="/" replace />} /> </Routes> </HashRouter> ); } export default App;
View more
    
index.css
copy
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; }
View more
    
index.js
copy
import "./App.css"; import React from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; const container = document.getElementById("root"); const root = createRoot(container); root.render( <React.StrictMode> <App /> </React.StrictMode> );
View more
    
Layout.js
copy
import UserProfile from "./UserProfile"; import LoginPage from "./LoginPage.js"; import { useEffect, useState } from "react"; function Layout() { const [isFetching, setIsFetching] = useState(true); const [isUserAuthenticated, setIsUserAuthenticated] = useState(false); const [userDetails, setUserDetails] = useState({ firstName: "", lastName: "", mailid: "", timeZone: "", createdTime: "", }); useEffect(() => { window.catalyst.auth.isUserAuthenticated().then((result) => { setUserDetails({ firstName: result.content.first_name, lastName: result.content.last_name, mailid: result.content.email_id, timeZone: result.content.time_zone, createdTime: result.content.created_time, }); setIsUserAuthenticated(true); }) .catch((err) => {}) .finally(() => { setIsFetching(false); }); }, []); return ( <> {isFetching ? ( <p>Loading ….</p> ) : isUserAuthenticated ? ( <UserProfile userDetails={userDetails} /> ) : ( <LoginPage /> )} </> ); } export default Layout;
View more
    
ListUsers.js
copy
import { useState, useEffect } from "react"; import axios from "axios"; import UserList from "./components/UserList"; import Modal from "./components/Modal"; import TopBar from "./components/TopBar"; function ListUsers() { const [users, setUsers] = useState([]); const [editData, setEditData] = useState(null); const [isModelOpen, setModal] = useState(false); const fetchUsers = async () => { try { const response = await axios.get("/server/advance_function/getReminder"); setUsers(response.data); } catch (error) { console.error("Error fetching users:", error); } }; useEffect(() => { fetchUsers(); }, []); const handleEdit = (id) => { const userToEdit = users.find((user) => user.ID === id); setEditData(userToEdit); setModal(true); }; const handleUpdate = async (updatedData) => { try { await axios.put("/server/advance_function/updateReminder", updatedData); alert("User updated successfully!"); setEditData(null); setModal(false); fetchUsers(); } catch (error) { console.error("Error updating user:", error); } }; const handleDelete = async (id) => { if (window.confirm("Are you sure you want to delete this birthday wish?")) { try { await axios.delete(`/server/advance_function/deleteReminder/${id}`); setUsers(users.filter((user) => user.ID !== id)); alert("User deleted successfully!"); } catch (error) { console.error("Error deleting user:", error); } } }; const handleToggle = async (ID, checked) => { const AutoSendStatus = checked ? "enable" : "disable"; try { await axios.patch("/server/advance_function/toggleAutoSend", { id: ID, status: AutoSendStatus, }); setUsers((prevUsers) => prevUsers.map((user) => user.ID === ID ? { ...user, AutoSend: checked } : user ) ); } catch (error) { console.error("Error toggling the user:", error); } }; return ( <> <div > <TopBar /> </div> <div className="userlist-div" style={{height: "calc(100vh - 60px)",margin: "60px 0 0"}}> <UserList users={users} onEdit={handleEdit} onDelete={handleDelete} onToggle={handleToggle} /> {isModelOpen && ( <Modal editData={editData} onUpdate={handleUpdate} onClose={() => setModal(false)} /> )} </div> </> ); } export default ListUsers;
View more
    
LoginPage.js
copy
import { useEffect } from "react"; import { Link } from "react-router-dom"; const LoginPage = () => { useEffect(() => { // Configuration is optional const config = { css_url: "/app/embeddediframe.css", // Login page customization CSS file path, if not provided default CSS will be rendered is_customize_forgot_password: false, // Default value is false. Set to true to customize Forgot Password page forgot_password_id: "login", // Element ID where the Forgot Password page should be loaded, defaults to "loginDivElementId" forgot_password_css_url: "/app/fpwd.css", // Forgot Password page customization CSS file path, if not provided default CSS will be rendered }; window.catalyst.auth.signIn("login", config); }, []); return ( <div className="container"> <center> <h1 className="title">Birthday Greetings</h1> </center> <div id="login"></div> <p className="homepage"> <b> Don't have an account?{" "} <Link to="/signup" style={{ color: "blue", textDecorationLine: "underline" }}> Sign-up </Link>{" "} now! </b> </p> </div> ); }; export default LoginPage;
View more
    
SignUp.css
copy
input[type="submit"] { background-color: green; color: white; width: 40%; padding: 8px; border-radius: 8px; text-align: center; border: none; cursor: pointer; } #link { font-size: medium; color: blue; } .modal-content { background-color: #c0c0c0; margin: 30px auto; } .signupfnbtn { width: 30%; padding: 8px; border-radius: 8px; background-color: green; height: 100%; } p { text-align: center; font-size: medium; font-weight: bold; }
View more
    
SignUp.js
copy
import "./SignUp.css"; import React, { useState } from "react"; function Signup() { const [displayText, setDisplayText] = useState(""); const [form, setForm] = useState({ firstName: "", lastName: "", email: "", }); const [showForm, setShowForm] = useState(true); const handleSubmit = async (event) => { event.preventDefault(); setShowForm(false); setDisplayText( "An account verification email has been sent to your email address" ); const data = { first_name: form.firstName, last_name: form.lastName, email_id: form.email, platform_type: "web", }; try { const auth = window.catalyst.auth; const signupResponse = await auth.signUp(data); if (signupResponse.status === 200) { setTimeout(() => { window.location.href = "index.html"; }, 3000); } else { alert(signupResponse.message); } } catch (error) { console.error("Error during signup:", error); alert("An error occurred during signup. Please try again."); setShowForm(true); // Show the form again if there's an error } }; const handleInputChange = (e) => { const { name, value } = e.target; setForm((prevForm) => ({ ...prevForm, [name]: value, })); }; return ( <div id="signup" className="signup"> {showForm ? ( <div> <center> <img width="80px" height="80px" src="https://cdn2.iconfinder.com/data/icons/user-management/512/profile_settings-512.png" alt="User Profile" /> <h1>User Profile Management</h1> </center> <form onSubmit={handleSubmit} className="modal-content"> <center> <h1>Sign Up</h1> <p>Please fill this form to sign up for a new account.</p> </center> <label htmlFor="firstName"> <b>First Name</b> <input name="firstName" className="inputs" placeholder="Enter First Name" value={form.firstName} onChange={handleInputChange} required /> </label> <label htmlFor="lastName"> <b>Last Name</b> <input name="lastName" className="inputs" placeholder="Enter Last Name" value={form.lastName} onChange={handleInputChange} required /> </label> <label htmlFor="email"> <b>Email</b> <input name="email" className="inputs" placeholder="Enter email address" value={form.email} onChange={handleInputChange} required /> </label> <p> By creating an account, you agree to our{" "} <a href="https://www.zoho.com/catalyst/terms.html" target="_blank" rel="noopener noreferrer" id="link" > Terms & Conditions </a> . </p> <center> <input type="submit" value="Sign Up" className="signupfnbtn" /> </center> </form> </div> ) : ( <p>{displayText}</p> )} </div> ); } export default Signup;
View more
    
UserProfile.css
copy
.app-container{ overflow: auto; } ::-webkit-scrollbar{ width: 5px; } ::-webkit-scrollbar-track{ background-color: rgb(34, 34, 59); } ::-webkit-scrollbar-thumb{ background-color: rgb(150, 150, 150); } .Header{ display: flex; align-items: center; gap: 54%; }
View more
    
UserProfile.js
copy
import "./UserProfile.css"; import axios from "axios"; import Form from "./components/Form"; import TopBar from "./components/TopBar"; function UserProfile() { const handleSubmit = async (formData) => { try { await axios.post("/server/advance_function/insertReminder",formData); alert("Reminder added successfully!"); window.location.reload(); } catch (error) { console.error("Error submitting form:", error); } }; return ( <div className="app-container"> <div className="Header"> <TopBar /> </div> <div className="form-div"> <Form onSubmit={handleSubmit} /> </div> </div> ); } export default UserProfile;
View more

Update the client-package.json file present in the birthdaygreetings/ directory as shown below.

    
client-package.json
copy
{ "name": "birthdaygreetings", "version": "0.0.1", "homepage": "index.html", "login_redirect": "index.html" }
View more

The client directory is now configured.

Let’s go over the business logic of the application.

  • Authentication:
    • The first page of the application will be the login page. Along with the login page, the user will be provided with the option to create a new account or reset the password of an existing account.
    • The user will only be able to create an account if they satisfy the condition coded in the Custom User Validation function.
    • When they successfully register for an account, they will have to verify their account using the verification link sent to their email.
    • Once they have verified their account and created a valid password, they will be allowed to log in to the app and begin using the application.
  • Scheduling the cron (reminder creation):
    • The end user will now create a birthday greeting by providing the following details:
      • Name
      • Date of birth
      • Custom message
      • Email address of the recipient
    • Once these details are submitted, the Dynamic Cron will be created, and it will be scheduled to submit a recurring job every year to the job pool on the date of the birthday.
  • Manage the reminders:
    • After creating the required reminders, you can view a list of reminders in the application. You can also disable, edit, and delete reminders.
    • The disable action is handled using a toggle. By default, it will be enabled. If disabled, or updated in any manner, the change will be updated in the Data Store, and the Dynamic Cron will be automatically adjusted per the new requirement.
  • Log out functionality:
    • Finally, once you have completed all of the required operations, you can safely log out of the application.

Last Updated 2025-04-01 11:10:20 +0530 +0530

RELATED LINKS

Client Directory