Configurar el cliente
Configuremos el componente cliente.
El directorio del cliente de la React web app contiene los siguientes archivos:
- El directorio raíz del cliente contiene un archivo client-package.json, que es un archivo de configuración que define el nombre, versión, página de inicio predeterminada y página de redirección del componente cliente.
- El directorio del cliente birthdaygreetings contiene dos subcarpetas, según la estructura de proyecto predeterminada de una React app:
- La carpeta public generalmente se usa para contener archivos que pueden ser accedidos abiertamente por los navegadores a través de URLs públicas, como archivos de iconos de la web app, el archivo index.html.
- La carpeta src contiene los archivos fuente de la aplicación que se incluirán en la carpeta build cuando compilemos la React app.
- El directorio del cliente también contiene el archivo de dependencias package.json y un archivo oculto .gitignore.
Los archivos en el directorio BirthdayGreetings/birthdaygreetings/public incluyen:
- Archivos nativos de React como Tests.js, index.js, reportWebVitals.js, logo.svg y App.test.js.
- index.html Contiene un SDK web de Catalyst que te permite acceder a los componentes de Catalyst.
- Adicionalmente, crearemos los siguientes archivos:
- embeddediframe.css: Contendrá los elementos de estilo requeridos para los formularios de inicio de sesión presentes en tu aplicación.
- fpwd.css: Contendrá los elementos de estilo requeridos para las pantallas de olvidé mi contraseña presentes en tu aplicación.
Los archivos en el directorio BirthdayGreetings/birthdaygreetings/src incluyen:
- Archivos nativos de React como setupTests.js, reportWebVitals.js, logo.svg y App.test.js.
- App.js: Contendrá las rutas hash de tu aplicación.
- App.css: Contendrá los elementos de estilo generales de tu aplicación.
- index.js: Actuará como el punto de entrada de tu aplicación.
- index.css: Contiene el estilo de los elementos presentes en el archivo index.js.
- Agregaremos los siguientes archivos adicionales al directorio src:
- Layout.js: Contendrá el componente React para la lógica de la aplicación.
- LoginPage.js: Contendrá el componente React para las páginas de inicio de sesión que generaste en la consola de Catalyst.
- UserProfile.js: Contendrá la página de perfil de usuario, que muestra una barra superior y un formulario para enviar datos de recordatorio al servidor.
- UserProfile.css: Contendrá los elementos de estilo usados para la página de perfil de usuario, incluyendo configuraciones personalizadas de barra de desplazamiento y ajustes de diseño para la sección del encabezado.
- Signup.js: Contendrá el componente React para las páginas de Signup que generaste en la consola de Catalyst.
- Signup.css: Contendrá los elementos de estilo para la página de Signup en la aplicación.
- ListUsers.js: Contendrá la página que lista todos los recordatorios que has configurado, permite editar y eliminar, y proporciona la capacidad de alternar el estado del recordatorio usando solicitudes Axios.
- Adicionalmente, necesitas crear una carpeta llamada components en el directorio src. El directorio BirthdayGreetings/birthdaygreetings/src/components/ incluirá los siguientes archivos de código:
- form.jsx: Contendrá el componente de formulario responsable de gestionar datos del formulario, manejar cambios de entrada y enviar los datos del formulario al componente padre a través de la función onSubmit.
- modal.jsx: Contendrá la funcionalidad modal para editar datos de usuario, incluyendo campos de entrada para nombre, mensaje, cumpleaños y correo electrónico, junto con un botón de actualización.
- modal.css: Contendrá el estilo para el componente modal, incluyendo diseño, campos de entrada y botones para editar datos de usuario con un fondo oscuro y contenido centrado.
- ToggleSwitch.jsx: Contendrá la lógica para el componente de interruptor de alternancia, permitiendo a los usuarios alternar entre dos estados, como habilitar o deshabilitar una característica.
- toggleSwitch.css: Contendrá el estilo para un interruptor de alternancia deslizante con efectos de transición para los estados activado y desactivado.
- TopBar.jsx: Contendrá la estructura de la barra de navegación superior, incluyendo enlaces a páginas como “Add User” y “List User,” un título en el centro y un botón de “Sign-out” a la derecha.
- topBar.css: Contendrá los elementos de estilo requeridos para estilizar la barra de navegación superior, incluyendo diseño, apariencia de botones y posicionamiento fijo.
- UserList.jsx: Contendrá la estructura para renderizar una lista de recordatorios con la opción de alternar, editar o eliminar cada recordatorio.
- Userlist.css: Contendrá los elementos de estilo requeridos para estilizar la lista de usuarios, incluyendo diseño, estilo de elementos. También contendrá los diseños de botones para las acciones de editar y eliminar.
Codificaremos los archivos 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 y Userlist.css.
También modificaremos el client-package.json para asegurar que la página de inicio de la aplicación sea la página de login.
Instalar paquetes adicionales de React
Antes de comenzar a agregar código a tus archivos, necesitas instalar los siguientes paquetes:
- react-router-dom: Este paquete es requerido para realizar enrutamiento hash.
- axios: Para manejar las promesas del cliente de forma fluida.
Instala el paquete react-router-dom ejecutando el siguiente comando en el directorio BirthdayGreetings/birthdaygreetings/public/ usando tu terminal:
Instala el paquete axios ejecutando el siguiente comando en el directorio BirthdayGreetings/birthdaygreetings/public/ usando tu terminal:
Este es el directorio del proyecto después de que hayas creado los archivos requeridos y eliminado los innecesarios.

Copia el código dado a continuación y pégalo en los archivos respectivos ubicados en el directorio del cliente (birthdaygreetings/public/) usando un IDE y guarda el archivo.
<!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>
@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;
}
@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;
}
@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;
}
Copia el código que se muestra a continuación y pégalo en los archivos respectivos ubicados en el directorio del cliente (birthdaygreetings/src/components/) usando un IDE y guarda el archivo.
.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%;
}
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;
.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;
}
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} // Establecer fecha máxima como hoy
/>
</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;
.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);
}
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;
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;
}
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>
</>
)
}
.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);
}
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;
Copia el código que se muestra a continuación y pégalo en los archivos respectivos ubicados en el directorio del cliente (birthdaygreetings/src/) usando un IDE y guarda el archivo.
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%;
}
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;
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;
}
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>
);
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;
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;
import { useEffect } from "react";
import { Link } from "react-router-dom";
const LoginPage = () => {
useEffect(() => {
// La configuración es opcional
const config = {
css_url: "/app/embeddediframe.css", // Ruta del archivo CSS de personalización de la página de inicio de sesión, si no se proporciona se renderizará el CSS por defecto
is_customize_forgot_password: false, // Por defecto value is false. Set to true to customize Forgot Password page
forgot_password_id: "login", // ID del elemento donde se cargará la página de contraseña olvidada, por defecto "loginDivElementId"
forgot_password_css_url: "/app/fpwd.css", // Ruta del archivo CSS de personalización de la página de contraseña olvidada, si no se proporciona se renderizará el CSS por defecto
};
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;
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;
}
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;
.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%;
}
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;
Actualiza el archivo client-package.json presente en el directorio birthdaygreetings/ como se muestra a continuación.
{
"name": "birthdaygreetings",
"version": "0.0.1",
"homepage": "index.html",
"login_redirect": "index.html"
}
El directorio del cliente ahora está configurado.
Repasemos la lógica de negocio de la aplicación.
- Autenticación:
- La primera página de la aplicación será la página de inicio de sesión. Junto con la página de inicio de sesión, se le proporcionará al usuario la opción de crear una nueva cuenta o restablecer la contraseña de una cuenta existente.
- El usuario solo podrá crear una cuenta si cumple con la condición codificada en la función Custom User Validation.
- Cuando se registre exitosamente para una cuenta, tendrá que verificar su cuenta usando el enlace de verificación enviado a su correo electrónico.
- Una vez que haya verificado su cuenta y creado una contraseña válida, se le permitirá iniciar sesión en la aplicación y comenzar a usarla.
- Programación del cron (creación de recordatorios):
- El usuario final ahora creará un saludo de cumpleaños proporcionando los siguientes detalles:
- Nombre
- Fecha de nacimiento
- Mensaje personalizado
- Dirección de correo electrónico del destinatario
- Una vez que se envíen estos detalles, se creará el Dynamic Cron y se programará para enviar un job recurrente cada año al job pool en la fecha del cumpleaños.
- El usuario final ahora creará un saludo de cumpleaños proporcionando los siguientes detalles:
- Gestionar los recordatorios:
- Después de crear los recordatorios requeridos, puedes ver una lista de recordatorios en la aplicación. También puedes desactivar, editar y eliminar recordatorios.
- La acción de desactivación se maneja mediante un toggle. Por defecto, estará habilitado. Si se deshabilita o se actualiza de cualquier manera, el cambio se actualizará en el Data Store, y el Dynamic Cron se ajustará automáticamente según el nuevo requisito.
- Funcionalidad de cierre de sesión:
- Finalmente, una vez que hayas completado todas las operaciones requeridas, puedes cerrar sesión de la aplicación de forma segura.
Última actualización 2026-03-30 13:40:30 +0530 IST

