diff --git a/src/assets/icons/visu/gcu/gcu-arrow.svg b/src/assets/icons/visu/gcu/gcu-arrow.svg new file mode 100644 index 0000000000000000000000000000000000000000..0ccd27b100a7d2bcc66dc5be198891726c1dd69a --- /dev/null +++ b/src/assets/icons/visu/gcu/gcu-arrow.svg @@ -0,0 +1,9 @@ +<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="13.5" cy="13.5" r="12.5" fill="url(#paint0_radial)" stroke="#383941" stroke-width="2"/> +<defs> +<radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(13.5 0.84375) rotate(90) scale(8.26875 16.3748)"> +<stop stop-color="#2A2B30"/> +<stop offset="1" stop-color="#1B1C22"/> +</radialGradient> +</defs> +</svg> diff --git a/src/components/App.tsx b/src/components/App.tsx index af33ff0167d75d232e4495d1224f460890fc791d..023aae9a7299b0feba660b31a1b813893d31425c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -3,16 +3,22 @@ import React from 'react' import { HashRouter } from 'react-router-dom' import { createBrowserHistory } from 'history' import { Layout, Main, Content } from 'cozy-ui/transpiled/react/Layout' +import { useSelector } from 'react-redux' +import { AppStore } from 'store' import Routes from 'components/Routes/Routes' import Navbar from 'components/Navbar/Navbar' -import SplashRoot from './Splash/SplashRoot' +import SplashRoot from 'components/Splash/SplashRoot' import SplashScreen from 'components/Splash/SplashScreen' import SplashScreenError from 'components/Splash/SplashScreenError' +import GCUModal from 'components/GCU/GCUModal' export const history = createBrowserHistory() export const App = () => { + const { GCUApprovalDate } = useSelector( + (state: AppStore) => state.ecolyo.profile + ) return ( <HashRouter {...history}> <Layout> @@ -20,12 +26,18 @@ export const App = () => { splashComponent={SplashScreen} splashErrorComponent={SplashScreenError} > - <Navbar /> - <Main> - <Content className="app-content" tabIndex="-1"> - <Routes /> - </Content> - </Main> + {!GCUApprovalDate ? ( + <GCUModal /> + ) : ( + <> + <Navbar /> + <Main> + <Content className="app-content" tabIndex="-1"> + <Routes /> + </Content> + </Main> + </> + )} </SplashRoot> </Layout> </HashRouter> diff --git a/src/components/GCU/GCU.spec.tsx b/src/components/GCU/GCU.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9c0c7ccbba0b4f483effa31e9fc1fd739ac1bf8a --- /dev/null +++ b/src/components/GCU/GCU.spec.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import { shallow } from 'enzyme' +import GCU from 'components/GCU/GCU' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +describe('GCU component', () => { + it('should be rendered correctly', () => { + const component = shallow(<GCU />).getElement() + expect(component).toMatchSnapshot() + }) +}) diff --git a/src/components/GCU/GCU.tsx b/src/components/GCU/GCU.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e5179de83d6f87c281856c848057884b6b534706 --- /dev/null +++ b/src/components/GCU/GCU.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import './gcu.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' + +interface GCUProps { + fromOption?: boolean +} + +const GCU: React.FC<GCUProps> = ({ fromOption = false }: GCUProps) => { + const { t } = useI18n() + return ( + <div className="gcu-root"> + <div className="gcu-content"> + <h1 className="text-22-normal">{t('gcu.title')}</h1> + {!fromOption && <h2 className="text-16-normal">{t('gcu.subtitle')}</h2>} + <div className="gcu-content-title">{t('gcu.content.title')}</div> + <div>{t('gcu.content.intro')}</div> + <div className="gcu-content-title">{t('gcu.content.subtitle1')}</div> + <div>{t('gcu.content.content1')}</div> + <div className="gcu-content-title">{t('gcu.content.subtitle2')}</div> + <div>{t('gcu.content.content2')}</div> + <div className="gcu-content-title">{t('gcu.content.subtitle3')}</div> + <div>{t('gcu.content.content3')}</div> + <div className="gcu-content-title">{t('gcu.content.subtitle4')}</div> + <div>{t('gcu.content.content4')}</div> + <div className="gcu-content-title">{t('gcu.content.subtitle5')}</div> + <div>{t('gcu.content.content5')}</div> + <div className="gcu-content-title">{t('gcu.content.subtitle6')}</div> + <div>{t('gcu.content.content6')}</div> + <div className="gcu-content-title">{t('gcu.content.subtitle7')}</div> + <div>{t('gcu.content.content7_1')}</div> + <div>{t('gcu.content.content7_2')}</div> + <div>{t('gcu.content.content7_3')}</div> + <div>{t('gcu.content.content7_4')}</div> + <div>{t('gcu.content.content7_5')}</div> + </div> + </div> + ) +} + +export default GCU diff --git a/src/components/GCU/GCUModal.spec.tsx b/src/components/GCU/GCUModal.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bd891f40b9436c7717db560b8b7a43cbb911847e --- /dev/null +++ b/src/components/GCU/GCUModal.spec.tsx @@ -0,0 +1,94 @@ +import React from 'react' +import { mount } from 'enzyme' +import { Provider } from 'react-redux' +import GCUModal from 'components/GCU/GCUModal' +import { + createMockStore, + mockInitialEcolyoState, +} from '../../../tests/__mocks__/store' +import * as profileActions from 'store/profile/profile.actions' +import { Button } from '@material-ui/core' +import StyledIcon from 'components/CommonKit/Icon/StyledIcon' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +const updateProfileSpy = jest.spyOn(profileActions, 'updateProfile') + +describe('GCUModal component', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let store: any + beforeEach(() => { + store = createMockStore(mockInitialEcolyoState) + updateProfileSpy.mockClear() + }) + it('should be rendered correctly', () => { + const wrapper = mount( + <Provider store={store}> + <GCUModal /> + </Provider> + ) + expect(wrapper.find(StyledIcon)).toBeTruthy() + expect( + wrapper + .find(Button) + .first() + .prop('disabled') + ).toBeTruthy() + }) + it('should hide icon and enable button when scroll to the bottom', () => { + const wrapper = mount( + <Provider store={store}> + <GCUModal /> + </Provider> + ) + wrapper.find('.gcu-modal-content').simulate('scroll') + expect(wrapper.find(StyledIcon)).toMatchObject({}) + expect( + wrapper + .find(Button) + .first() + .prop('disabled') + ).toBeFalsy() + }) + it('should display icon and let button enabled when scroll to the bottom and scroll up', () => { + const wrapper = mount( + <Provider store={store}> + <GCUModal /> + </Provider> + ) + wrapper.find('.gcu-modal-content').simulate('scroll') + wrapper.find('.gcu-modal-content').simulate('scroll', { + target: { + scrollheight: -100, + }, + }) + expect(wrapper.find(StyledIcon)).toBeTruthy() + expect( + wrapper + .find(Button) + .first() + .prop('disabled') + ).toBeFalsy() + }) + it('should update profile when button is clicked', () => { + const wrapper = mount( + <Provider store={store}> + <GCUModal /> + </Provider> + ) + wrapper.find('.gcu-modal-content').simulate('scroll') + wrapper + .find(Button) + .first() + .simulate('click') + expect(updateProfileSpy).toBeCalledTimes(1) + }) +}) diff --git a/src/components/GCU/GCUModal.tsx b/src/components/GCU/GCUModal.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5861ef9bf1fe1f7cd098ebdd8182652d9557b4e1 --- /dev/null +++ b/src/components/GCU/GCUModal.tsx @@ -0,0 +1,78 @@ +import React, { useCallback, useState } from 'react' +import './gcumodal.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import { useDispatch } from 'react-redux' +import { updateProfile } from 'store/profile/profile.actions' +import { Button, Dialog } from '@material-ui/core' +import GCU from 'components/GCU/GCU' +import StyledIcon from 'components/CommonKit/Icon/StyledIcon' +import arrowIcon from 'assets/icons/visu/gcu/gcu-arrow.svg' +import { DateTime } from 'luxon' + +const GCUModal: React.FC = () => { + const { t } = useI18n() + const dispatch = useDispatch() + const [isBottom, setIsBottom] = useState<boolean>(false) + const [bottomReached, setBottomReached] = useState<boolean>(false) + + const handleScroll = (event: React.UIEvent<HTMLElement>) => { + const target = event.currentTarget + if (target.scrollHeight - target.scrollTop === target.clientHeight) { + setIsBottom(true) + setBottomReached(true) + } else { + setIsBottom(false) + } + } + + const handleGCUValidate = useCallback(() => { + dispatch( + updateProfile({ + GCUApprovalDate: DateTime.local().setZone('utc', { + keepLocalTime: true, + }), + }) + ) + }, [dispatch]) + + return ( + <Dialog + open={true} + disableBackdropClick + disableEscapeKeyDown + aria-labelledby={'accessibility-title'} + classes={{ + root: 'modal-root', + paper: 'modal-paper-full-screen', + }} + > + <div id={'accessibility-title'}> + {t('gcu_modal.accessibility.window_title')} + </div> + <div className="gcu-modal-root"> + <div className="gcu-modal-content" onScroll={handleScroll}> + <GCU /> + </div> + <div className="gcu-modal-footer"> + {!isBottom && ( + <StyledIcon className="gcu-modal-icon" icon={arrowIcon} size={27} /> + )} + <Button + aria-label={t('gcu_modal.accessibility.button_accept')} + onClick={handleGCUValidate} + className={'gcu-modal-button'} + disabled={!bottomReached} + classes={{ + root: 'btn-profile-next rounded', + label: 'text-16-normal', + }} + > + {t('gcu.button_accept')} + </Button> + </div> + </div> + </Dialog> + ) +} + +export default GCUModal diff --git a/src/components/GCU/__snapshots__/GCU.spec.tsx.snap b/src/components/GCU/__snapshots__/GCU.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..e077cfd5b9d104f492c024840f5b862da8ce1367 --- /dev/null +++ b/src/components/GCU/__snapshots__/GCU.spec.tsx.snap @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GCU component should be rendered correctly 1`] = ` +<div + className="gcu-root" +> + <div + className="gcu-content" + > + <h1 + className="text-22-normal" + > + gcu.title + </h1> + <h2 + className="text-16-normal" + > + gcu.subtitle + </h2> + <div + className="gcu-content-title" + > + gcu.content.title + </div> + <div> + gcu.content.intro + </div> + <div + className="gcu-content-title" + > + gcu.content.subtitle1 + </div> + <div> + gcu.content.content1 + </div> + <div + className="gcu-content-title" + > + gcu.content.subtitle2 + </div> + <div> + gcu.content.content2 + </div> + <div + className="gcu-content-title" + > + gcu.content.subtitle3 + </div> + <div> + gcu.content.content3 + </div> + <div + className="gcu-content-title" + > + gcu.content.subtitle4 + </div> + <div> + gcu.content.content4 + </div> + <div + className="gcu-content-title" + > + gcu.content.subtitle5 + </div> + <div> + gcu.content.content5 + </div> + <div + className="gcu-content-title" + > + gcu.content.subtitle6 + </div> + <div> + gcu.content.content6 + </div> + <div + className="gcu-content-title" + > + gcu.content.subtitle7 + </div> + <div> + gcu.content.content7_1 + </div> + <div> + gcu.content.content7_2 + </div> + <div> + gcu.content.content7_3 + </div> + <div> + gcu.content.content7_4 + </div> + <div> + gcu.content.content7_5 + </div> + </div> +</div> +`; diff --git a/src/components/GCU/gcu.scss b/src/components/GCU/gcu.scss new file mode 100644 index 0000000000000000000000000000000000000000..f3db9ccf2618050cb4cb410e0072b330ff23e373 --- /dev/null +++ b/src/components/GCU/gcu.scss @@ -0,0 +1,17 @@ +.gcu-root{ + height: 100%; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + .gcu-content{ + margin: 2rem; + > div:last-child{ + margin-bottom: 1rem; + } + .gcu-content-title{ + margin: 1rem 0 0.5rem; + } + } +} \ No newline at end of file diff --git a/src/components/GCU/gcumodal.scss b/src/components/GCU/gcumodal.scss new file mode 100644 index 0000000000000000000000000000000000000000..011629a7005b3b0c812927b36f141bb4ef503a41 --- /dev/null +++ b/src/components/GCU/gcumodal.scss @@ -0,0 +1,34 @@ +.gcu-modal-root{ + height: 100%; + width: 100%; + display: flex; + flex-direction: column; + .gcu-modal-content{ + position: relative; + overflow-x: hidden; + overflow-y: scroll; + flex: 1; + } + .gcu-modal-footer{ + position: relative; + margin: 1.5rem 0; + display: flex; + flex-direction: column; + align-items: center; + .gcu-modal-icon{ + position: absolute; + left: calc(50% - 13px); + top: -35px; + } + .rounded { + border-radius: 22px; + margin-left: 1rem; + margin-right: 1rem; + } + } +} +button.gcu-modal-button { + max-width: 12.5rem; + margin: 0.375rem 1rem; + padding: 0.5rem 1rem; +} \ No newline at end of file diff --git a/src/locales/fr.json b/src/locales/fr.json index a51565027431dc7ae12a7dfac668009147c65232..b44369f9f3c22a750468ca9451acaa80b8058296 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -369,6 +369,39 @@ "button_close": "Fermer la fenêtre de partage de retours" } }, + "gcu": { + "title": "Conditions générales d’utilisation d’Ecolyo – Service de la Métropole de Lyon", + "subtitle": "Envie de prendre le temps de relire ces CGU ces Conditions Générales d’Utilisation plus tard ? Vous pourrez les retrouver dans la page Options du service.", + "content": { + "title": "Ecolyo, késako ?", + "intro": "Ecolyo un service proposé par la Métropole de Lyon vous permettant de suivre au même endroit vos consommations d’électricité, de gaz et d’eau, en kWh, en litres, en euros et à différentes échelles de temps. Ce service vous permet également de participer à des défis individuels et vous offre une analyse de vos consommations. Des éco-gestes vous sont aussi proposés afin de vous permettre de réduire vos consommations. C’est un service gratuit qui prend la forme d’un site web dit « responsive », c’est-à-dire qu’il peut être consulté sur ordinateur ou sur mobile. Sur mobile il ressemble à une belle application.", + "subtitle1": "Comment ai-je accès à mes données d’électricité, de gaz et d’eau ?", + "content1": "Pour visualiser vos consommations réelles et profiter pleinement du potentiel de notre service, il vous faut au minimum un des trois compteurs communicants suivants : Linky (pour l’électricité), Gazpar (pour le gaz), Téléo (pour l’eau). Ces compteurs sont opérés par les gestionnaires de réseaux. Pour Linky, c’est Enedis, le gestionnaire de réseau de distribution d’électricité. Pour Gazpar, GRDF est responsable de cette gestion. Et pour Téléo, c’est Eau du Grand Lyon. Ces acteurs sont responsables de la relève de vos données. C’es données servent notamment votre fournisseur d’électricité, de gaz ou d’eau pour vous facturer. Des fournisseurs d’électricité ou de gaz il y en a des dizaines ! Les gestionnaires de réseaux (… et de votre compteur) ne sont que trois ! Nous avons donc décidé de travailler avec eux, au plus près de la donnée brute issue de vos compteurs. Il vous faudra donc avoir un compte chez Enedis, GRDF et Eau du Grand Lyon pour accéder à vos données. Si vous n’en avez pas, il suffira de vous en créer un. Ceci ne sera à faire qu’une fois, au début.", + "subtitle2": "Ecolyo se trouve dans un cloud personnel Grand Lyon, qu’est-ce que cela signifie ?", + "content2" : "Comme vous avez dû le remarquer, lors de votre première connexion à Ecolyo vous avez dû vous créer un Cloud Personnel Grand Lyon. Le service Ecolyo se trouve à l’intérieur de cet espace protégé. Dans ce cloud personnel, vous pourrez trouver également d’autres services. Toutes les données traitées par Ecolyo, mais aussi les autres services que vous seriez amenés à utiliser dans ce cloud personnel restent dans ce Cloud Personnel Grand Lyon et n’en sortent pas. Pour en savoir plus sur ce cloud et son utilisation, ainsi que la durée de conservation de vos données, vous pouvez lire les conditions générales d’utilisation du service ici.", + "subtitle3": "Et donc concrètement pour Ecolyo, quelles données sont collectées et qui y a accès ?", + "content3": "Pour qu’Ecolyo ait accès à vos données de consommations, vous devrez activer vos connecteurs dans la page Options. À ce moment-là, et à travers un court parcours, vous donnerez votre consentement à partager ces données avec le Service Ecolyo, et ce pour une durée limitée dans le temps. Chaque partenaire définit la durée de base du temps du partage des données. Vos connecteurs, une fois configurés, permettent le transfert de vos données de consommations au service Ecolyo. Le transfert de cette donnée se fait sans que personne n’y accède, pas même la Métropole de Lyon. En effet, ces données sont stockées et travaillées directement dans votre cloud personnel qui en assure la protection. Tous les calculs, analyses et traitements sur ces données sont faites DANS votre espace personnel sans visibilité sur le contenu des données par la Métropole de Lyon. Vous pouvez bien sûr mettre fin au partage de vos données de consommation à plusieurs niveaux : Vous pouvez supprimer le transfert quotidien de vos données en supprimant tout simplement le connecteur dans la Page Options. Attention : lors de la désinstallation du connecteur qui collecte vos données au sein du cloud, celui-ci ne va plus aller chercher vos données. Par contre, votre consentement chez le partenaire fournisseur est toujours actif jusqu’à votre révocation de consentement auprès de ce dernier. Pour révoquer votre consentement, il vous faudra contacter ou agir directement chez le partenaire en question : Enedis pour l’électricité ou GRDF pour le gaz. Pour l’électricité, vous pouvez peut supprimer votre consentement à partager vos données en écrivant directement à dataconnect(at)enedis.fr. Pour le gaz, il vous faudra vous connecter à votre espace GRDF et supprimer le consentement donné à la Métropole de Lyon dans la partie « Suivi de Consommations » puis « Données Consultées ». Pour supprimer l’ensemble de vos données ainsi que votre espace personnel Grand Lyon, contactez nous à ecolyo(at)grandlyon.com.", + "subtitle4": "Personne n’a donc accès à mes données, pas même la métropole de Lyon, vraiment ?", + "content4": "Comme expliqué dans le paragraphe précédent, la Métropole de Lyon n’accède ni à vos données de consommations ni aux données que vous communiqueriez via certaines parties du service comme le formulaire (celui-là même qui permet l’analyse de vos consommations personnalisée ainsi qu’une sélection d’éco-gestes personnalisés). Toutes ces informations sont bien gardées au chaud dans votre cloud personnel Grand Lyon. Seul vous pouvez accepter de partager vos données, documents ou fichiers privées avec la Métropole de Lyon, ses partenaires ou d’autres utilisateurs ou acteurs (publics ou privés) avec un consentement éclairé et une action expresse de votre part. La Métropole de Lyon n’a accès qu’à vos données de compte choisies, c’est-à-dire à l’email utilisé la toute première fois lors de la création de votre compte au niveau de la plateforme de cloud personnel. Nous ne l’utiliserons qu’à des fins de gestion du compte et de communication avec l’usager. Plus clairement, et en dehors de toute expérimentation, nous ne vous contacterons qu’en cas de problème majeur avec la gestion de votre compte ou bien sûr si vous nous contactez. Par ailleurs, vous pouvez recevoir un email de notre part indiquant la mise à disposition d'un nouveau bilan (mensuel) de vos consommations. Vous pouvez gérer l'inscription ou la désincription à cette notitication par email via la page Options du service. D’autre part sachez que, dans le cadre de l’amélioration de la qualité de notre service, des métriques d’usages sont périodiquement remontées et ce, de manière anonyme, sur un serveur. Par métrique d’usage on entend par exemple, le nombre de connecteurs connectés, le nombre de défis gagnés. Tout cela aura été anonymisé avant l’arrivée sur le serveur. Par exemple si VOUS avez installé uniquement le connecteur électricité et avait gagné le défi Simone Veille, nous récolterons simplement une information du type « UN utilisateur a connecté son connecteur électricité et a gagné le défi Simone Veille. » sans connaître l’identité de cet utilisateur.", + "subtitle5": "Mentions Légales", + "content5": "Pour plus d’information sur l’ensemble de vos droits concernant vos données personnelles, retrouvez ici les mentions légales du service.", + "subtitle6": "Encore des questions ?", + "content6": "N’hésitez pas à consulter la FAQ présente dans le service (page Options) ou à nous contacter via le formulaire de contact (la petite bulle jaune) présente sur l’ensemble des pages. Dernière option, contactez-nous directement à ecolyo(at)grandlyon.com.", + "subtitle7": "Lexique", + "content7_1": "Cloud personnel Grand Lyon : Cloud personnel : appelé aussi le « domicile numérique », le cloud personnel est souvent réduit à un simple espace de stockage de documents mais il est bien plus que ça. C'est un espace individuel et sécurisé où vous pouvez accéder à des services sans exposer aucune donnée à l’extérieur. Vous seul pouvez y accéder, personne d'autre.", + "content7_2": "Connecteur : def Inés ?", + "content7_3": "Compteur communicant : Un compteur communicant est un compteur qui mesure de manière précise et détaillée vos consommations et peut transmettre ces données au gestionnaire de réseau via une technologie radio (c'est le cas pour Gazpar et Téléo par exemple) ou via les réseaux électriques (via Courant Porteur en ligne, c'est le cas pour Linky par exemple).", + "content7_4": "Fournisseur : Votre fournisseur d’électricité, de gaz ou d’eau est l’entreprise qui vous facture votre électricité, gaz ou eau. Côté électricité il en existe aujourd’hui plus de 50, chacun proposant des tarifs différents.", + "content7_5": "Gestionnaire de réseau de distribution : Appelé aussi parfois distributeur, il est en charge de la livraison de votre électricité, gaz ou eau jusqu’à votre domicile. Il est aussi en charge du compteur qui relève vos consommations. Il transmet vos données de consommations à votre fournisseur afin qu’il vous facture. Il peut également les transmettre à tout acteur avec qui vous avez décidé de partager ces données." + } + }, + "gcu_modal": { + "button_accept": "J'accepte", + "accessibility": { + "window_title": "Conditions générales d’utilisation", + "button_accept": "Accepter les conditions générales d'utilisation" + } + }, "header": { "accessibility": { "button_back": "Retour à la page précédente", diff --git a/src/styles/components/_dialog.scss b/src/styles/components/_dialog.scss index 983b2fc1b1e894d6c80f91f05e07268b9fb87385..af98a94e9284193b92c819c6e3d4ef8b59ad1e20 100644 --- a/src/styles/components/_dialog.scss +++ b/src/styles/components/_dialog.scss @@ -44,3 +44,26 @@ div.modal-paper{ z-index: 10; } } + +div.modal-paper-full-screen{ + background: $grey-linear-gradient-background; + width: 36rem; + max-width: 100%; + height: 85vh; + max-height: 85vh; + padding: 0; + margin: 0; + box-sizing: border-box; + box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.55); + border-radius: 4px; + align-items: center; + color: $white; + @media #{$tablet} { + width: 35rem; + } + @media #{$large-phone} { + width: 100%; + height: 100%; + max-height: 100%; + } +} \ No newline at end of file