Initial commit: Penyerahan final Source code Tugas Akhir

This commit is contained in:
ferdiakhh
2025-07-10 19:15:14 +07:00
commit e1f2206b8a
687 changed files with 80132 additions and 0 deletions

View File

@ -0,0 +1,217 @@
import 'package:flutter/material.dart';
import 'package:initial_folder/helper/user_info.dart';
import 'package:initial_folder/providers/theme_provider.dart';
import 'package:initial_folder/screens/home/home_screen.dart';
import 'package:initial_folder/screens/login/login_screen.dart';
import 'package:initial_folder/screens/login/login_with_email/login_email_screen.dart';
import 'package:initial_folder/size_config.dart';
import 'package:initial_folder/theme.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
import 'package:shared_preferences/shared_preferences.dart';
class introScreen extends StatefulWidget {
const introScreen({Key? key}) : super(key: key);
@override
State<introScreen> createState() => _introScreenState();
}
class _introScreenState extends State<introScreen> {
int? _currentSlide;
CarouselController? buttonCarouselController;
@override
void initState() {
super.initState();
_currentSlide = 0; // Inisialisasi _currentSlide di initState
buttonCarouselController = CarouselController();
}
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);
return GestureDetector(
onHorizontalDragUpdate: (details) {
if (details.primaryDelta! > 0) {
buttonCarouselController?.previousPage(
duration: Duration(milliseconds: 300), curve: Curves.linear);
} else if (details.primaryDelta! < 0) {
buttonCarouselController?.nextPage(
duration: Duration(milliseconds: 300), curve: Curves.linear);
}
},
child: Scaffold(
body: Stack(
children: [
Positioned(
top: getProportionateScreenHeight(37),
left: 0,
right: 0,
child: _currentSlide == 2
? Padding(
padding: EdgeInsets.only(
right: getProportionateScreenWidth(15)),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: () async {
await UsersInfo().setStateintro('true');
Navigator.of(context).pushNamedAndRemoveUntil(
LoginEmail.routeName,
(Route<dynamic> route) => false);
},
child: Text(
'Login',
style: thirdTextStyle.copyWith(
fontSize: getProportionateScreenHeight(11)),
),
)
],
),
)
: SizedBox(), // Jika _currentSlide bukan 2, widget tidak ditampilkan
),
Positioned(
top: getProportionateScreenHeight(40),
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(3, (index) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
width: _currentSlide == index ? 20.0 : 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(horizontal: 3.0),
decoration: BoxDecoration(
borderRadius: _currentSlide == index
? BorderRadius.circular(50)
: BorderRadius.circular(50),
shape: _currentSlide == index
? BoxShape.rectangle
: BoxShape.rectangle,
color: _currentSlide == index ? fourthColor : Colors.grey,
),
);
}),
),
),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/intro_image.png',
width: getProportionateScreenWidth(200),
),
Padding(
padding: EdgeInsets.only(
top: getProportionateScreenHeight(15),
bottom: getProportionateScreenHeight(15)),
child: CarouselSlider(
carouselController: buttonCarouselController,
options: CarouselOptions(
height: getProportionateScreenHeight(150),
enableInfiniteScroll: false,
viewportFraction: 1.0,
initialPage: 0, // Change this to 0
onPageChanged: (index, reason) {
setState(() {
_currentSlide = index;
});
},
),
items: [
"WELCOME TO VOCASIA -\nUNLOCK YOUR LEARNING\nPOTENTIAL!",
"EXPLORE BOUNDLESS\nKNOWLEDGE - ANYTIME,\nANYWHERE.",
"JOIN OUR COMMUNITY OF\nLEARNERS - LET'S GROW\nTOGETHER!"
].map((i) {
return Builder(
builder: (BuildContext context) {
return Text(
'$i',
style: thirdTextStyle.copyWith(
fontWeight: FontWeight.w900,
fontSize: getProportionateScreenWidth(23),
color:
Theme.of(context).colorScheme.onBackground,
),
textAlign: TextAlign.center,
);
},
);
}).toList(),
),
),
],
),
),
Positioned(
bottom: getProportionateScreenHeight(25),
left: 0,
right: 0,
child: Center(
child: GestureDetector(
onTap: () async {
await UsersInfo().setStateintro('true');
if (_currentSlide == 2) {
Navigator.of(context).pushNamedAndRemoveUntil(
HomeScreen.routeName, (Route<dynamic> route) => false);
print('nanti');
} else {
buttonCarouselController?.nextPage(
duration: Duration(milliseconds: 300),
curve: Curves.linear);
}
},
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
width: _currentSlide == 2
? getProportionateScreenWidth(200)
: 55.0,
height: _currentSlide == 2
? getProportionateScreenWidth(60)
: 55.0,
margin: EdgeInsets.symmetric(horizontal: 3.0),
decoration: BoxDecoration(
borderRadius: _currentSlide == 2
? BorderRadius.circular(15)
: BorderRadius.circular(50),
shape: _currentSlide == 2
? BoxShape.rectangle
: BoxShape.rectangle,
color: themeProvider.themeData == ThemeClass.darkmode
?primaryColor : primaryColorligtmode,
),
child: Center(
child: _currentSlide == 2
? AnimatedOpacity(
duration: Duration(milliseconds: 1000),
opacity: _currentSlide == 2 ? 1.0 : 0.0,
child: Text(
"Let's Explore",
textAlign: TextAlign.center,
style: thirdTextStyle.copyWith(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 20,
),
),
)
: Icon(
Icons.arrow_forward_rounded,
color: Colors.white,
),
),
),
)),
),
],
),
),
);
}
}

View File

@ -0,0 +1,194 @@
import 'dart:async';
// import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:initial_folder/helper/user_info.dart';
import 'package:initial_folder/providers/incomplete_profile_provider.dart';
// import 'package:initial_folder/providers/notification_provider.dart';
import 'package:initial_folder/providers/user_info_provider.dart';
// import 'package:initial_folder/screens/home/components/notification.dart';
import 'package:initial_folder/screens/home/home_screen.dart';
import 'package:initial_folder/screens/login/login_screen.dart';
import 'package:initial_folder/screens/login/login_with_email/login_email_screen.dart';
import 'package:initial_folder/screens/profile/account_sign_in/incomplete_profile_screen.dart';
import 'package:initial_folder/providers/firebase_authentication_provider.dart';
import 'package:initial_folder/providers/page_provider.dart';
import 'package:initial_folder/screens/splash/intro_screen.dart';
import 'package:initial_folder/services/auth_service.dart';
import 'package:initial_folder/theme.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../size_config.dart';
class SplashScreenLogin extends StatefulWidget {
const SplashScreenLogin({Key? key}) : super(key: key);
static String routeName = "/splash";
@override
State<SplashScreenLogin> createState() => _SplashScreenLoginState();
}
class Condition {
static bool loginFirebase = false;
static bool loginEmail = false;
}
class _SplashScreenLoginState extends State<SplashScreenLogin>
with TickerProviderStateMixin {
late final AnimationController _controller = AnimationController(
duration: const Duration(seconds: 1),
vsync: this,
)..forward();
late final Animation<double> _animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
);
@override
void initState() {
super.initState();
// getIntroScreen();
Timer(const Duration(seconds: 3), () {
if (mounted) {
isLogin();
}
});
}
void isLogin() async {
var token = await UsersInfo().getToken();
var email = await UsersInfo().getEmail();
var stateintro = await UsersInfo().getStateintro();
var isTokenExpired = await AuthService().checkToken(token);
print("Token expired? ${isTokenExpired}");
if (isTokenExpired) {
print('masuk sini');
UsersInfo().logout();
Provider.of<FirebaseAuthenticationProvider>(context, listen: false)
.logout();
Provider.of<PageProvider>(context, listen: false).remove();
Navigator.of(context).pushNamedAndRemoveUntil(
LoginScreen.routeName, (Route<dynamic> route) => false);
print("state intro ${stateintro}");
if (stateintro == 'true') {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => LoginEmail(),
),
);
} else {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => introScreen(),
),
);
}
} else {
await Provider.of<UserInfoProvider>(context, listen: false)
.getUserInfo(email);
Condition.loginFirebase = true;
Condition.loginEmail = true;
if (!mounted) return;
IncompleteProfileProvider userInfoIncomplete =
Provider.of<IncompleteProfileProvider>(context, listen: false);
await userInfoIncomplete.getUserInfoIncomplete();
print("User info incomplete ${userInfoIncomplete.isUserInfoComplete}");
if (userInfoIncomplete.isUserInfoComplete == null) {
Navigator.of(context).pushNamedAndRemoveUntil(
LoginEmail.routeName, (Route<dynamic> route) => false);
return;
}
if (userInfoIncomplete.isUserInfoComplete!) {
Navigator.of(context).pushNamedAndRemoveUntil(
HomeScreen.routeName, (Route<dynamic> route) => false);
} else {
Navigator.of(context).pushNamedAndRemoveUntil(
IncompleteProfile.routeName, (Route<dynamic> route) => false);
}
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final Brightness brightnessValue =
MediaQuery.of(context).platformBrightness;
bool isDarkMode = brightnessValue == Brightness.dark;
String imagePath = Theme.of(context).brightness == Brightness.dark
? "assets/images/VOCASIA logo.png"
: "assets/images/Logo2.png";
SizeConfig().init(context);
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
flex: 10,
child: FadeTransition(
opacity: _animation,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
imagePath,
width: getProportionateScreenWidth(140),
),
Padding(
padding: EdgeInsets.all(10),
child: Text(
'Make You Competent',
style: primaryTextStyle.copyWith(
fontSize: getProportionateScreenHeight(11),
color: fourthColor),
),
)
// SizedBox(
// height: getProportionateScreenHeight(10),
// ),
// Text(
// "Make You Competent",
// style: primaryTextStyle.copyWith(
// fontWeight: reguler,
// fontSize: getProportionateScreenWidth(12.0),
// color: secondaryColor),
// ),
],
),
),
),
),
Flexible(
flex: 1,
child: Padding(
padding: EdgeInsets.only(
bottom: getProportionateScreenHeight(
25)), // Ubah sesuai kebutuhan Anda
child: Align(
alignment: Alignment.bottomCenter,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 3,
),
),
),
),
],
),
),
);
}
}