diff --git a/lib/login/ui/web/left_panel.dart b/lib/login/ui/web/left_panel.dart index a485d772b..71673d81d 100644 --- a/lib/login/ui/web/left_panel.dart +++ b/lib/login/ui/web/left_panel.dart @@ -23,154 +23,117 @@ class LeftPanel extends HookConsumerWidget { .watch(loadingProvider) .maybeWhen(data: (data) => data, orElse: () => false); - return Column( - children: [ - SizedBox( - height: 160, - child: Row( - children: [ - Expanded( - flex: 3, - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset('assets/images/logo.png', - width: 70, height: 70), - const SizedBox(width: 20), - const Text('MyECL', - style: TextStyle( - fontSize: 30, fontWeight: FontWeight.bold)), - const SizedBox(width: 15), - const Text("-", - style: - TextStyle(fontSize: 25, color: Colors.black)), - const SizedBox(width: 15), - const Text("L'application de l'associatif centralien", - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.black)), + return Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SizedBox( + height: 100, + ), + Flexible( + child: SvgPicture.asset('assets/images/login.svg', width: 350)), + const SizedBox(height: 70), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: WaitingButton( + onTap: () async { + await authNotifier.getTokenFromRequest(); + ref.watch(authTokenProvider).when( + data: (token) { + QR.to(pathForwarding.path); + }, + error: (e, s) { + displayToast(context, TypeMsg.error, + LoginTextConstants.loginFailed); + }, + loading: () {}); + }, + builder: (child) => Container( + width: 400, + height: 60, + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [ + Color(0xFFFF8A14), + Color.fromARGB(255, 255, 114, 0) ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, ), - ), - ), - const Spacer(flex: 1) - ], - )), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Spacer(), - Expanded( - flex: 5, - child: SvgPicture.asset('assets/images/login.svg', - width: 350, height: double.infinity)), - const SizedBox(height: 70), - WaitingButton( - onTap: () async { - await authNotifier.getTokenFromRequest(); - ref.watch(authTokenProvider).when( - data: (token) { - QR.to(pathForwarding.path); - }, - error: (e, s) { - displayToast(context, TypeMsg.error, - LoginTextConstants.loginFailed); - }, - loading: () {}); - }, - builder: (child) => Container( - width: 400, - height: 60, - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - Color(0xFFFF8A14), - Color.fromARGB(255, 255, 114, 0) - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: const Color.fromARGB(255, 255, 114, 0) + .withOpacity(0.2), + spreadRadius: 3, + blurRadius: 7, + offset: const Offset(0, 3), ), - borderRadius: BorderRadius.circular(20), - boxShadow: [ - BoxShadow( - color: const Color.fromARGB(255, 255, 114, 0) - .withOpacity(0.2), - spreadRadius: 3, - blurRadius: 7, - offset: const Offset(0, 3), - ), - ], - ), - child: child), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text(LoginTextConstants.signIn, - style: TextStyle( - fontSize: 30, - fontWeight: FontWeight.bold, - color: Colors.white)), - Container( - margin: const EdgeInsets.only(left: 20), - child: isLoading - ? const Padding( - padding: EdgeInsets.all(12.0), - child: CircularProgressIndicator( - color: Colors.white, - ), - ) - : const HeroIcon( - HeroIcons.arrowRight, + ], + ), + child: child), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text(LoginTextConstants.signIn, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + color: Colors.white)), + Container( + margin: const EdgeInsets.only(left: 20), + child: isLoading + ? const Padding( + padding: EdgeInsets.all(12.0), + child: CircularProgressIndicator( color: Colors.white, - size: 35.0, ), - ), - ], - ), + ) + : const HeroIcon( + HeroIcons.arrowRight, + color: Colors.white, + size: 35.0, + ), + ), + ], ), - const Spacer(flex: 3), - SizedBox( - width: double.infinity, - child: Row( - children: [ - const Spacer(), - GestureDetector( - onTap: () { - QR.to(LoginRouter.createAccount); - controller?.forward(); - }, - child: const Text(LoginTextConstants.createAccount, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - decoration: TextDecoration.underline, - color: Color.fromARGB(255, 48, 48, 48))), - ), - const Spacer(flex: 4), - GestureDetector( - onTap: () { - QR.to(LoginRouter.forgotPassword); - controller?.forward(); - }, - child: const Text(LoginTextConstants.forgotPassword, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - decoration: TextDecoration.underline, - color: Color.fromARGB(255, 48, 48, 48))), - ), - const Spacer(), - ], - ), + ), + ), + const SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + GestureDetector( + onTap: () { + QR.to(LoginRouter.createAccount); + controller?.forward(); + }, + child: const Text(LoginTextConstants.createAccount, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + decoration: TextDecoration.underline, + color: Color.fromARGB(255, 48, 48, 48))), + ), + GestureDetector( + onTap: () { + QR.to(LoginRouter.forgotPassword); + controller?.forward(); + }, + child: const Text(LoginTextConstants.forgotPassword, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + decoration: TextDecoration.underline, + color: Color.fromARGB(255, 48, 48, 48))), ), - const SizedBox(height: 50), ], ), - ) - ], + const SizedBox(height: 50), + ], + ), ); } } diff --git a/lib/login/ui/web/right_panel.dart b/lib/login/ui/web/right_panel.dart index a76a865af..702fb5054 100644 --- a/lib/login/ui/web/right_panel.dart +++ b/lib/login/ui/web/right_panel.dart @@ -1,7 +1,7 @@ import 'dart:ui'; - import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:myecl/login/class/screen_shot.dart'; @@ -24,7 +24,6 @@ class RightPanel extends HookConsumerWidget { Curves.easeInOut.transform(resetAnimation.value))!; }); final isHovering = useState(false); - final screenShots = [ ScreenShot( path: 'assets/web/Calendrier.webp', @@ -56,127 +55,135 @@ class RightPanel extends HookConsumerWidget { description: "L'éléction des nouveaux mandats"), ]; - return Row( + return Stack( children: [ - const Spacer(flex: 3), - Expanded( - flex: 8, - child: PageView.builder( - controller: pageController, - itemBuilder: ((context, index) { - final screenShot = screenShots[screenShots.length - - (initialPage - index - 1) % screenShots.length - - 1]; - return Column( - children: [ - const SizedBox(height: 50), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox( - width: 20, - ), - if (screenShot.title.isNotEmpty) - Text( - screenShot.title, - style: const TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: Colors.white), - ), - if (screenShot.title.isNotEmpty) - const Text( - " - ", - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: Colors.white), - ), - Expanded( - child: AutoSizeText( - screenShot.description, - maxLines: 1, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white), - ), - ), - ], - ), - Expanded( - child: Container( - margin: const EdgeInsets.symmetric( - vertical: 20, horizontal: 15), - child: LayoutBuilder( - builder: (context, constraints) => MouseRegion( - onHover: (event) { - if (isHovering.value) { - offset.value = event.localPosition - - Offset(constraints.maxWidth / 2, - constraints.maxHeight / 2); - } - }, - onExit: (event) { - resetAnimation.forward(from: 0); - isHovering.value = false; - }, - onEnter: (event) { - resetAnimation.reverse(from: 1); - isHovering.value = true; - }, - child: Transform( - transform: Matrix4.identity() - ..setEntry(3, 2, 0.0005) - ..rotateX(0.0005 * offset.value.dy) - ..rotateY(-0.0005 * offset.value.dx), - alignment: FractionalOffset.center, - child: ClipRRect( - borderRadius: BorderRadius.circular(20), - child: BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 10, - sigmaY: 10, - ), - child: Container( - width: constraints.maxWidth, - decoration: BoxDecoration( - color: - Colors.grey.shade200.withOpacity(0.2), - borderRadius: BorderRadius.circular(20), - border: Border.all( - color: Colors.white.withOpacity(0.2), - width: 2), + if (MediaQuery.sizeOf(context).width > 1000) + const Positioned(bottom: 30, right: 15, child: EclairLogo()), + Positioned( + left: 15, + child: Padding( + padding: const EdgeInsets.only(top: 30), + child: Row( + children: [ + SizedBox( + width: 300, + height: MediaQuery.sizeOf(context).height - 60, + child: PageView.builder( + controller: pageController, + itemBuilder: ((context, index) { + final screenShot = screenShots[screenShots.length - + (initialPage - index - 1) % screenShots.length - + 1]; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: SizedBox( + height: 60, + child: screenShot.title.isNotEmpty + ? Flexible( + child: Column( + children: [ + AutoSizeText( + screenShot.title, + maxLines: 1, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 22, + fontWeight: + FontWeight.bold, + color: Colors.black), + ), + AutoSizeText( + screenShot.description, + maxLines: 1, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 20, + fontWeight: + FontWeight.bold, + color: Colors.black), + ) + ], + ), + ) + : Container(), ), - child: Padding( - padding: const EdgeInsets.all(10), - child: Image.asset( - screenShot.path, - fit: BoxFit.contain, + ), + ], + ), + const SizedBox( + height: 5, + ), + Flexible( + child: LayoutBuilder( + builder: (context, constraints) => MouseRegion( + onHover: (event) { + if (isHovering.value) { + offset.value = event.localPosition - + Offset(constraints.minWidth / 2, + constraints.minHeight / 2); + } + }, + onExit: (event) { + resetAnimation.forward(from: 0); + isHovering.value = false; + }, + onEnter: (event) { + resetAnimation.reverse(from: 1); + isHovering.value = true; + }, + child: Transform( + transform: Matrix4.identity() + ..setEntry(3, 2, 0.0005) + ..rotateX(0.0005 * offset.value.dy) + ..rotateY(-0.0005 * offset.value.dx), + alignment: FractionalOffset.center, + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 10, + sigmaY: 10, + ), + child: Container( + decoration: BoxDecoration( + color: Colors.grey.shade200 + .withOpacity(0.2), + borderRadius: + BorderRadius.circular(20), + border: Border.all( + color: Colors.white + .withOpacity(0.2), + width: 2), + ), + child: Padding( + padding: const EdgeInsets.all(10), + child: Image.asset( + screenShot.path, + fit: BoxFit.contain, + ), + ), + ), + ), ), ), ), ), ), - ), + ], ), - ), - ), + ); + }), ), - const SizedBox(height: 20), - ], - ); - }), - ), - ), - Expanded( - flex: 5, - child: Column(children: [ - const SizedBox(height: 50), - Row( - children: [ - const Spacer(flex: 5), - SmoothPageIndicator( + ), + Padding( + padding: const EdgeInsets.only(left: 15, bottom: 200.0), + child: SmoothPageIndicator( axisDirection: Axis.vertical, controller: pageController, count: screenShots.length, @@ -191,20 +198,58 @@ class RightPanel extends HookConsumerWidget { curve: Curves.easeInOut); }, ), - const Spacer(), - ], - ), - const Spacer(), - Image.asset('assets/images/eclair.png', width: 120, height: 120), - const SizedBox( - height: 30, - ), - const Text( - "Développé par ECLAIR", - style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), + ), + ], + ), + ), + ), + ], + ); + } +} + +class EclairLogo extends StatelessWidget { + const EclairLogo({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(40), + bottomRight: Radius.circular(40), + bottomLeft: Radius.circular(20), + topRight: Radius.circular(20)), + child: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 5, + sigmaY: 5, + ), + child: Container( + decoration: BoxDecoration( + color: Colors.grey.shade200.withOpacity(0.4), + border: + Border.all(color: Colors.white.withOpacity(0.4), width: 2), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(40), + bottomRight: Radius.circular(40), + bottomLeft: Radius.circular(20), + topRight: Radius.circular(20)), ), - const SizedBox(height: 50), - ])), + child: Image.asset('assets/images/eclair.png', + width: 120, height: 120), + ), + ), + ), + const SizedBox( + height: 15, + ), + const Text( + "Développée par ECLAIR", + textAlign: TextAlign.center, + style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), + ), ], ); } diff --git a/lib/login/ui/web/title_bar.dart b/lib/login/ui/web/title_bar.dart new file mode 100644 index 000000000..1ede7d956 --- /dev/null +++ b/lib/login/ui/web/title_bar.dart @@ -0,0 +1,37 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +class TitleBar extends StatelessWidget { + const TitleBar({super.key}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) => SizedBox( + width: constraints.maxWidth, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset('assets/images/logo.png', width: 70, height: 70), + const SizedBox(width: 20), + const Text('MyECL', + style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold)), + const SizedBox(width: 15), + const Text("-", + style: TextStyle(fontSize: 25, color: Colors.black)), + const SizedBox(width: 15), + const Expanded( + child: AutoSizeText("L'application de l'associatif centralien", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.black)), + ), + ], + ), + ), + ); + } +} diff --git a/lib/login/ui/web/web_sign_in.dart b/lib/login/ui/web/web_sign_in.dart index b539d53eb..21b0effd6 100644 --- a/lib/login/ui/web/web_sign_in.dart +++ b/lib/login/ui/web/web_sign_in.dart @@ -1,6 +1,9 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:myecl/login/ui/web/left_panel.dart'; import 'package:myecl/login/ui/web/right_panel.dart'; +import 'package:myecl/login/ui/web/title_bar.dart'; class WebSignIn extends StatelessWidget { const WebSignIn({super.key}); @@ -19,10 +22,39 @@ class WebSignIn extends StatelessWidget { ), ), ), - const Row(children: [ - Expanded(child: LeftPanel()), - Expanded(child: RightPanel()), - ]), + ListView( + children: [ + if (MediaQuery.sizeOf(context).width > 750) + Row(children: [ + SizedBox( + height: MediaQuery.sizeOf(context).height, + width: MediaQuery.sizeOf(context).width / 2, + child: const LeftPanel()), + SizedBox( + height: MediaQuery.sizeOf(context).height, + width: MediaQuery.sizeOf(context).width / 2, + child: const RightPanel()), + ]) + else + Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + const TitleBar(), + SizedBox( + height: MediaQuery.sizeOf(context).height * 4 / 5, + width: MediaQuery.sizeOf(context).width, + child: const LeftPanel()), + ], + ), + ], + ), + if (MediaQuery.sizeOf(context).width > 750) + Positioned( + top: 20, + left: 30, + child: SizedBox( + width: MediaQuery.sizeOf(context).width / 2, + child: const TitleBar())), ], ), ),