├── env_example.txt
├── web
├── favicon.ico
├── favicon-16x16.png
├── favicon-32x32.png
├── icons
│ ├── icon-192.png
│ ├── icon-384.png
│ ├── apple-touch-icon.png
│ ├── mstile-150x150.png
│ ├── icon-maskable-192.png
│ ├── icon-maskable-512.png
│ └── safari-pinned-tab.svg
├── manifest.json
├── github_login.js
└── index.html
├── assets
├── images
│ ├── events.jpg
│ ├── teams.jpg
│ ├── welcome.jpg
│ ├── fork_icon.png
│ ├── handshake.png
│ ├── ocy_logo.png
│ ├── add_skills.png
│ ├── github_logo.png
│ ├── google_logo.png
│ └── icon_community.png
└── fonts
│ ├── PublicSans_Bold.otf
│ ├── PublicSans_Regular.otf
│ └── PublicSans_ExtraBold.otf
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable-v21
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── values-night
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── ocy
│ │ │ │ │ └── ocyclient
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
└── build.gradle
├── lib
├── external
│ └── github_sign_in
│ │ └── lib
│ │ ├── github_sign_in.dart
│ │ └── src
│ │ ├── github_sign_in_result.dart
│ │ ├── github_sign_in_page.dart
│ │ └── github_sign_in.dart
├── models
│ ├── localization
│ │ └── language.dart
│ ├── user
│ │ └── user_model.dart
│ ├── team
│ │ └── team_model.dart
│ └── project
│ │ └── project_model.dart
├── blocs
│ ├── profile_bloc.dart
│ ├── edit_profile_bloc.dart
│ ├── community_bloc.dart
│ ├── navigation_bloc.dart
│ ├── teams_bloc.dart
│ ├── projects_bloc.dart
│ └── locale_bloc.dart
├── widgets
│ ├── Utils
│ │ ├── snackbar.dart
│ │ ├── measure_size_render_object.dart
│ │ ├── scroll_animation.dart
│ │ ├── common_widgets.dart
│ │ ├── custom_inputfields.dart
│ │ └── navigation_drawer.dart
│ ├── Milestones
│ │ └── milestones.dart
│ ├── Community
│ │ └── community.dart
│ ├── ComingSoon
│ │ └── coming_soon.dart
│ ├── Home
│ │ ├── home.dart
│ │ └── sub_pages
│ │ │ ├── events.dart
│ │ │ ├── intro.dart
│ │ │ ├── footer.dart
│ │ │ └── benefits.dart
│ ├── Auth
│ │ ├── page_view
│ │ │ └── login_intro_page.dart
│ │ └── login_signup.dart
│ ├── Teams
│ │ ├── member
│ │ │ ├── member_horizontal.dart
│ │ │ └── member_vertical.dart
│ │ ├── team_card.dart
│ │ └── teams.dart
│ └── Profile
│ │ ├── widgets
│ │ └── accounts.dart
│ │ ├── edit_profile.dart
│ │ └── profile.dart
├── utils
│ └── app_translations.dart
├── configs
│ └── config.dart
└── main.dart
├── attribution.md
├── firebase.json
├── dartdoc_options.yaml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── analysis_options.yaml
├── .metadata
├── data
└── teams.json
├── pubspec.yaml
├── .firebase
└── hosting.YnVpbGRcd2Vi.cache
├── CODE_OF_CONDUCT.md
└── README.md
/env_example.txt:
--------------------------------------------------------------------------------
1 | github_access_token = 'YOUR_TOKEN_HERE'
--------------------------------------------------------------------------------
/web/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/favicon.ico
--------------------------------------------------------------------------------
/web/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/favicon-16x16.png
--------------------------------------------------------------------------------
/web/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/favicon-32x32.png
--------------------------------------------------------------------------------
/web/icons/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/icons/icon-192.png
--------------------------------------------------------------------------------
/web/icons/icon-384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/icons/icon-384.png
--------------------------------------------------------------------------------
/assets/images/events.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/events.jpg
--------------------------------------------------------------------------------
/assets/images/teams.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/teams.jpg
--------------------------------------------------------------------------------
/assets/images/welcome.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/welcome.jpg
--------------------------------------------------------------------------------
/assets/images/fork_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/fork_icon.png
--------------------------------------------------------------------------------
/assets/images/handshake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/handshake.png
--------------------------------------------------------------------------------
/assets/images/ocy_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/ocy_logo.png
--------------------------------------------------------------------------------
/assets/images/add_skills.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/add_skills.png
--------------------------------------------------------------------------------
/assets/images/github_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/github_logo.png
--------------------------------------------------------------------------------
/assets/images/google_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/google_logo.png
--------------------------------------------------------------------------------
/web/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/web/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/assets/fonts/PublicSans_Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/fonts/PublicSans_Bold.otf
--------------------------------------------------------------------------------
/assets/images/icon_community.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/images/icon_community.png
--------------------------------------------------------------------------------
/web/icons/icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/icons/icon-maskable-192.png
--------------------------------------------------------------------------------
/web/icons/icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/web/icons/icon-maskable-512.png
--------------------------------------------------------------------------------
/assets/fonts/PublicSans_Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/fonts/PublicSans_Regular.otf
--------------------------------------------------------------------------------
/assets/fonts/PublicSans_ExtraBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/assets/fonts/PublicSans_ExtraBold.otf
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCodeyard/ocyclient/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/external/github_sign_in/lib/github_sign_in.dart:
--------------------------------------------------------------------------------
1 | library github_sign_in;
2 |
3 | export 'src/github_sign_in.dart';
4 | export 'src/github_sign_in_result.dart';
5 |
--------------------------------------------------------------------------------
/attribution.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/ocy/ocyclient/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.ocy.ocyclient
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/lib/models/localization/language.dart:
--------------------------------------------------------------------------------
1 | class Language {
2 | final String name;
3 | final String countryCode;
4 | final String languageCode;
5 |
6 | Language(this.name, this.countryCode, this.languageCode);
7 | }
8 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
7 |
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "public": "build/web",
4 | "ignore": [
5 | "firebase.json",
6 | "**/.*",
7 | "**/node_modules/**"
8 | ],
9 | "rewrites": [
10 | {
11 | "source": "**",
12 | "destination": "/index.html"
13 | }
14 | ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/blocs/profile_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// {@category Blocs}
4 | class ProfileBloc extends ChangeNotifier {
5 | int _currentSelectedMenuItem = 0;
6 |
7 | int get currentSelectedMenuItem => _currentSelectedMenuItem;
8 |
9 | void setCurrentSelectedItem(int index) {
10 | _currentSelectedMenuItem = index;
11 | notifyListeners();
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/lib/blocs/edit_profile_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// {@category Blocs}
4 | class EditProfileBloc extends ChangeNotifier {
5 | int _currentSelectedMenuItem = 0;
6 |
7 | int get currentSelectedMenuItem => _currentSelectedMenuItem;
8 |
9 | void setCurrentSelectedItem(int index) {
10 | _currentSelectedMenuItem = index;
11 | notifyListeners();
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/lib/blocs/community_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// {@category Blocs}
4 | class CommunityBloc extends ChangeNotifier {
5 | bool _hasCompletedCurtainAnimation = false;
6 |
7 | bool get hasCompletedCurtainAnimation => _hasCompletedCurtainAnimation;
8 |
9 | void setCurtainAnimationStatus() {
10 | _hasCompletedCurtainAnimation = true;
11 | notifyListeners();
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/lib/widgets/Utils/snackbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fluttertoast/fluttertoast.dart';
3 |
4 | showToast(String text) {
5 | Fluttertoast.showToast(
6 | msg: text,
7 | toastLength: Toast.LENGTH_SHORT,
8 | gravity: ToastGravity.BOTTOM_RIGHT,
9 | timeInSecForIosWeb: 2,
10 | webShowClose: true,
11 | webBgColor: "linear-gradient(60deg, #647DEE 12%, #7F53AC 100%)",
12 | webPosition: "left",
13 | textColor: Colors.white,
14 | fontSize: 16.0,
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/dartdoc_options.yaml:
--------------------------------------------------------------------------------
1 | dartdoc:
2 | categories:
3 | "Blocs":
4 | markdown: README.md
5 | name: Blocs
6 | "Configs":
7 | markdown: README.md
8 | name: Configs
9 | "Models":
10 | markdown: README.md
11 | name: Models
12 | "External":
13 | markdown: README.md
14 | name: External
15 | "Widgets":
16 | markdown: README.md
17 | name: Widgets
18 | categoryOrder: [ "Blocs","Widgets","Models","External" ]
19 | favicon: web/favicon.ico
20 | showUndocumentedCategories: true
--------------------------------------------------------------------------------
/lib/external/github_sign_in/lib/src/github_sign_in_result.dart:
--------------------------------------------------------------------------------
1 | class GitHubSignInResult {
2 | final String? token;
3 | final GitHubSignInResultStatus status;
4 | final String errorMessage;
5 |
6 | GitHubSignInResult(
7 | this.status, {
8 | this.token,
9 | this.errorMessage = "",
10 | });
11 | }
12 |
13 | enum GitHubSignInResultStatus {
14 | /// The login was successful.
15 | ok,
16 |
17 | /// The user cancelled the login flow, usually by closing the
18 | /// login dialog.
19 | cancelled,
20 |
21 | /// The login completed with an error and the user couldn't log
22 | /// in for some reason.
23 | failed,
24 | }
25 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.1.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/lib/utils/app_translations.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | class AppTranslations extends Translations {
4 | @override
5 | Map> get keys => {
6 | 'en_US': {
7 | "home": "Home",
8 | "about_us": "About Us",
9 | "teams": "Teams",
10 | },
11 | 'bn_IN': {
12 | "home": "ঘর",
13 | "about_us": "আমাদের সম্পর্কে",
14 | "teams": "দল",
15 | },
16 | 'hn_IN': {
17 | "home": "घर",
18 | "about_us": "हमारे बारे में",
19 | "teams": "दल",
20 | },
21 | 'mt_IN':{
22 | "home":"मुख्यपृष्ठ",
23 | "about_us":"आमच्या बद्दल",
24 | "teams":"संघ"
25 | }
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/lib/blocs/navigation_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:get/get_navigation/src/extension_navigation.dart';
3 | import 'package:get/utils.dart';
4 |
5 | /// {@category Blocs}
6 | class NavigationBloc extends ChangeNotifier {
7 | late GlobalKey _navigatorKey;
8 |
9 | GlobalKey get navigatorKey => _navigatorKey;
10 |
11 | NavigationBloc(GlobalKey navigatorKey) {
12 | _navigatorKey = navigatorKey;
13 | }
14 |
15 | void toRoute(String s,
16 | {bool shouldPopCurrent = false, bool shouldPopAll = false}) {
17 | if (shouldPopAll) {
18 | Get.offAllNamed(s);
19 | } else if (shouldPopCurrent) {
20 | Get.offAndToNamed(s);
21 | } else {
22 | Get.toNamed(s);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/widgets/Milestones/milestones.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:get/get.dart';
4 | import 'package:ocyclient/widgets/ComingSoon/coming_soon.dart';
5 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
6 |
7 | class MilestonesPage extends StatefulWidget {
8 | const MilestonesPage({Key? key}) : super(key: key);
9 |
10 | @override
11 | State createState() => _MilestonesPageState();
12 | }
13 |
14 | class _MilestonesPageState extends State {
15 |
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | SystemChrome.setApplicationSwitcherDescription(
20 | ApplicationSwitcherDescription(
21 | label: 'Milestones 🏆',
22 | primaryColor: Theme.of(context).primaryColor.value,
23 | ),
24 | );
25 |
26 | return const ComingSoon();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Android Studio will place build artifacts here
43 | /android/app/debug
44 | /android/app/profile
45 | /android/app/release
46 |
47 | env
48 | lib/firebase_options.dart
49 | android/app/google-services.json
50 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a code of conduct, please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11 | build.
12 | 2. Update the README.md with details of changes to the interface, this includes new environment
13 | variables, exposed ports, useful file locations and container parameters.
14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this
15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
17 | do not have permission to do that, you may request the second reviewer to merge it for you.
18 |
--------------------------------------------------------------------------------
/lib/widgets/Community/community.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:ocyclient/blocs/community_bloc.dart';
4 | import 'package:ocyclient/widgets/ComingSoon/coming_soon.dart';
5 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
6 | import 'package:provider/provider.dart';
7 |
8 | class CommunityPage extends StatefulWidget {
9 | const CommunityPage({Key? key}) : super(key: key);
10 |
11 | @override
12 | State createState() => _CommunityPageState();
13 | }
14 |
15 | class _CommunityPageState extends State {
16 | @override
17 | Widget build(BuildContext context) {
18 | SystemChrome.setApplicationSwitcherDescription(
19 | ApplicationSwitcherDescription(
20 | label: 'Community 🤝',
21 | primaryColor: Theme.of(context).primaryColor.value,
22 | ),
23 | );
24 |
25 | Size size = MediaQuery.of(context).size;
26 | CommunityBloc cb = Provider.of(context);
27 | return const ComingSoon();
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Open Codeyard",
3 | "short_name": "OCY",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "Official client side application of Open Codeyard",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-384.png",
19 | "sizes": "384x384",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/lib/widgets/Utils/measure_size_render_object.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/rendering.dart';
3 |
4 | typedef OnWidgetSizeChange = void Function(Size size);
5 |
6 | class MeasureSizeRenderObject extends RenderProxyBox {
7 | Size? oldSize;
8 | final OnWidgetSizeChange onChange;
9 |
10 | MeasureSizeRenderObject(this.onChange);
11 |
12 | @override
13 | void performLayout() {
14 | super.performLayout();
15 |
16 | Size? newSize = child?.size;
17 | if (oldSize == newSize) return;
18 |
19 | oldSize = newSize;
20 | WidgetsBinding.instance.addPostFrameCallback((_) {
21 | onChange(newSize!);
22 | });
23 | }
24 | }
25 |
26 | class MeasureSize extends SingleChildRenderObjectWidget {
27 | final OnWidgetSizeChange onChange;
28 |
29 | const MeasureSize({
30 | Key? key,
31 | required this.onChange,
32 | required Widget child,
33 | }) : super(key: key, child: child);
34 |
35 | @override
36 | RenderObject createRenderObject(BuildContext context) {
37 | return MeasureSizeRenderObject(onChange);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Open Codeyard
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/lib/models/user/user_model.dart:
--------------------------------------------------------------------------------
1 | class UserModel {
2 | String uid;
3 | String email;
4 | String name;
5 | String profilePicUrl;
6 | String userGitHubAccessToken;
7 | List loginProvidersConnected = [];
8 | Map skills = {};
9 | String? bio;
10 | String? phoneNumber;
11 | String? dob;
12 | String? gender;
13 | String? employmentStatus;
14 | String? locality;
15 |
16 | UserModel(
17 | this.uid,
18 | this.email,
19 | this.name,
20 | this.profilePicUrl,
21 | this.userGitHubAccessToken,
22 | this.skills,
23 | this.loginProvidersConnected, {
24 | this.bio,
25 | this.phoneNumber,
26 | this.dob,
27 | this.gender,
28 | this.employmentStatus,
29 | this.locality,
30 | });
31 |
32 | @override
33 | String toString() {
34 | return 'UserModel{uid: $uid, email: $email, name: $name, profilePicUrl: $profilePicUrl, userGitHubAccessToken: $userGitHubAccessToken, loginProvidersConnected: $loginProvidersConnected, skills: $skills, bio: $bio, phoneNumber: $phoneNumber, dob: $dob, gender: $gender, employmentStatus: $employmentStatus, locality: $locality}';
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/models/team/team_model.dart:
--------------------------------------------------------------------------------
1 | class Team {
2 | String id;
3 | String name;
4 | List members;
5 |
6 | // from json
7 | Team({
8 | required this.id,
9 | required this.name,
10 | required this.members,
11 | });
12 |
13 | static fromJson(json) {
14 | return Team(
15 | id: json["id"],
16 | name: json["name"],
17 | members: List.from(json["members"]
18 | .map(
19 | (json) => Member.fromJson(json),
20 | )
21 | .toList()),
22 | );
23 | }
24 | }
25 |
26 | class Member {
27 | String name;
28 | String title;
29 | String image;
30 | String? github;
31 | String? linkedIn;
32 | String? twitter;
33 |
34 | Member({
35 | required this.name,
36 | required this.title,
37 | required this.image,
38 | this.github,
39 | this.linkedIn,
40 | this.twitter,
41 | });
42 |
43 | static fromJson(json) {
44 | return Member(
45 | name: json["name"],
46 | image: json["image"],
47 | title: json["title"],
48 | github: json["github"],
49 | linkedIn: json["linkedIn"],
50 | twitter: json["twitter"],
51 | );
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/models/project/project_model.dart:
--------------------------------------------------------------------------------
1 | class ProjectModel {
2 | String name;
3 | String id;
4 | DateTime creationDate;
5 | String description;
6 | List contributors = [];
7 | String repoUrl;
8 | int starCount, watchCount, activeIssuesCount, forkCount;
9 |
10 | setContributors(List urls) {
11 | contributors = urls;
12 | }
13 |
14 | ProjectModel({
15 | required this.name,
16 | required this.id,
17 | required this.creationDate,
18 | required this.description,
19 | required this.repoUrl,
20 | required this.starCount,
21 | required this.watchCount,
22 | required this.activeIssuesCount,
23 | required this.forkCount,
24 | });
25 |
26 | factory ProjectModel.fromJson(Map parsedJson) {
27 | return ProjectModel(
28 | id: parsedJson['id'].toString(),
29 | name: parsedJson['name'].toString(),
30 | creationDate: DateTime.parse(parsedJson['created_at'].toString()),
31 | description: parsedJson['description'].toString(),
32 | repoUrl: parsedJson['html_url'].toString(),
33 | activeIssuesCount: parsedJson['open_issues_count'],
34 | starCount: parsedJson['stargazers_count'],
35 | watchCount: parsedJson['watchers_count'],
36 | forkCount: parsedJson['forks_count'],
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/widgets/ComingSoon/coming_soon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
3 |
4 | class ComingSoon extends StatelessWidget {
5 | const ComingSoon({Key? key}) : super(key: key);
6 |
7 | @override
8 | Widget build(BuildContext context) {
9 | Size size = MediaQuery.of(context).size;
10 |
11 | return OcyScaffold(
12 | body: SizedBox(
13 | width: size.width,
14 | child: Column(
15 | crossAxisAlignment: CrossAxisAlignment.center,
16 | mainAxisAlignment: MainAxisAlignment.center,
17 | mainAxisSize: MainAxisSize.max,
18 | children: [
19 | ClipRRect(
20 | borderRadius: BorderRadius.circular(15.0),
21 | child: FadeInImage.assetNetwork(
22 | placeholder: "assets/images/ocy_logo.png",
23 | fadeInCurve: Curves.easeOutQuint,
24 | image: "https://i.imgur.com/mxc0F3W.gif",
25 | width: 200,
26 | height: 200,
27 | ),
28 | ),
29 | const SizedBox(height: 50,),
30 | const Text(
31 | "Coming Soon!",
32 | style: TextStyle(
33 | fontWeight: FontWeight.w700,
34 | fontFamily: "PublicSans",
35 | fontSize: 35,
36 | ),
37 | ),
38 | ],
39 | ),
40 | ),
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 |
--------------------------------------------------------------------------------
/lib/widgets/Home/home.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:ocyclient/widgets/Home/sub_pages/benefits.dart';
4 | import 'package:ocyclient/widgets/Home/sub_pages/events.dart';
5 | import 'package:ocyclient/widgets/Home/sub_pages/footer.dart';
6 | import 'package:ocyclient/widgets/Home/sub_pages/intro.dart';
7 | import 'package:ocyclient/widgets/Home/sub_pages/projects.dart';
8 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
9 |
10 | class HomePage extends StatefulWidget {
11 | const HomePage({Key? key}) : super(key: key);
12 |
13 | @override
14 | State createState() => _HomePageState();
15 | }
16 |
17 | class _HomePageState extends State {
18 | @override
19 | Widget build(BuildContext context) {
20 | SystemChrome.setApplicationSwitcherDescription(
21 | ApplicationSwitcherDescription(
22 | label: 'Home 🏠',
23 | primaryColor: Theme.of(context).primaryColor.value,
24 | ),
25 | );
26 |
27 | //Add attribution
28 | //Community icon by Icons8
29 |
30 | return OcyScaffold(
31 | body: SingleChildScrollView(
32 | physics: const BouncingScrollPhysics(),
33 | child: Column(
34 | crossAxisAlignment: CrossAxisAlignment.center,
35 | children: const [
36 | Intro(),
37 | // if (kDebugMode) UpcomingEvents(),
38 | Benefits(),
39 | Projects(),
40 | Footer(),
41 | ],
42 | ),
43 | ),
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: f1875d570e39de09040c8f79aa13cc56baab8db1
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
17 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
18 | - platform: android
19 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
20 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
21 | - platform: ios
22 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
23 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
24 | - platform: linux
25 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
26 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
27 | - platform: macos
28 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
29 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
30 | - platform: web
31 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
32 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
33 | - platform: windows
34 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
35 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/lib/widgets/Utils/scroll_animation.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ScrollAnimationWidget extends StatefulWidget {
4 | const ScrollAnimationWidget({
5 | Key? key,
6 | this.duration = const Duration(milliseconds: 1500),
7 | this.deltaY = 20,
8 | this.curve = Curves.fastOutSlowIn,
9 | required this.child,
10 | }) : super(key: key);
11 |
12 | final Duration duration;
13 | final double deltaY;
14 | final Widget child;
15 | final Curve curve;
16 |
17 | @override
18 | ScrollAnimationWidgetState createState() => ScrollAnimationWidgetState();
19 | }
20 |
21 | class ScrollAnimationWidgetState extends State
22 | with SingleTickerProviderStateMixin {
23 | AnimationController? controller;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 | controller = AnimationController(
29 | duration: widget.duration,
30 | vsync: this,
31 | )
32 | ..forward()
33 | ..addListener(() {
34 | if (controller!.isCompleted) {
35 | controller!.repeat();
36 | }
37 | });
38 | }
39 |
40 | @override
41 | void dispose() {
42 | controller!.dispose();
43 |
44 | super.dispose();
45 | }
46 |
47 | /// convert 0-1 to 0-1-0
48 | double scrollAnimation(double value) =>
49 | 2.5 * (0.5 - (0.5 - widget.curve.transform(value)).abs());
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | return AnimatedBuilder(
54 | animation: controller!,
55 | builder: (context, child) => Transform.translate(
56 | offset: Offset(0, widget.deltaY * scrollAnimation(controller!.value)),
57 | child: Transform.scale(
58 | scale: (1-controller!.value),
59 | child: child,
60 | ),
61 | ),
62 | child: widget.child,
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
10 |
18 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
32 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/data/teams.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Organizers",
4 | "id": "0",
5 | "members": [
6 | {
7 | "name": "Shatanik Mahanty",
8 | "title": "Founder",
9 | "image": "https://i.imgur.com/1Yd49vH.jpeg",
10 | "linkedIn": "https://www.linkedin.com/in/shatanikmahanty/",
11 | "github": "https://github.com/shatanikmahanty/",
12 | "twitter": "https://twitter.com/MahantyShatanik"
13 | },
14 | {
15 | "name": "Prosenjit Swarnakar",
16 | "title": "Co-Founder",
17 | "image": "https://i.imgur.com/kE7kqq8.jpeg",
18 | "linkedIn": "https://www.linkedin.com/in/prosenjit-swarnakar-5baa59236/",
19 | "github": "https://github.com/PROSENJIT-RONI/",
20 | "twitter": "https://twitter.com/ProsenjitSwarn5"
21 | },
22 | {
23 | "name": "Sayan Mukherjee",
24 | "title": "Organizer",
25 | "image": "https://i.imgur.com/iJhYOE7_d.webp?maxwidth=760&fidelity=grand",
26 | "linkedIn": "https://www.linkedin.com/in/sayan-mukherjee-8946a3207/",
27 | "github": "https://github.com/sayanm16",
28 | "twitter": "https://twitter.com/SayanMu79522282"
29 | },
30 | {
31 | "name": "Manish Kr. Barnwal",
32 | "title": "Organizer",
33 | "image": "https://i.imgur.com/Zf443Hd.png",
34 | "linkedIn": "https://www.linkedin.com/in/imanishbarnwal/",
35 | "github": "https://github.com/imanishbarnwal",
36 | "twitter": "https://twitter.com/imanishbarnwal"
37 | }
38 | ]
39 | },
40 | {
41 | "name": "Outreach",
42 | "id": "1",
43 | "members": [
44 | ]
45 | },
46 | {
47 | "id": "2",
48 | "name": "Designers",
49 | "members": [
50 | ]
51 | },
52 | {
53 | "id": "3",
54 | "name": "Project Leads",
55 | "members": [
56 | ]
57 | },
58 | {
59 | "id": "4",
60 | "name": "Sponsor Relations",
61 | "members": [
62 | ]
63 | }
64 | ]
65 |
--------------------------------------------------------------------------------
/lib/widgets/Auth/page_view/login_intro_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class LoginIntroPage extends StatelessWidget {
4 | final String title, subtitle;
5 | final String imagePath;
6 |
7 | const LoginIntroPage({
8 | Key? key,
9 | required this.title,
10 | required this.subtitle,
11 | required this.imagePath,
12 | }) : super(key: key);
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return ClipRRect(
17 | borderRadius: BorderRadius.circular(8.0),
18 | child: Container(
19 | padding: const EdgeInsets.all(20),
20 | decoration: BoxDecoration(
21 | image: DecorationImage(
22 | image: AssetImage(
23 | imagePath,
24 | ),
25 | opacity: 0.7,
26 | fit: BoxFit.cover,
27 | ),
28 | color: Colors.black,
29 | ),
30 | child: Column(
31 | mainAxisAlignment: MainAxisAlignment.center,
32 | crossAxisAlignment: CrossAxisAlignment.center,
33 | children: [
34 | Text(
35 | title,
36 | style: TextStyle(
37 | fontSize: MediaQuery.of(context).size.width < 1050 ? 80 : 100,
38 | fontFamily: "PublicSans",
39 | fontWeight: FontWeight.w800,
40 | foreground: Paint()
41 | ..strokeWidth = 3
42 | ..style = PaintingStyle.stroke
43 | ..color = Colors.white,
44 | ),
45 | ),
46 | const SizedBox(
47 | height: 15,
48 | ),
49 | Text(
50 | subtitle,
51 | textAlign: TextAlign.center,
52 | style: const TextStyle(
53 | fontSize: 25,
54 | fontFamily: "PublicSans",
55 | fontWeight: FontWeight.w600,
56 | color: Colors.white,
57 | ),
58 | ),
59 | ],
60 | ),
61 | ),
62 | );
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/widgets/Utils/common_widgets.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ocyclient/widgets/Utils/snackbar.dart';
3 | import 'package:url_launcher/url_launcher_string.dart';
4 |
5 | Widget getIconButton(
6 | {required String title, required Function func, required IconData icon}) {
7 | return GestureDetector(
8 | onTap: () {
9 | func();
10 | },
11 | child: MouseRegion(
12 | cursor: SystemMouseCursors.click,
13 | child: getIconButtonBody(
14 | title,
15 | icon,
16 | ),
17 | ),
18 | );
19 | }
20 |
21 | Widget getIconButtonBody(String title, IconData icon) {
22 | return Row(
23 | children: [
24 | Card(
25 | shape: RoundedRectangleBorder(
26 | borderRadius: BorderRadius.circular(10),
27 | ),
28 | child: SizedBox(
29 | width: 30,
30 | height: 30,
31 | child: getIconForButton(icon),
32 | ),
33 | ),
34 | const SizedBox(
35 | width: 10,
36 | ),
37 | getTextForButton(title)
38 | ],
39 | );
40 | }
41 |
42 | Widget getTextForButton(String label, {Color? color}) {
43 | return Text(
44 | label,
45 | style: TextStyle(
46 | color: color ?? Colors.white,
47 | fontWeight: FontWeight.bold,
48 | fontSize: 19,
49 | fontFamily: "PublicSans",
50 | ),
51 | );
52 | }
53 |
54 | Widget getIconForButton(IconData icon) {
55 | return Icon(
56 | icon,
57 | color: const Color(0xff0f254e),
58 | size: 15,
59 | );
60 | }
61 |
62 |
63 | Widget getFooterSocialButton(IconData icon, {String? link}) {
64 | return GestureDetector(
65 | onTap: () {
66 | if (link == null) {
67 | showToast("Coming soon");
68 | } else {
69 | launchUrlString(link);
70 | }
71 | },
72 | child: Card(
73 | shape: RoundedRectangleBorder(
74 | borderRadius: BorderRadius.circular(10),
75 | ),
76 | child: SizedBox(
77 | width: 30,
78 | height: 30,
79 | child: MouseRegion(
80 | cursor: SystemMouseCursors.click,
81 | child: getIconForButton(icon),
82 | ),
83 | ),
84 | ),
85 | );
86 | }
87 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion flutter.compileSdkVersion
30 |
31 | compileOptions {
32 | sourceCompatibility JavaVersion.VERSION_1_8
33 | targetCompatibility JavaVersion.VERSION_1_8
34 | }
35 |
36 | kotlinOptions {
37 | jvmTarget = '1.8'
38 | }
39 |
40 | sourceSets {
41 | main.java.srcDirs += 'src/main/kotlin'
42 | }
43 |
44 | defaultConfig {
45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
46 | // applicationId "com.ocy.ocyclient"
47 | applicationId "com.ocy.first-ocy-setup"
48 | minSdkVersion flutter.minSdkVersion
49 | targetSdkVersion flutter.targetSdkVersion
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | }
53 |
54 | buildTypes {
55 | release {
56 | // TODO: Add your own signing config for the release build.
57 | // Signing with the debug keys for now, so `flutter run --release` works.
58 | signingConfig signingConfigs.debug
59 | }
60 | }
61 | }
62 |
63 | flutter {
64 | source '../..'
65 | }
66 |
67 | dependencies {
68 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
69 | }
70 |
--------------------------------------------------------------------------------
/lib/blocs/teams_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'dart:convert';
3 | import 'package:http/http.dart';
4 | import 'package:ocyclient/models/team/team_model.dart';
5 |
6 | /// {@category Blocs}
7 | class TeamsBloc extends ChangeNotifier {
8 |
9 | ///API URL for teams
10 | final Uri teamsUrl = Uri.parse(
11 | "https://raw.githubusercontent.com/OpenCodeyard/ocyclient/dev/data/teams.json?t=current%20timestamp",
12 | );
13 |
14 | ///List of teams
15 | List _teams = [];
16 |
17 | List get teams => _teams;
18 |
19 | ///Handles team loading state
20 | bool _isLoading = false;
21 |
22 | bool get isLoading => _isLoading;
23 |
24 | ///Handles error state
25 | bool _hasError = false;
26 |
27 | bool get hasError => _hasError;
28 |
29 | ///Stores error message in case of an error
30 | String _errorMessage = "";
31 |
32 | String get errorMessage => _errorMessage;
33 |
34 | ///Running fetch logic at app start from constructor
35 | TeamsBloc() {
36 | _fetchTeams();
37 | }
38 |
39 | ///Gets list of team for org from Github API
40 | Future _fetchTeams() async {
41 | _isLoading = true;
42 | notifyListeners();
43 | try {
44 |
45 | ///Gets list of teams from API
46 | final response = await get(teamsUrl);
47 | if (response.statusCode == 200) {
48 | final data = json.decode(response.body);
49 |
50 | ///Converts json team data to list of dart objects
51 | _teams = List.from(data.map((json) {
52 | return Team.fromJson(json);
53 | }).toList());
54 | _isLoading = false;
55 | notifyListeners();
56 | } else {
57 | _hasError = true;
58 | _errorMessage = "Something went wrong";
59 | notifyListeners();
60 | }
61 | } catch (e) {
62 |
63 | ///Handle errors here
64 |
65 | _hasError = true;
66 | if (kDebugMode) {
67 | print(e.toString());
68 | }
69 | _errorMessage = "Something went wrong";
70 | notifyListeners();
71 | }
72 | }
73 |
74 | ///Gets single team object using ID
75 | ///Returns null if not found
76 | Team? getTeam(String id) {
77 | for (Team tm in teams) {
78 | if (tm.id == id) {
79 | return tm;
80 | }
81 | }
82 | return null;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/external/github_sign_in/lib/src/github_sign_in_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:webview_flutter/webview_flutter.dart';
3 |
4 | class GitHubSignInPage extends StatefulWidget {
5 | final String url;
6 | final String redirectUrl;
7 | final bool clearCache;
8 | final String title;
9 | final bool? centerTitle;
10 | final String? userAgent;
11 |
12 | const GitHubSignInPage(
13 | {Key? key,
14 | required this.url,
15 | required this.redirectUrl,
16 | this.userAgent,
17 | this.clearCache = true,
18 | this.title = "",
19 | this.centerTitle})
20 | : super(key: key);
21 |
22 | @override
23 | State createState() => _GitHubSignInPageState();
24 | }
25 |
26 | class _GitHubSignInPageState extends State {
27 | static const String _userAgentMacOSX =
28 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36";
29 |
30 | @override
31 | void initState() {
32 | super.initState();
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | return Scaffold(
38 | appBar: AppBar(
39 | title: Text(widget.title),
40 | centerTitle: widget.centerTitle,
41 | ),
42 | body: WebView(
43 | initialUrl: widget.url,
44 | userAgent: widget.userAgent ?? _userAgentMacOSX,
45 | javascriptMode: JavascriptMode.unrestricted,
46 | onWebViewCreated: (WebViewController controller) {
47 | if (widget.clearCache) {
48 | controller.clearCache();
49 | CookieManager manager = CookieManager();
50 | manager.clearCookies();
51 | }
52 | },
53 | onPageFinished: (url) {
54 | if (url.contains("error=")) {
55 | Navigator.of(context).pop(
56 | Exception(Uri.parse(url).queryParameters["error"]),
57 | );
58 | } else if (url.startsWith(widget.redirectUrl)) {
59 | Navigator.of(context).pop(
60 | url.replaceFirst("${widget.redirectUrl}?code=", "").trim());
61 | }
62 | },
63 | ));
64 | }
65 |
66 | @override
67 | void dispose() {
68 | super.dispose();
69 | // _wv.dispose();
70 | // _wv.close();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/blocs/projects_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter_dotenv/flutter_dotenv.dart';
4 | import 'package:ocyclient/configs/config.dart';
5 | import 'package:ocyclient/models/project/project_model.dart';
6 |
7 | /// {@category Blocs}
8 | class ProjectsBloc extends ChangeNotifier {
9 | Dio dio = Dio();
10 |
11 | List _projects = [];
12 |
13 | List get projects => _projects;
14 |
15 | bool _isProjectsLoading = true;
16 |
17 | bool get isProjectsLoading => _isProjectsLoading;
18 |
19 | ///Gets list of projects for org from Github API
20 | void getProjects() async {
21 | String? token = dotenv.env[Config.envGhAccessToken];
22 |
23 | dio.options.headers["Authorization"] = "token $token";
24 | dio.options.headers["accept"] = "application/vnd.github.v3+json";
25 |
26 | dio
27 | .get(
28 | "${Config.ghRootUrl}${Config.ghOrganisationsApi}/${Config.ghOrganisationName}/${Config.ghReposApi}",
29 | )
30 | .then((value) async {
31 | List projectsResponse = value.data;
32 |
33 | ///Running expensive function in a separate isolate
34 | _projects = await compute(parseResponseIntoList, projectsResponse);
35 |
36 | int i = 0;
37 | for (var project in projectsResponse) {
38 | ///Gets list of contributors for all projects
39 | var responseContributors = await dio.get(project["contributors_url"]);
40 | List contributors = await compute(
41 | getImageUrls,
42 | responseContributors.data as List,
43 | );
44 | _projects[i].contributors = contributors;
45 | i++;
46 | }
47 |
48 | ///Sorts projects based on star count
49 | _projects.sort((a,b) => b.starCount.compareTo(a.starCount));
50 |
51 | _isProjectsLoading = false;
52 | notifyListeners();
53 | });
54 | }
55 | }
56 |
57 | ///Top level functions because it will be used in an isolate
58 | ///Warning : Putting it inside the class will cause error
59 |
60 | List parseResponseIntoList(List projects) {
61 | return projects.map((data) => ProjectModel.fromJson(data)).toList();
62 | }
63 |
64 | List getImageUrls(List users) {
65 | List toBeReturned = [];
66 | for (var user in users) {
67 | toBeReturned.add("${user["avatar_url"]}^${user["html_url"]}");
68 | }
69 |
70 | return toBeReturned;
71 | }
72 |
--------------------------------------------------------------------------------
/web/github_login.js:
--------------------------------------------------------------------------------
1 | async function initLogin(isLinkOperation){
2 | var provider = new firebase.auth.GithubAuthProvider();
3 |
4 | provider.addScope('repo');
5 | provider.addScope('user');
6 | provider.addScope('gist');
7 | provider.addScope('user:email');
8 | provider.setCustomParameters({
9 | 'allow_signup': 'true'
10 | });
11 |
12 | var result;
13 |
14 | if(!isLinkOperation.value){
15 | result = await firebase
16 | .auth()
17 | .signInWithPopup(provider)
18 | .then((result) => {
19 | /** @type {firebase.auth.OAuthCredential} */
20 | var credential = result.credential;
21 |
22 | // This gives you a GitHub Access Token. You can use it to access the GitHub API.
23 | var token = credential.accessToken;
24 |
25 | // The signed-in user info.
26 | var user = result.user;
27 |
28 | return token;
29 |
30 | }).catch((error) => {
31 | // Handle Errors here.
32 | var errorCode = error.code;
33 | var errorMessage = error.message;
34 | // The email of the user's account used.
35 | var email = error.email;
36 | // The firebase.auth.AuthCredential type that was used.
37 | var credential = error.credential;
38 |
39 | return "error:" + errorMessage;
40 | });
41 |
42 | return result;
43 | } else{
44 | result = await firebase
45 | .auth()
46 | .currentUser
47 | .linkWithPopup(provider)
48 | .then((result) => {
49 | /** @type {firebase.auth.OAuthCredential} */
50 | var credential = result.credential;
51 |
52 | // This gives you a GitHub Access Token. You can use it to access the GitHub API.
53 | var token = credential.accessToken;
54 |
55 | // The signed-in user info.
56 | var user = result.user;
57 |
58 | return token;
59 |
60 | }).catch((error) => {
61 | // Handle Errors here.
62 | var errorCode = error.code;
63 | var errorMessage = error.message;
64 | // The email of the user's account used.
65 | var email = error.email;
66 | // The firebase.auth.AuthCredential type that was used.
67 | var credential = error.credential;
68 |
69 | return "error:" + errorMessage;
70 | });
71 |
72 | return result;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/lib/blocs/locale_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:get/get.dart';
3 | import 'package:ocyclient/configs/config.dart';
4 | import 'package:ocyclient/models/localization/language.dart';
5 | import 'package:shared_preferences/shared_preferences.dart';
6 |
7 | class LocaleBLoc extends ChangeNotifier {
8 | static const String english = "en";
9 | static const String bengali = "bn";
10 | static const String hindi = "hn";
11 | static const String marathi ="mt"
12 | Locale _currentLocale = const Locale(english, "US");
13 |
14 | Locale get currentLocale => _currentLocale;
15 |
16 | LocaleBLoc(GlobalKey navigatorKey) {
17 | loadLocale(navigatorKey);
18 | }
19 |
20 | void changeLanguage(Language language, context) async {
21 | SharedPreferences sp = await SharedPreferences.getInstance();
22 |
23 | Locale locale;
24 | switch (language.languageCode) {
25 | case english:
26 | locale = Locale(language.languageCode, "US");
27 | break;
28 | case bengali:
29 | locale = Locale(language.languageCode, "IN");
30 | break;
31 | case hindi:
32 | locale = Locale(language.languageCode, "IN");
33 | break;
34 | case marathi:
35 | locale = Locale(language.languageCode,"IN");
36 | break;
37 | default:
38 | locale = Locale(language.languageCode, 'US');
39 | }
40 | _currentLocale = locale;
41 | notifyListeners();
42 |
43 | Get.updateLocale(currentLocale);
44 |
45 | sp.setString("currentLanguageName", getCurrentSelectedLanguage().name);
46 | sp.setString("currentLanguageCode", _currentLocale.languageCode);
47 | sp.setString(
48 | "currentLanguageCountryCode", _currentLocale.countryCode ?? "NULL");
49 | }
50 |
51 | Language getCurrentSelectedLanguage() {
52 | for (Language l in Config.languageList) {
53 | if ((currentLocale.countryCode ?? "") == l.countryCode) {
54 | if (currentLocale.languageCode == l.languageCode) {
55 | return l;
56 | }
57 | } else if (currentLocale.countryCode == null && l.countryCode == "") {
58 | if (currentLocale.languageCode == l.languageCode) {
59 | return l;
60 | }
61 | }
62 | }
63 |
64 | return Language("English", "US", "en");
65 | }
66 |
67 | void loadLocale(GlobalKey navigatorKey) async {
68 | SharedPreferences sp = await SharedPreferences.getInstance();
69 |
70 | String? countryCode = sp.getString("currentLanguageCountryCode");
71 | String? langCode = sp.getString("currentLanguageCode") ?? "en";
72 |
73 | if (countryCode == "NULL" || countryCode == null) {
74 | countryCode = "US";
75 | }
76 |
77 | _currentLocale = Locale(
78 | langCode,
79 | countryCode,
80 | );
81 |
82 | Get.updateLocale(currentLocale);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/widgets/Teams/member/member_horizontal.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/models/team/team_model.dart';
4 | import 'package:ocyclient/widgets/Utils/common_widgets.dart';
5 | import 'package:url_launcher/url_launcher_string.dart';
6 |
7 | class MemberHorizontal extends StatelessWidget {
8 | final Member member;
9 |
10 | const MemberHorizontal({Key? key, required this.member}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Padding(
15 | padding: const EdgeInsets.symmetric(
16 | horizontal: 45.0,
17 | vertical: 10,
18 | ),
19 | child: Row(
20 | mainAxisAlignment: MainAxisAlignment.start,
21 | crossAxisAlignment: CrossAxisAlignment.start,
22 | children: [
23 | ClipRRect(
24 | borderRadius: BorderRadius.circular(15.0),
25 | child: Image.network(
26 | member.image,
27 | width: 120,
28 | height: 120,
29 | fit: BoxFit.cover,
30 | ),
31 | ),
32 | const SizedBox(
33 | width: 20,
34 | ),
35 | memberDetails(member),
36 | ],
37 | ),
38 | );
39 | }
40 |
41 | Widget memberDetails(Member member) {
42 | return Column(
43 | mainAxisAlignment: MainAxisAlignment.start,
44 | crossAxisAlignment: CrossAxisAlignment.start,
45 | children: [
46 | Text(
47 | member.name,
48 | style: const TextStyle(
49 | fontSize: 20,
50 | color: Colors.white,
51 | fontWeight: FontWeight.bold,
52 | fontFamily: "PublicSans"),
53 | ),
54 | const SizedBox(
55 | height: 15,
56 | ),
57 | Text(
58 | member.title,
59 | style: const TextStyle(
60 | fontSize: 17, color: Colors.white, fontFamily: "PublicSans"),
61 | ),
62 | const SizedBox(
63 | height: 15,
64 | ),
65 | SizedBox(
66 | height: 50,
67 | child: ListView(
68 | scrollDirection: Axis.horizontal,
69 | shrinkWrap: true,
70 | physics: const BouncingScrollPhysics(),
71 | children: [
72 | if ((member.linkedIn ?? "").isNotEmpty)
73 | getIconButton(
74 | title: "",
75 | func: () {
76 | launchUrlString(member.linkedIn ?? "");
77 | },
78 | icon: FontAwesomeIcons.linkedinIn,
79 | ),
80 | if ((member.github ?? "").isNotEmpty)
81 | getIconButton(
82 | title: "",
83 | func: () {
84 | launchUrlString(member.github ?? "");
85 | },
86 | icon: FontAwesomeIcons.github,
87 | ),
88 | if ((member.twitter ?? "").isNotEmpty)
89 | getIconButton(
90 | title: "",
91 | func: () {
92 | launchUrlString(member.twitter ?? "");
93 | },
94 | icon: FontAwesomeIcons.twitter,
95 | ),
96 | ],
97 | ),
98 | ),
99 | ],
100 | );
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/lib/widgets/Home/sub_pages/events.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:line_icons/line_icons.dart';
3 |
4 | class UpcomingEvents extends StatelessWidget {
5 | const UpcomingEvents({Key? key}) : super(key: key);
6 |
7 | @override
8 | Widget build(BuildContext context) {
9 | Size size = MediaQuery.of(context).size;
10 |
11 | return Container(
12 | padding: EdgeInsets.all(size.width < 900 ? 30 : 15),
13 | color: Colors.white,
14 | width: size.width,
15 | // height: 400,
16 | child: Column(
17 | crossAxisAlignment: CrossAxisAlignment.start,
18 | children: [
19 | SizedBox(
20 | height: size.height * 0.1,
21 | ),
22 | size.width < 900
23 | ? Column(
24 | crossAxisAlignment: CrossAxisAlignment.start,
25 | children: [
26 | eventZone(size),
27 | const SizedBox(
28 | height: 50,
29 | ),
30 | ],
31 | )
32 | : Row(
33 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
34 | crossAxisAlignment: CrossAxisAlignment.start,
35 | children: [
36 | Column(
37 | children: "EVENTS"
38 | .split("")
39 | .map((string) => Text(
40 | string,
41 | style: TextStyle(
42 | fontFamily: "PublicSans",
43 | fontWeight: FontWeight.bold,
44 | fontSize: size.width > 1100 ? 70 : 60,
45 | letterSpacing: 4,
46 | foreground: Paint()
47 | ..strokeWidth = 1
48 | ..style = PaintingStyle.stroke
49 | ..color = const Color(
50 | 0xff071a2b,
51 | ),
52 | ),
53 | ))
54 | .toList(),
55 | ),
56 | eventZone(size),
57 | eventZone(size),
58 | ],
59 | ),
60 | SizedBox(
61 | height: size.height * 0.1,
62 | ),
63 | ],
64 | ),
65 | );
66 | }
67 |
68 | Widget eventZone(Size size) {
69 | return Column(
70 | crossAxisAlignment: CrossAxisAlignment.start,
71 | children: [
72 | const SizedBox(
73 | height: 30,
74 | ),
75 | SizedBox(
76 | width: size.width < 900
77 | ? size.width
78 | : size.width > 1050
79 | ? 380
80 | : size.width * 0.3,
81 | child: Text(
82 | "We conduct as well as participate in frequent events spanning over"
83 | " a wide range of topics from technology, "
84 | "games, awareness campaigns, etc.",
85 | style: TextStyle(
86 | fontSize: size.width < 1000 ? 16 : 18,
87 | fontFamily: "PublicSans",
88 | fontWeight: FontWeight.bold,
89 | ),
90 | ),
91 | ),
92 | const SizedBox(
93 | height: 20,
94 | ),
95 | TextButton.icon(
96 | onPressed: () {},
97 | icon: const Text(
98 | "All events",
99 | style: TextStyle(
100 | color: Colors.blue,
101 | ),
102 | ),
103 | label: const Icon(
104 | LineIcons.arrowRight,
105 | color: Colors.blue,
106 | ),
107 | ),
108 | ],
109 | );
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/lib/widgets/Home/sub_pages/intro.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/configs/config.dart';
4 | import 'package:ocyclient/widgets/Utils/common_widgets.dart';
5 | import 'package:ocyclient/widgets/Utils/snackbar.dart';
6 | import 'package:responsive_grid/responsive_grid.dart';
7 | import 'package:url_launcher/url_launcher_string.dart';
8 |
9 | class Intro extends StatelessWidget {
10 | const Intro({Key? key}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | Size size = MediaQuery.of(context).size;
15 |
16 | return Stack(
17 | children: [
18 | Container(
19 | height: size.width > 700 ? size.height : size.height / 1.8,
20 | decoration: BoxDecoration(
21 | image: DecorationImage(
22 | image: const AssetImage(
23 | "assets/images/welcome.jpg",
24 | ),
25 | fit: size.width < 700 ? BoxFit.fill : BoxFit.cover,
26 | opacity: 0.8,
27 | ),
28 | color: const Color(0xff152839),
29 | ),
30 | width: MediaQuery.of(context).size.width,
31 | // height: MediaQuery.of(context).size.height,
32 | child: Row(
33 | children: [
34 | logoDescription(size),
35 | ],
36 | ),
37 | ),
38 | ],
39 | );
40 | }
41 |
42 | Widget logoDescription(Size size) {
43 | return SizedBox(
44 | width: size.width,
45 | child: Column(
46 | mainAxisAlignment: MainAxisAlignment.center,
47 | children: [
48 | const Spacer(),
49 | const SizedBox(
50 | height: 50,
51 | ),
52 | Row(
53 | mainAxisAlignment: MainAxisAlignment.center,
54 | children: [
55 | Text(
56 | "OPEN CODEYARD",
57 | style: TextStyle(
58 | fontSize: size.width < 500
59 | ? 40
60 | : size.width < 1200
61 | ? 50
62 | : 100,
63 | fontWeight: FontWeight.bold,
64 | fontFamily: "PublicSans",
65 | color: Colors.white),
66 | )
67 | ],
68 | ),
69 | const Spacer(),
70 | ResponsiveGridList(
71 | desiredItemWidth: size.width < 700 ? 50 : 140,
72 | scroll: false,
73 | rowMainAxisAlignment: MainAxisAlignment.center,
74 | minSpacing: 20,
75 | children: [
76 | getIconButton(
77 | title: size.width < 700 ? "" : "LinkedIn",
78 | func: () {
79 | launchUrlString(Config.linkedInUrl);
80 | },
81 | icon: FontAwesomeIcons.linkedinIn,
82 | ),
83 | getIconButton(
84 | title: size.width < 700 ? "" : "Telegram",
85 | func: () {
86 | launchUrlString(Config.telegramUrl);
87 | },
88 | icon: FontAwesomeIcons.telegram,
89 | ),
90 | getIconButton(
91 | title: size.width < 700 ? "" : "GitHub",
92 | func: () {
93 | launchUrlString(Config.ghUrl);
94 | },
95 | icon: FontAwesomeIcons.github,
96 | ),
97 | getIconButton(
98 | title: size.width < 700 ? "" : "Discord",
99 | func: () {
100 | showToast("Coming Soon!");
101 | },
102 | icon: FontAwesomeIcons.discord,
103 | ),
104 | ],
105 | ),
106 | const SizedBox(
107 | height: 10,
108 | ),
109 | ],
110 | ),
111 | );
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: ocyclient
2 | description: Official client side application of Open Codeyard
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `flutter pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 0.8.1-alpha+12
19 |
20 | environment:
21 | sdk: ">=2.18.6 <3.0.0"
22 |
23 | # Dependencies specify other packages that your package needs in order to work.
24 | # To automatically upgrade your package dependencies to the latest versions
25 | # consider running `flutter pub upgrade --major-versions`. Alternatively,
26 | # dependencies can be manually updated by changing the version numbers below to
27 | # the latest version available on pub.dev. To see which dependencies have newer
28 | # versions available, run `flutter pub outdated`.
29 | dependencies:
30 | flutter:
31 | sdk: flutter
32 | flutter_localizations:
33 | sdk: flutter
34 | flutter_web_plugins:
35 | sdk: flutter
36 |
37 | #ux
38 | flutter_markdown: ^0.6.10+5
39 | html2md: ^1.2.6
40 | carousel_slider: ^4.1.1
41 | responsive_grid: ^2.1.0
42 |
43 | #Icons
44 | line_icons: ^2.0.1
45 | font_awesome_flutter: ^10.1.0
46 |
47 | #State management
48 | provider: ^6.0.3
49 | get: ^4.6.5
50 |
51 | #Session management
52 | shared_preferences: 2.0.15
53 |
54 | # Extras
55 | url_launcher: ^6.1.6
56 | webview_flutter: ^3.0.4
57 | step_progress_indicator: ^1.0.2
58 | fluttertoast: ^8.0.9
59 | face_pile: ^0.0.2
60 | intl: ^0.17.0
61 |
62 | #Networking
63 | http: ^0.13.5
64 |
65 | #Firebase dependencies
66 | firebase_auth: ^3.11.1
67 | firebase_core: ^1.24.0
68 | cloud_firestore: ^3.5.0
69 |
70 | #Web
71 | universal_html: ^2.0.8
72 | js: ^0.6.3
73 |
74 | #Login Providers
75 | google_sign_in: ^5.4.2
76 |
77 | #Apis
78 | dio: ^4.0.6
79 |
80 | #Api key management
81 | flutter_dotenv: ^5.0.2
82 |
83 | dev_dependencies:
84 | flutter_test:
85 | sdk: flutter
86 |
87 | # The "flutter_lints" package below contains a set of recommended lints to
88 | # encourage good coding practices. The lint set provided by the package is
89 | # activated in the `analysis_options.yaml` file located at the root of your
90 | # package. See that file for information about deactivating specific lint
91 | # rules and activating additional ones.
92 | flutter_lints: ^2.0.1
93 |
94 | # For information on the generic Dart part of this file, see the
95 | # following page: https://dart.dev/tools/pub/pubspec
96 |
97 | # The following section is specific to Flutter.
98 | flutter:
99 |
100 | # The following line ensures that the Material Icons font is
101 | # included with your application, so that you can use the icons in
102 | # the material Icons class.
103 | uses-material-design: true
104 |
105 | # To add assets to your application, add an assets section, like this:
106 | assets:
107 | - assets/images/
108 | - env
109 |
110 | fonts:
111 | - family: PublicSans
112 | fonts:
113 | - asset: assets/fonts/PublicSans_Regular.otf
114 | - asset: assets/fonts/PublicSans_ExtraBold.otf
115 | weight: 700
116 | - asset: assets/fonts/PublicSans_Bold.otf
117 | weight: 500
118 |
--------------------------------------------------------------------------------
/lib/widgets/Teams/member/member_vertical.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/models/team/team_model.dart';
4 | import 'package:ocyclient/widgets/Utils/common_widgets.dart';
5 | import 'package:url_launcher/url_launcher_string.dart';
6 |
7 | class MemberVertical extends StatelessWidget {
8 | final Member member;
9 |
10 | const MemberVertical({Key? key, required this.member}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Padding(
15 | padding: const EdgeInsets.symmetric(
16 | horizontal: 45.0,
17 | vertical: 10,
18 | ),
19 | child: Column(
20 | mainAxisAlignment: MainAxisAlignment.start,
21 | crossAxisAlignment: CrossAxisAlignment.start,
22 | children: [
23 | Row(
24 | crossAxisAlignment: CrossAxisAlignment.start,
25 | children: [
26 | ClipRRect(
27 | borderRadius: BorderRadius.circular(15.0),
28 | child: Image.network(
29 | member.image,
30 | width: 140,
31 | height: 140,
32 | fit: BoxFit.cover,
33 | ),
34 | ),
35 | const SizedBox(
36 | width: 20,
37 | ),
38 | SizedBox(
39 | height: 140,
40 | width: 60,
41 | child: Center(
42 | child: ListView(
43 | scrollDirection: Axis.vertical,
44 | shrinkWrap: true,
45 | physics: const BouncingScrollPhysics(),
46 | children: [
47 | if ((member.linkedIn ?? "").isNotEmpty)
48 | getIconButton(
49 | title: "",
50 | func: () {
51 | launchUrlString(member.linkedIn ?? "");
52 | },
53 | icon: FontAwesomeIcons.linkedinIn,
54 | ),
55 | const SizedBox(
56 | height: 10,
57 | ),
58 | if ((member.github ?? "").isNotEmpty)
59 | getIconButton(
60 | title: "",
61 | func: () {
62 | launchUrlString(member.github ?? "");
63 | },
64 | icon: FontAwesomeIcons.github,
65 | ),
66 | if ((member.twitter ?? "").isNotEmpty)
67 | getIconButton(
68 | title: "",
69 | func: () {
70 | launchUrlString(member.twitter ?? "");
71 | },
72 | icon: FontAwesomeIcons.twitter,
73 | ),
74 | ],
75 | ),
76 | ),
77 | ),
78 | ],
79 | ),
80 | const SizedBox(
81 | height: 20,
82 | ),
83 | memberDetails(member),
84 | ],
85 | ),
86 | );
87 | }
88 |
89 | Widget memberDetails(Member member) {
90 | return Column(
91 | mainAxisAlignment: MainAxisAlignment.start,
92 | crossAxisAlignment: CrossAxisAlignment.start,
93 | children: [
94 | Text(
95 | member.name,
96 | style: const TextStyle(
97 | fontSize: 20,
98 | color: Colors.white,
99 | fontWeight: FontWeight.bold,
100 | fontFamily: "PublicSans"),
101 | ),
102 | const SizedBox(
103 | height: 15,
104 | ),
105 | Text(
106 | member.title,
107 | style: const TextStyle(
108 | fontSize: 17, color: Colors.white, fontFamily: "PublicSans"),
109 | ),
110 | const SizedBox(
111 | height: 15,
112 | ),
113 | ],
114 | );
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/lib/widgets/Profile/widgets/accounts.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/blocs/auth_bloc.dart';
4 | import 'package:ocyclient/blocs/navigation_bloc.dart';
5 | import 'package:provider/provider.dart';
6 |
7 | class AccountWidget extends StatelessWidget {
8 | const AccountWidget({Key? key}) : super(key: key);
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | AuthenticationBloc ab = Provider.of(context);
13 |
14 | NavigationBloc nb = Provider.of(context);
15 |
16 | Size size = MediaQuery.of(context).size;
17 |
18 | return Column(
19 | crossAxisAlignment: CrossAxisAlignment.start,
20 | children: [
21 | Container(
22 | margin: const EdgeInsets.all(10),
23 | child: Text(
24 | "Accounts",
25 | style: TextStyle(
26 | fontWeight: FontWeight.bold,
27 | fontSize: size.width < 700 ? 25 : 40,
28 | fontFamily: "PublicSans",
29 | ),
30 | ),
31 | ),
32 | Container(
33 | margin: const EdgeInsets.all(10),
34 | child: SingleChildScrollView(
35 | scrollDirection: Axis.horizontal,
36 | child: Row(
37 | children: [
38 | getAccountCard(
39 | ab, nb, "assets/images/google_logo.png", "Google", context),
40 | const SizedBox(
41 | width: 15,
42 | ),
43 | getAccountCard(
44 | ab, nb, "assets/images/github_logo.png", "Github", context)
45 | ],
46 | ),
47 | ),
48 | ),
49 | ],
50 | );
51 | }
52 |
53 | Widget getAccountCard(
54 | AuthenticationBloc ab,
55 | NavigationBloc nb,
56 | String imagePath,
57 | String name,
58 | BuildContext context,
59 | ) {
60 | return Card(
61 | elevation: 3,
62 | shape: RoundedRectangleBorder(
63 | borderRadius: BorderRadius.circular(20),
64 | ),
65 | child: Container(
66 | padding: const EdgeInsets.all(20),
67 | width: 140,
68 | child: Column(
69 | crossAxisAlignment: CrossAxisAlignment.center,
70 | children: [
71 | Image.asset(
72 | imagePath,
73 | height: 30,
74 | width: 30,
75 | ),
76 | const SizedBox(
77 | height: 20,
78 | ),
79 | MouseRegion(
80 | cursor: !ab.userModel.loginProvidersConnected.contains(name)
81 | ? SystemMouseCursors.click
82 | : SystemMouseCursors.basic,
83 | child: GestureDetector(
84 | onTap: () {
85 | if (!ab.userModel.loginProvidersConnected.contains(name)) {
86 | if (name == "Google") {
87 | ab.authWithGoogle(nb, true);
88 | } else {
89 | ab.authWithGithub(context, nb, true);
90 | }
91 | }
92 | },
93 | child: Row(
94 | mainAxisSize: MainAxisSize.min,
95 | children: [
96 | ab.userModel.loginProvidersConnected.contains(name)
97 | ? const Icon(
98 | FontAwesomeIcons.circleCheck,
99 | color: Colors.green,
100 | size: 15,
101 | )
102 | : const Icon(
103 | FontAwesomeIcons.link,
104 | color: Colors.indigoAccent,
105 | size: 15,
106 | ),
107 | const SizedBox(
108 | width: 5,
109 | ),
110 | Text(
111 | name,
112 | style: const TextStyle(
113 | fontFamily: "PublicSans",
114 | fontWeight: FontWeight.bold,
115 | ),
116 | ),
117 | ],
118 | ),
119 | ),
120 | ),
121 | ],
122 | ),
123 | ),
124 | );
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/lib/widgets/Teams/team_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/models/team/team_model.dart';
4 | import 'package:ocyclient/widgets/Teams/member/member_vertical.dart';
5 | import 'package:ocyclient/widgets/Teams/member/member_horizontal.dart';
6 | import 'package:responsive_grid/responsive_grid.dart';
7 |
8 | class TeamCard extends StatefulWidget {
9 | final Size size;
10 | final String title;
11 | final List members;
12 |
13 | const TeamCard(
14 | {Key? key,
15 | required this.size,
16 | required this.title,
17 | required this.members})
18 | : super(key: key);
19 |
20 | @override
21 | State createState() => _TeamCardState();
22 | }
23 |
24 | class _TeamCardState extends State {
25 | bool isExpanded = true;
26 |
27 | @override
28 | void initState() {
29 | if (widget.members.isEmpty) {
30 | setState(() {
31 | isExpanded = false;
32 | });
33 | }
34 | super.initState();
35 | }
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | return Padding(
40 | padding: const EdgeInsets.symmetric(vertical: 25.0),
41 | child: Card(
42 | elevation: 8,
43 | shape: RoundedRectangleBorder(
44 | borderRadius: BorderRadius.circular(15),
45 | ),
46 | color: const Color(0xff152839),
47 | child: ExpansionTile(
48 | initiallyExpanded: widget.members.isNotEmpty,
49 | onExpansionChanged: (bool value) {
50 | setState(() {
51 | isExpanded = value;
52 | });
53 | },
54 | trailing: const SizedBox(),
55 | title: Padding(
56 | padding: const EdgeInsets.symmetric(
57 | horizontal: 8.0,
58 | vertical: 20,
59 | ),
60 | child: Row(
61 | children: [
62 | const SizedBox(
63 | width: 22,
64 | ),
65 | Text(
66 | widget.title,
67 | style: TextStyle(
68 | fontFamily: "PublicSans",
69 | fontWeight: FontWeight.bold,
70 | color: Colors.white,
71 | fontSize: widget.size.width > 1100
72 | ? 40
73 | : widget.size.width > 800
74 | ? 30
75 | : 25,
76 | ),
77 | ),
78 | const Spacer(),
79 | Icon(
80 | isExpanded
81 | ? FontAwesomeIcons.circleMinus
82 | : FontAwesomeIcons.circlePlus,
83 | color: Colors.white,
84 | size: widget.size.width > 800 ? 40 : 25,
85 | ),
86 | if (widget.size.width > 800)
87 | const SizedBox(
88 | width: 22,
89 | ),
90 | ],
91 | ),
92 | ),
93 | children: [
94 | if (widget.members.isNotEmpty) ...[
95 | ResponsiveGridList(
96 | desiredItemWidth:
97 | widget.size.width < 480 ? widget.size.width - 50 : 430,
98 | scroll: false,
99 | rowMainAxisAlignment: MainAxisAlignment.start,
100 | children: List.generate(
101 | widget.members.length,
102 | (index) {
103 | Member member = widget.members[index];
104 | return widget.size.width > 500
105 | ? MemberHorizontal(member: member)
106 | : MemberVertical(member: member);
107 | },
108 | ),
109 | ),
110 | const SizedBox(
111 | height: 30,
112 | ),
113 | ] else ...[
114 | const Text(
115 | "No members found",
116 | style: TextStyle(
117 | fontSize: 17,
118 | color: Colors.white,
119 | fontWeight: FontWeight.bold,
120 | fontFamily: "PublicSans"),
121 | ),
122 | const SizedBox(
123 | height: 30,
124 | ),
125 | ]
126 | ],
127 | ),
128 | ),
129 | );
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/lib/external/github_sign_in/lib/src/github_sign_in.dart:
--------------------------------------------------------------------------------
1 | @JS()
2 | library github_login;
3 |
4 | import 'dart:convert';
5 |
6 | import 'package:flutter/material.dart';
7 | import 'package:http/http.dart' as http;
8 | import 'package:js/js.dart';
9 | import 'package:js/js_util.dart';
10 |
11 | import 'package:flutter/foundation.dart';
12 |
13 | import 'github_sign_in_page.dart';
14 | import 'github_sign_in_result.dart';
15 |
16 | @JS()
17 | external dynamic initLogin(ObjectYouWantToSend theObject);
18 |
19 | @JS()
20 | @anonymous
21 | class ObjectYouWantToSend {
22 | external factory ObjectYouWantToSend({
23 | bool value,
24 | });
25 |
26 | external bool get value;
27 | }
28 |
29 | class GitHubSignIn {
30 | final String clientId;
31 | final String clientSecret;
32 | final String redirectUrl;
33 | final String scope;
34 | final String title;
35 | final bool? centerTitle;
36 | final bool allowSignUp;
37 | final bool clearCache;
38 | final String? userAgent;
39 |
40 | final String _githubAuthorizedUrl =
41 | "https://github.com/login/oauth/authorize";
42 | final String _githubAccessTokenUrl =
43 | "https://github.com/login/oauth/access_token";
44 |
45 | GitHubSignIn({
46 | required this.clientId,
47 | required this.clientSecret,
48 | required this.redirectUrl,
49 | this.scope = "user,gist,user:email",
50 | this.title = "",
51 | this.centerTitle,
52 | this.allowSignUp = true,
53 | this.clearCache = true,
54 | this.userAgent,
55 | });
56 |
57 | Future signIn(
58 | BuildContext context, bool isLinkOperation) async {
59 |
60 | // let's authorize
61 | var authorizedResult;
62 | var cred;
63 | if (kIsWeb) {
64 | cred = await promiseToFuture(initLogin(ObjectYouWantToSend(
65 | value: isLinkOperation,
66 | )));
67 | //push data into authorized result somehow
68 |
69 | } else {
70 | authorizedResult = await Navigator.of(context).push(
71 | MaterialPageRoute(
72 | builder: (context) => GitHubSignInPage(
73 | url: _generateAuthorizedUrl(),
74 | redirectUrl: redirectUrl,
75 | userAgent: userAgent,
76 | clearCache: clearCache,
77 | title: title,
78 | centerTitle: centerTitle,
79 | ),
80 | ),
81 | );
82 | }
83 |
84 | GitHubSignInResult result;
85 | if (!kIsWeb) {
86 | if (authorizedResult == null ||
87 | authorizedResult.toString().contains('access_denied')) {
88 | return GitHubSignInResult(
89 | GitHubSignInResultStatus.cancelled,
90 | errorMessage: "Sign In attempt has been cancelled.",
91 | );
92 | } else if (authorizedResult is Exception) {
93 | return GitHubSignInResult(
94 | GitHubSignInResultStatus.failed,
95 | errorMessage: authorizedResult.toString(),
96 | );
97 | }
98 |
99 | // exchange for access token
100 | String code = authorizedResult;
101 | var response = await http.post(
102 | Uri.parse(_githubAccessTokenUrl),
103 | headers: {"Accept": "application/json"},
104 | body: {
105 | "client_id": clientId,
106 | "client_secret": clientSecret,
107 | "code": code
108 | },
109 | );
110 |
111 | if (response.statusCode == 200) {
112 | var body = json.decode(utf8.decode(response.bodyBytes));
113 | result = GitHubSignInResult(
114 | GitHubSignInResultStatus.ok,
115 | token: body["access_token"],
116 | );
117 | } else {
118 | result = GitHubSignInResult(
119 | GitHubSignInResultStatus.cancelled,
120 | errorMessage:
121 | "Unable to obtain token. Received: ${response.statusCode}",
122 | );
123 | }
124 | } else {
125 | if (cred.toString().startsWith("error")) {
126 | result = GitHubSignInResult(
127 | GitHubSignInResultStatus.failed,
128 | errorMessage: cred.toString().split("error:")[1],
129 | );
130 | } else {
131 | result = GitHubSignInResult(
132 | GitHubSignInResultStatus.ok,
133 | token: cred.toString(),
134 | );
135 | }
136 | }
137 | return result;
138 | }
139 |
140 | String _generateAuthorizedUrl() {
141 | return "$_githubAuthorizedUrl?"
142 | "client_id=$clientId"
143 | "&redirect_uri=$redirectUrl"
144 | "&scope=$scope"
145 | "&allow_signup=$allowSignUp";
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/.firebase/hosting.YnVpbGRcd2Vi.cache:
--------------------------------------------------------------------------------
1 | favicon-16x16.png,1664637518602,92bc66de59f3616e0a8a8e197f479e47b38638b842cc0d87be6d9920efb198f8
2 | favicon-32x32.png,1664637518602,c2c805f5da7423cbca7a0cd94838f9e7dc33a7f3062eeebf6e1cf13164de6184
3 | favicon.ico,1664637518602,b8038bf2985bf999e62a693aab78f64ec2862b647497320d6d156bdf217b1209
4 | flutter.js,1672719538763,3b3a07d4c55d59c5461929dc37484dec4d38c90aca67f7c044eb85d9524889e6
5 | github_login.js,1664637518602,0650816d750e85c4f1324d98e6352d7872bfe1088286351942397cbd03a298c9
6 | manifest.json,1664637518623,3bbf45483e1a07534e51b47b66c259c203ca5d90d869babb904dad2ed2f8ad85
7 | assets/env,1662443822263,2af834b1162cfbc8b1c4630f645813d3be178d3034258f81901e30c166c04b01
8 | assets/assets/fonts/PublicSans_Bold.otf,1664637518484,18a3a82b3fd44249db46c9c69fd2e78db9731602954e54d45662c771f07832ec
9 | assets/assets/fonts/PublicSans_ExtraBold.otf,1664637518495,a3dfbe9afdf5b1fd7c2c32d4b8d80294912063b375525da37ce1e14d3113b153
10 | assets/assets/fonts/PublicSans_Regular.otf,1664637518495,02b82ce178e9b00896c6f626ef72541ea084878e086fc0fea1b5f8acef55ddd4
11 | assets/assets/images/add_skills.png,1664637518495,17bbcae95471496076577817d621245d5ab69e65018d862a5a6cdb2460b74d75
12 | assets/assets/images/events.jpg,1664637518506,36857078d09a3d650add84ec2a9eb2aa81792d7d38ed6d1a250256dcc115b8a9
13 | assets/assets/images/fork_icon.png,1664637518506,6d61940da8d1435ea29b43591cacefc441eb59f346c2e08990518f4ea3a4416a
14 | assets/assets/images/github_logo.png,1664637518506,ea8edc268426b5d63304a6a02d43c67fb542ce583ae44550086952c517e36a67
15 | assets/assets/images/google_logo.png,1664637518506,e73bcea8239c55ef8fe98b283dfec7c2e88d6a2b8ac455e4bec8d7b985b928b0
16 | assets/assets/images/handshake.png,1664637518506,c2c805f5da7423cbca7a0cd94838f9e7dc33a7f3062eeebf6e1cf13164de6184
17 | assets/assets/images/icon_community.png,1664637518506,c07fbfb180de1bcbf37bc402016ce0d8e7a56eae879733bbac87e4a56ca39e55
18 | assets/assets/images/ocy_logo.png,1664637518506,5380a6fc11aee558934d43d0fd8e52eb2f7284cc611792300213cd34faf67113
19 | assets/assets/images/teams.jpg,1664637518516,01f4e76d7fdd85086f764aa8f35fe8356d3e8251b513259859bb32cadefe49c5
20 | assets/assets/images/welcome.jpg,1664637518516,776e69235064e4e884b50dda0c98fa94dd6c25743cf92b838e9e6a17b59ecf33
21 | assets/fonts/MaterialIcons-Regular.otf,1652601154936,6c5b450bbaa24bf30f1a1c111fe2be1e9c2cb23dde6fa9ee8b3609e812302aed
22 | assets/packages/fluttertoast/assets/toastify.css,1648229989936,6afc6f35b72ca06962c0b9197750a2af6334c905331f080d8047b437ffa170b1
23 | assets/packages/fluttertoast/assets/toastify.js,1648229989951,76b60b9795e3b1093a16956ede93215d4315c157c3fbc99de1483999c081eb89
24 | assets/packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf,1664858649863,7bbb66c28cb081bed5962213758552bf2243705f1d8fa6bb6c80fd43277f39f9
25 | assets/packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf,1664858649832,171dd2d143a4a3b602c3de48f0eb2d2090a870ca1f6368991264317aa6f83870
26 | assets/packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf,1664858649816,2f92675a0fa593f31c5e1e841f341f2a8c35e173dcb834732718ba59bfebcfcd
27 | assets/packages/line_icons/lib/assets/fonts/LineIcons.ttf,1642488512952,afa977305511f17872e9c199cc334e881c22f387b9e0b3cf552347a2a1eabcee
28 | canvaskit/canvaskit.js,1671250576441,1c5e4be41a8a2901d8c9ae4edb5c2bd26c5c4d0564d732a3ce2bef7c6c27bcb0
29 | canvaskit/canvaskit.wasm,1671250576472,5ead4a7a5f1445e19dbf4515ce48c88ad7070b05c4c318e8a73f83917862aa16
30 | canvaskit/profiling/canvaskit.js,1671250576473,15d13a02cb0d513cda2f2a2b63df45ad9ebb843723e1380386b016360ffc9ba0
31 | canvaskit/profiling/canvaskit.wasm,1671250576512,92eb89423488999d48294283d3905d1040b96088d7e3c243bf109dbd1bb29ee0
32 | icons/apple-touch-icon.png,1664637518612,85bdb54cb9e9429b809ffca176de83fd0c8229d6779af9ed8d015f809411c89d
33 | icons/icon-192.png,1664637518612,e581fe7427d8dd4acd45f0717c401c358ef593abd7dc0c24a97601a93a7203b6
34 | icons/icon-384.png,1664637518612,9f64c5bf089ebf7aea6ac359e1db8a6f435b6bdbf107066906984e90caf2a7ee
35 | icons/icon-maskable-192.png,1664637518612,e581fe7427d8dd4acd45f0717c401c358ef593abd7dc0c24a97601a93a7203b6
36 | icons/icon-maskable-512.png,1664637518612,a9b693791ae3bebed1aedb59a6a209cb3508d86702c60c5ccf023db50656917c
37 | icons/mstile-150x150.png,1664637518612,a38c6ed68873099e3e5e6f7e47bdb479e859b9b22c020d7522e8dfb5fd0e00f6
38 | icons/safari-pinned-tab.svg,1664637518612,4cb0bab46f560d040ebf5403a3b37a2f1b8239d338c3a726f82f7967aee325db
39 | assets/AssetManifest.json,1672721835245,f4bf6ae3057f7896d3a8242d0261053a4724e391fec2410c2d5189af42f265e3
40 | flutter_service_worker.js,1672721838859,169444effc55f098785ab1827adbc872708886bc72d32a5075ff724eefdf24cc
41 | index.html,1672721835781,df5055925b9136a559320c9c8cf5c4890e6881cb62105ca2c671721f5a5673df
42 | assets/FontManifest.json,1672721835245,e2645b56b34950c0c501adcbeb9c1bec9bcc5ef3bf4509e6c6025c2b3eb47fc4
43 | version.json,1672721834819,24d176ec89ce89a0d343dda21102bca7428dd459838bd7f8d9690aadbe52d7da
44 | assets/shaders/ink_sparkle.frag,1672721835592,1c6829fee2ec1eeba159adb8964740cecaf55dbe614560a997b0c9e5a5f6844f
45 | assets/NOTICES,1672721835245,2e9f207e09996c37b1fab00293ae4618fc8c00aae9209c0412c62c2d8e8bee78
46 | main.dart.js,1672721831139,1b00410ff95aae0ab27ac6e978ab5b60565ec386e86cefc4a088b2eb7f942a10
47 |
--------------------------------------------------------------------------------
/lib/configs/config.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:line_icons/line_icons.dart';
4 | import 'package:ocyclient/models/localization/language.dart';
5 |
6 | /// {@category Configs}
7 | class Config {
8 | static final Map _routeNames = {
9 | "home": "/home",
10 | // "Community": "/community",
11 | "about_us": "/about_us",
12 | "teams": "/teams",
13 | // "Milestones": "/milestones",
14 | };
15 |
16 | static Map get routeNames => _routeNames;
17 |
18 | static final List _appDrawerIcons = [
19 | LineIcons.home,
20 | LineIcons.globe,
21 | LineIcons.question,
22 | LineIcons.peopleCarry,
23 | Icons.emoji_events_outlined,
24 | Icons.logout_sharp,
25 | ];
26 |
27 | static final List _selectedAppDrawerIcons = [
28 | FontAwesomeIcons.house,
29 | FontAwesomeIcons.earthAmericas,
30 | FontAwesomeIcons.question,
31 | FontAwesomeIcons.peopleCarryBox,
32 | FontAwesomeIcons.trophy,
33 | Icons.logout,
34 | ];
35 |
36 | static List get appDrawerIcons => _appDrawerIcons;
37 |
38 | static List get selectedAppDrawerIcons => _selectedAppDrawerIcons;
39 |
40 | ///GitHub Configs
41 | static const String clientId = "ba4e3c2ad6622ba3b12c";
42 | static const String clientSecret = "079b49d4b5ba6e84ad7ec4f4d4e90163c35c18ad";
43 |
44 | static const String redirectUrl =
45 | "https://opencodeyard.firebaseapp.com/__/auth/handler";
46 |
47 | ///Shared Preferences Keys
48 | static const String prefIsLoggedIn = "is_logged_in";
49 | static const String prefName = "name";
50 | static const String prefEmail = "email";
51 | static const String prefProfilePicUrl = "profile_pic_url";
52 | static const String prefUid = "uid";
53 | static const String prefGithubAccessToken = "user_github_access_token";
54 | static const String prefLoginProvidersConnected = "login_providers";
55 | static const String prefSkills = "skills";
56 | static const String prefPhone = "user_phone";
57 | static const String prefGender = "user_gender";
58 | static const String prefDOB = "user_dob";
59 | static const String prefBio = "user_bio";
60 | static const String prefEmploymentStatus = "employment_status";
61 | static const String prefLocality = "locality";
62 |
63 | ///Routes that should not be accessible to authenticated users
64 | static const List authenticatedPreventAccessRoutes = ["/auth"];
65 |
66 | ///Routes that should not be accessible to unauthenticated users
67 | static const List unauthenticatedPreventAccessRoutes = [
68 | "/profile",
69 | "/editProfile"
70 | ];
71 |
72 | static const appVersion = "0.3.1-alpha";
73 |
74 | ///Firestore Collection Names
75 | static const fsUser = "Users";
76 |
77 | ///Firestore field Names
78 | static const userUID = "uid";
79 | static const userName = "name";
80 | static const userEmail = "email";
81 | static const userProfilePic = "profilePic";
82 | static const userLoginProviders = "loginProviders";
83 | static const userGithubAccessToken = "accessTokenGithub";
84 | static const userSkills = "skills";
85 | static const userBio = "bio";
86 | static const userGender = "gender";
87 | static const userDob = "dob";
88 | static const userEmploymentStatus = "employment";
89 | static const userLocality = "locality";
90 | static const userPhone = "phone";
91 |
92 | ///Github api
93 | static const ghOrganisationName = "OpenCodeyard";
94 | static const ghRootUrl = "https://api.github.com/";
95 | static const ghOrganisationsApi = "orgs";
96 | static const ghReposApi = "repos";
97 | static const ghUserApi = "user";
98 |
99 | static const Color themeColor = Colors.deepPurple;
100 |
101 | static const String communityLogoPath = "assets/images/ocy_logo.png";
102 |
103 | ///Env names
104 | static const String envGhAccessToken = "github_access_token";
105 |
106 | ///Social
107 | static const String linkedInUrl =
108 | "https://www.linkedin.com/company/opencodeyard";
109 | static const String ghUrl = "https://github.com/OpenCodeyard";
110 | static const String telegramUrl = "https://telegram.me/Open_Codeyard";
111 |
112 | static const List weAre = [
113 | "Coders 💻",
114 | "Students 🧑🎓",
115 | "Professionals 💼",
116 | "Dreamers 😴",
117 | "builders ⚒️",
118 | "Innovators 💡",
119 | "Gamers 🎮",
120 | "Hackers 🕶️",
121 | "Brain-Stormers 💡",
122 | "Techies 🧑💻",
123 | "Singers 👨🎤",
124 | "Dancers 🕺",
125 | "Open Codeyard ♥️",
126 | ];
127 |
128 | static const List weAreColors = [
129 | Color(0xfffa5457),
130 | Color(0xff01b4bc),
131 | Color(0xffe3c515),
132 | Color(0xffa59cd3),
133 | Color(0xff4b2d9f),
134 | ];
135 |
136 | static List languageList = [
137 | Language("English", "US", "en"),
138 | Language("বাংলা", "IN", "bn"),
139 | Language("हिंदी", "IN", "hn"),
140 | Language("मराठी","IN","mt")
141 | ];
142 | }
143 |
--------------------------------------------------------------------------------
/web/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.14, written by Peter Selinger 2001-2017
9 |
10 |
12 |
28 |
43 |
54 |
57 |
59 |
61 |
63 |
69 |
75 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | support@opencodeyard.tech.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/lib/widgets/Utils/custom_inputfields.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ocyclient/configs/config.dart';
3 |
4 | buildInputFieldThemColor(
5 | String label,
6 | IconData icon,
7 | TextInputType type,
8 | TextEditingController controller,
9 | BuildContext context,
10 | bool isLast,
11 | FocusNode node,
12 | FocusNode? nextNode,
13 | bool isEnabled,
14 | String? Function(String?)? validator, {
15 | Function(String)? onChanged,
16 | }) {
17 | return Column(
18 | children: [
19 | const SizedBox(
20 | height: 20,
21 | ),
22 | TextFormField(
23 | controller: controller,
24 | textInputAction: isLast ? TextInputAction.done : TextInputAction.next,
25 | focusNode: node,
26 | enabled: isEnabled,
27 | onFieldSubmitted: (s) {
28 | if (nextNode != null) {
29 | nextNode.requestFocus();
30 | } else if (isLast) {
31 | FocusScope.of(context).unfocus();
32 | } else {
33 | FocusScope.of(context).nextFocus();
34 | }
35 | },
36 | onChanged: onChanged,
37 | validator: validator,
38 | autofocus: false,
39 | style: const TextStyle(
40 | color: Colors.black,
41 | ),
42 | keyboardType: type,
43 | cursorColor: Config.themeColor,
44 | decoration: InputDecoration(
45 | labelText: label,
46 | labelStyle: const TextStyle(color: Colors.black),
47 | prefixIcon: Icon(
48 | icon,
49 | size: 18,
50 | color: Colors.black,
51 | ),
52 | filled: true,
53 | border: OutlineInputBorder(
54 | borderRadius: BorderRadius.circular(4),
55 | borderSide: const BorderSide(
56 | width: 1,
57 | color: Colors.grey,
58 | style: BorderStyle.solid,
59 | ),
60 | ),
61 | enabledBorder: OutlineInputBorder(
62 | borderRadius: BorderRadius.circular(4),
63 | borderSide: const BorderSide(
64 | width: 2,
65 | color: Colors.black,
66 | style: BorderStyle.solid,
67 | ),
68 | ),
69 | focusedBorder: OutlineInputBorder(
70 | borderRadius: BorderRadius.circular(4),
71 | borderSide: const BorderSide(
72 | width: 2,
73 | color: Config.themeColor,
74 | style: BorderStyle.solid,
75 | ),
76 | ),
77 | disabledBorder: OutlineInputBorder(
78 | borderRadius: BorderRadius.circular(4),
79 | borderSide: const BorderSide(
80 | width: 2,
81 | color: Colors.blueGrey,
82 | style: BorderStyle.solid,
83 | ),
84 | ),
85 | ),
86 | )
87 | ],
88 | );
89 | }
90 |
91 | buildDescInputFieldThemColor(
92 | String label,
93 | IconData icon,
94 | TextInputType type,
95 | TextEditingController controller,
96 | BuildContext context,
97 | FocusNode node,
98 | FocusNode? nextNode,
99 | bool isEnabled,
100 | bool isLast, {
101 | Function(String)? onChanged,
102 | int maxLength = 300,
103 | }) {
104 | return Column(
105 | children: [
106 | const SizedBox(
107 | height: 20,
108 | ),
109 | TextFormField(
110 | controller: controller,
111 | autocorrect: true,
112 | keyboardType: type,
113 | autofocus: false,
114 | maxLines: null,
115 | style: const TextStyle(
116 | color: Colors.black,
117 | ),
118 | textInputAction: TextInputAction.newline,
119 | onFieldSubmitted: (s) {
120 | if (nextNode != null) {
121 | FocusScope.of(context).requestFocus(nextNode);
122 | } else if (isLast) {
123 | FocusScope.of(context).unfocus();
124 | } else {
125 | FocusScope.of(context).nextFocus();
126 | }
127 | },
128 | onChanged: onChanged,
129 | focusNode: node,
130 | enabled: isEnabled,
131 | cursorColor: Config.themeColor,
132 | maxLength: maxLength,
133 | decoration: InputDecoration(
134 | labelText: label,
135 | labelStyle: const TextStyle(color: Colors.black),
136 | prefixIcon: Icon(
137 | icon,
138 | size: 18,
139 | color: Colors.black,
140 | ),
141 | filled: true,
142 | border: OutlineInputBorder(
143 | borderRadius: BorderRadius.circular(4),
144 | borderSide: const BorderSide(
145 | width: 1,
146 | color: Colors.grey,
147 | style: BorderStyle.solid,
148 | ),
149 | ),
150 | enabledBorder: OutlineInputBorder(
151 | borderRadius: BorderRadius.circular(4),
152 | borderSide: const BorderSide(
153 | width: 2,
154 | color: Colors.black,
155 | style: BorderStyle.solid,
156 | ),
157 | ),
158 | focusedBorder: OutlineInputBorder(
159 | borderRadius: BorderRadius.circular(4),
160 | borderSide: const BorderSide(
161 | width: 2,
162 | color: Config.themeColor,
163 | style: BorderStyle.solid,
164 | ),
165 | ),
166 | disabledBorder: OutlineInputBorder(
167 | borderRadius: BorderRadius.circular(4),
168 | borderSide: const BorderSide(
169 | width: 2,
170 | color: Colors.blueGrey,
171 | style: BorderStyle.solid,
172 | ),
173 | ),
174 | ),
175 | )
176 | ],
177 | );
178 | }
179 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | # OCY Client [](code_of_conduct.md)
10 |
11 | This repo contains source code for the official Flutter Client of Open CodeYard
12 |
13 | A higly configurable community website template built using Flutter
14 |
15 |
16 |
17 | Table of Contents
18 |
19 |
20 |
21 | About The Project
22 |
28 |
29 |
30 | Getting Started
31 |
35 |
36 |
37 | Contact
38 |
39 |
40 |
41 |
42 |
43 |
44 | ## About the project
45 |
46 | :construction:**Actively under development**:construction:
47 |
48 | - ### Built With
49 |
50 | [![Flutter][flutter-image]][flutter-url] [![Firebase][firebase-image]][firebase-url]
51 |
52 | -
53 | Screenshots :iphone:
54 |
55 |
56 | Coming Soon
57 |
58 |
59 |
60 | - #### Documentation :notebook:
61 |
62 | * This project uses [Effective Dart Principles]() for documentation
63 | * Run `dart doc .` from root of project directory to generate documentation webpage.
64 |
65 | - #### Features
66 |
67 | * Self Hosted using Firebase
68 | * FCM for notification (Coming soon)
69 | * Built using [Provider Architecture](https://pub.dev/packages/provider) for clean state management
70 | * Google and GitHub login support for User Authentication
71 | * Custom user management logic using Firestore
72 | * Data caching for optimised network calls
73 | * Profile Screen
74 | * Fluid animations
75 | * Modern, Material UI (we all love this!)
76 | * Heavyily documented code (who doesn't like clean code)
77 |
78 | (back to top )
79 |
80 | ## Getting Started
81 |
82 | - This project depends heavily on firebase. A few resources to get you started if this is your first Firebase project:
83 |
84 | * [Lab: Firebase for Flutter](https://firebase.google.com/codelabs/firebase-get-to-know-flutter#0)
85 | * [FlutterFire Plugins](https://firebase.flutter.dev/)
86 |
87 | - A few resources to get you started if this is your first Flutter project:
88 |
89 | * [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
90 | * [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
91 |
92 | For help getting started with Flutter development, view the
93 | [online documentation](https://docs.flutter.dev/), which offers tutorials,
94 | samples, guidance on mobile development, and a full API reference.
95 |
96 | - #### Project Setup
97 |
98 | * Flutter App:
99 | * [Install Flutter](https://docs.flutter.dev/get-started/install)
100 | * [Setting up your ide](https://flutter.io/ide-setup/)
101 | * Fork and clone this repository.
102 | * cd into `ocyclient` directory.
103 | * Run `flutter clean` command.
104 | * Run `flutter pub get` command.
105 | * Run `flutter run` command.
106 |
107 | * Firebase:
108 | * Create a firebase project
109 | * Add android app with your package name in firebase console.
110 | * Enable Google Auth from `Authentication` menu in Firebase.
111 | * Create a file named env and store github_access_token in it (See [env_example.txt](https://github.com/OpenCodeyard/ocyclient/blob/dev/env_example.txt) file in project root for example). Check [this link](https://docs.github.com/en/enterprise-server@3.4/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) to see how to create a github access token.
112 | * Generate `SHA-1 key hash` for your debug keystore from your pc. This needs to be added to `SHA certificate fingerprints` section under your android app in `Firebase project settings`. Without this step **Google login** won't work.
113 | * Enable ***Cloud Firestore***
114 | * Recommended rules for Firestore
115 |
116 | ```JS
117 | rules_version = '2';
118 | service cloud.firestore {
119 | match /databases/{database}/documents {
120 | match /{document=**} {
121 | allow read, write: if
122 | request.auth != null;
123 | }
124 | }
125 | }
126 | ```
127 | * Enable ***Cloud Storage***
128 | * Download `google_services.json` from `Console` -> `Project Settings`. File is present in app section. SDK instructions found in the same page
129 | * (Optional) Enable ***Cloud Messaging*** from Firebase Console if you wan't notifications to work in your app
130 | * (Optional) If released to play store get `SHA-1 key hash` from playstore and upload them to firebase, otherwise google sign in won't work in play store app.
131 |
132 | * #### Contribution
133 |
134 | ##### Check out our awesome contributors:
135 |
136 |
137 |
138 |
139 | Made with [contributors-img](https://contrib.rocks).
140 |
141 |
142 | Check [Contributing.md](https://github.com/OpenCodeyard/ocyclient/blob/dev/CONTRIBUTING.md) for guidelines on contributing to this repo.
143 |
144 | (back to top )
145 |
146 | ## Contact Us
147 |
148 | If you have a question, please feel free to contact us through [email](mailto:support@opencodeyard.tech) or our [telegram community channel](https://telegram.me/Open_Codeyard).
149 |
150 |
151 |
152 |
153 | Made with ❤️ by Open Codeyard
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | [flutter-image]: https://img.shields.io/badge/Flutter-%2302569B.svg?style=plastic&logo=Flutter&logoColor=5cc8f8
167 | [flutter-url]: https://flutter.dev
168 | [firebase-image]: https://img.shields.io/badge/firebase-%23039BE5.svg?style=plastic&logo=firebase
169 | [firebase-url]: https://firebase.com/
170 |
--------------------------------------------------------------------------------
/lib/widgets/Home/sub_pages/footer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/blocs/navigation_bloc.dart';
4 | import 'package:ocyclient/configs/config.dart';
5 | import 'package:ocyclient/widgets/Utils/common_widgets.dart';
6 | import 'package:provider/provider.dart';
7 | import 'package:url_launcher/url_launcher_string.dart';
8 |
9 | class Footer extends StatelessWidget {
10 | const Footer({Key? key}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | Size size = MediaQuery.of(context).size;
15 |
16 | NavigationBloc nb = Provider.of(context);
17 |
18 | return Container(
19 | color: const Color(0xff152839),
20 | height: size.width <= 700 ? null : 300,
21 | padding: const EdgeInsets.all(10),
22 | child: Column(
23 | crossAxisAlignment: CrossAxisAlignment.start,
24 | children: [
25 | const SizedBox(
26 | height: 40,
27 | ),
28 | size.width > 700
29 | ? Row(
30 | crossAxisAlignment: CrossAxisAlignment.start,
31 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
32 | children: [
33 | about(size),
34 | contactUs(size),
35 | legal(size, nb),
36 | ],
37 | )
38 | : Column(
39 | mainAxisAlignment: MainAxisAlignment.center,
40 | children: [
41 | about(size),
42 | const SizedBox(
43 | height: 50,
44 | ),
45 | Row(
46 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
47 | children: [
48 | contactUs(size),
49 | legal(size, nb),
50 | ],
51 | ),
52 | const SizedBox(
53 | height: 30,
54 | ),
55 | ],
56 | ),
57 | ],
58 | ),
59 | );
60 | }
61 |
62 | Widget contactUs(Size size) {
63 | return Column(
64 | crossAxisAlignment: CrossAxisAlignment.start,
65 | children: [
66 | const Text(
67 | "Contact Us",
68 | style: TextStyle(
69 | color: Colors.white54,
70 | fontFamily: "PublicSans",
71 | ),
72 | ),
73 | const SizedBox(
74 | height: 20,
75 | ),
76 | getIconButton(
77 | title: "Email",
78 | func: () {
79 | launchUrlString("mailto:support@opencodeyard.tech");
80 | },
81 | icon: FontAwesomeIcons.envelope,
82 | ),
83 | const SizedBox(
84 | height: 20,
85 | ),
86 | getIconButton(
87 | title: "FAQ",
88 | func: () {
89 | // nb.toRoute("/licenses");
90 | },
91 | icon: FontAwesomeIcons.question,
92 | ),
93 | const SizedBox(
94 | height: 20,
95 | ),
96 | getIconButton(
97 | title: "Support",
98 | func: () {
99 | // nb.toRoute("/licenses");
100 | },
101 | icon: FontAwesomeIcons.headset,
102 | ),
103 | ],
104 | );
105 | }
106 |
107 | Widget legal(Size size, NavigationBloc nb) {
108 | return Column(
109 | crossAxisAlignment: CrossAxisAlignment.start,
110 | children: [
111 | const Text(
112 | "Legal",
113 | style: TextStyle(
114 | color: Colors.white54,
115 | fontFamily: "PublicSans",
116 | ),
117 | ),
118 | const SizedBox(
119 | height: 20,
120 | ),
121 | getIconButton(
122 | title: "Terms",
123 | func: () {
124 | // nb.toRoute("/licenses");
125 | },
126 | icon: FontAwesomeIcons.scaleBalanced,
127 | ),
128 | const SizedBox(
129 | height: 20,
130 | ),
131 | getIconButton(
132 | title: "Privacy",
133 | func: () {
134 | // nb.toRoute("/licenses");
135 | },
136 | icon: FontAwesomeIcons.userShield,
137 | ),
138 | const SizedBox(
139 | height: 20,
140 | ),
141 | getIconButton(
142 | title: "Licenses",
143 | func: () {
144 | nb.toRoute("/licenses");
145 | },
146 | icon: FontAwesomeIcons.fileInvoice,
147 | ),
148 | ],
149 | );
150 | }
151 |
152 | Widget about(Size size) {
153 | return Column(
154 | children: [
155 | RichText(
156 | text: TextSpan(
157 | text: "{",
158 | style: TextStyle(
159 | fontSize: size.width < 1100 && size.width > 900 ? 14 : 20,
160 | fontWeight: FontWeight.bold,
161 | color: Colors.white,
162 | fontFamily: "PublicSans",
163 | ),
164 | children: [
165 | TextSpan(
166 | text: " Open ",
167 | style: TextStyle(
168 | fontSize: size.width < 1100 && size.width > 900 ? 14 : 20,
169 | fontWeight: FontWeight.normal,
170 | color: Colors.white38,
171 | ),
172 | ),
173 | TextSpan(
174 | text: "Codeyard ",
175 | style: TextStyle(
176 | fontSize: size.width < 1100 && size.width > 900 ? 14 : 20,
177 | fontWeight: FontWeight.bold,
178 | ),
179 | ),
180 | TextSpan(
181 | text: "} ;",
182 | style: TextStyle(
183 | fontSize: size.width < 1100 && size.width > 900 ? 14 : 20,
184 | fontWeight: FontWeight.bold,
185 | ),
186 | ),
187 | ],
188 | ),
189 | ),
190 | const SizedBox(
191 | height: 40,
192 | ),
193 | Row(
194 | mainAxisAlignment: MainAxisAlignment.center,
195 | children: [
196 | getFooterSocialButton(
197 | FontAwesomeIcons.github,
198 | link: Config.ghUrl,
199 | ),
200 | getFooterSocialButton(
201 | FontAwesomeIcons.linkedinIn,
202 | link: Config.linkedInUrl,
203 | ),
204 | getFooterSocialButton(
205 | FontAwesomeIcons.discord,
206 | ),
207 | getFooterSocialButton(
208 | FontAwesomeIcons.telegram,
209 | link: Config.telegramUrl,
210 | ),
211 | ],
212 | ),
213 | const SizedBox(
214 | height: 40,
215 | ),
216 | const Text(
217 | "Engineered with ❤️ by\nOpen Codeyard",
218 | textAlign: TextAlign.center,
219 | style: TextStyle(
220 | height: 1.6,
221 | color: Colors.white,
222 | fontWeight: FontWeight.bold,
223 | fontFamily: "PublicSans",
224 | fontSize: 19,
225 | ),
226 | ),
227 | ],
228 | );
229 | }
230 |
231 | List getFooterWidgets(Size size, NavigationBloc nb) {
232 | return [
233 | about(size),
234 | contactUs(size),
235 | legal(size, nb),
236 | ];
237 | }
238 |
239 | }
240 |
--------------------------------------------------------------------------------
/lib/widgets/Profile/edit_profile.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/blocs/auth_bloc.dart';
4 | import 'package:ocyclient/blocs/edit_profile_bloc.dart';
5 | import 'package:ocyclient/blocs/navigation_bloc.dart';
6 | import 'package:ocyclient/widgets/Profile/sub_pages/edit_personal.dart';
7 | import 'package:ocyclient/widgets/Utils/common_widgets.dart';
8 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
9 | import 'package:provider/provider.dart';
10 |
11 | class EditProfilePage extends StatefulWidget {
12 | const EditProfilePage({Key? key}) : super(key: key);
13 |
14 | @override
15 | EditProfilePageState createState() => EditProfilePageState();
16 | }
17 |
18 | class EditProfilePageState extends State {
19 | ///TODO cover attribution Background vector created by freepik - www.freepik.com
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | Size size = MediaQuery.of(context).size;
24 |
25 | EditProfileBloc epb = Provider.of(context);
26 | AuthenticationBloc ab = Provider.of(context);
27 | NavigationBloc nb = Provider.of(context);
28 |
29 | return OcyScaffold(
30 | body: SizedBox(
31 | height: size.height - 70,
32 | child: size.width < 1000
33 | ? SingleChildScrollView(
34 | physics: const BouncingScrollPhysics(),
35 | child: Column(
36 | children: [
37 | const SizedBox(
38 | height: 20,
39 | ),
40 | Padding(
41 | padding: const EdgeInsets.symmetric(horizontal: 8.0),
42 | child: Card(
43 | elevation: 10,
44 | shape: RoundedRectangleBorder(
45 | borderRadius: BorderRadius.circular(15),
46 | ),
47 | child: SingleChildScrollView(
48 | scrollDirection: Axis.horizontal,
49 | physics: const BouncingScrollPhysics(),
50 | padding: const EdgeInsets.symmetric(
51 | horizontal: 5,
52 | vertical: 10,
53 | ),
54 | child: Row(
55 | mainAxisAlignment: MainAxisAlignment.center,
56 | children: getEditProfileMenu(size, epb, ab, nb),
57 | ),
58 | ),
59 | ),
60 | ),
61 | const PersonalTab(),
62 | ],
63 | ),
64 | )
65 | : Row(
66 | children: [
67 | Card(
68 | elevation: 10,
69 | margin: EdgeInsets.zero,
70 | child: SizedBox(
71 | height: size.height,
72 | width: 230,
73 | child: SingleChildScrollView(
74 | physics: const BouncingScrollPhysics(),
75 | padding: const EdgeInsets.symmetric(
76 | horizontal: 25,
77 | vertical: 10,
78 | ),
79 | child: Column(
80 | children: getEditProfileMenu(size, epb, ab, nb),
81 | ),
82 | ),
83 | ),
84 | ),
85 | const VerticalDivider(
86 | width: 1,
87 | color: Colors.black12,
88 | ),
89 | const PersonalTab(),
90 | const VerticalDivider(
91 | width: 1,
92 | color: Colors.black12,
93 | ),
94 | if (size.width >= 1500)
95 | const SizedBox(),
96 | ],
97 | ),
98 | ),
99 | );
100 | }
101 |
102 | List getEditProfileMenu(
103 | Size size,
104 | EditProfileBloc epb,
105 | AuthenticationBloc ab,
106 | NavigationBloc nb,
107 | ) {
108 | bool isHorizontal = false;
109 | if (size.width < 1000) {
110 | isHorizontal = true;
111 | }
112 | return [
113 | getCustomSizedBoxForMenu(isHorizontal),
114 | if (!isHorizontal) ...[
115 | Image.asset(
116 | "assets/images/ocy_logo.png",
117 | width: 100,
118 | height: 100,
119 | ),
120 | const SizedBox(
121 | height: 30,
122 | ),
123 | ],
124 | getSideMenuButton(
125 | epb,
126 | "Personal",
127 | FontAwesomeIcons.userLarge,
128 | 0,
129 | isHorizontal,
130 | ),
131 | getCustomSizedBoxForMenu(isHorizontal),
132 | getSideMenuButton(
133 | epb,
134 | "Education",
135 | FontAwesomeIcons.userGraduate,
136 | 1,
137 | isHorizontal,
138 | ),
139 | getCustomSizedBoxForMenu(isHorizontal),
140 | getSideMenuButton(
141 | epb,
142 | "Experience",
143 | FontAwesomeIcons.briefcase,
144 | 2,
145 | isHorizontal,
146 | ),
147 | getCustomSizedBoxForMenu(isHorizontal),
148 | ];
149 | }
150 |
151 | Widget getSideMenuButton(
152 | EditProfileBloc pb,
153 | String title,
154 | IconData icon,
155 | int index,
156 | bool isHorizontal, {
157 | AuthenticationBloc? authBloc,
158 | NavigationBloc? navBloc,
159 | }) {
160 | return MouseRegion(
161 | cursor: SystemMouseCursors.click,
162 | child: GestureDetector(
163 | onTap: () {
164 | pb.setCurrentSelectedItem(index);
165 | if (index == 3) {
166 | authBloc?.signOut(context, navBloc!);
167 | }
168 | },
169 | child: AnimatedContainer(
170 | padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
171 | decoration: BoxDecoration(
172 | color: pb.currentSelectedMenuItem == index
173 | ? const Color(0x73c6dbec)
174 | : Colors.white,
175 | borderRadius: BorderRadius.circular(10),
176 | ),
177 | duration: const Duration(milliseconds: 500),
178 | curve: Curves.fastOutSlowIn,
179 | child: SizedBox(
180 | child: Row(
181 | children: [
182 | Text(
183 | title,
184 | style: TextStyle(
185 | color: pb.currentSelectedMenuItem == index
186 | ? Colors.black
187 | : Colors.grey,
188 | fontWeight: pb.currentSelectedMenuItem == index
189 | ? FontWeight.bold
190 | : FontWeight.normal,
191 | fontSize: 14,
192 | fontFamily: "PublicSans"),
193 | ),
194 | if (isHorizontal)
195 | const SizedBox(
196 | width: 20,
197 | )
198 | else
199 | const Spacer(),
200 | getIconForButton(icon),
201 | if (isHorizontal)
202 | const SizedBox(
203 | width: 10,
204 | )
205 | ],
206 | ),
207 | ),
208 | ),
209 | ),
210 | );
211 | }
212 |
213 | Widget getCustomSizedBoxForMenu(bool isHorizontal) {
214 | return isHorizontal
215 | ? const SizedBox(
216 | width: 30,
217 | )
218 | : const SizedBox(
219 | height: 30,
220 | );
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Open Codeyard
48 |
49 |
51 |
52 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
118 |
122 |
123 |
124 |
125 |
130 |
131 |
132 |
133 |
134 |
150 |
151 |
154 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_core/firebase_core.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:flutter_dotenv/flutter_dotenv.dart';
6 | import 'package:flutter_localizations/flutter_localizations.dart';
7 | import 'package:flutter_web_plugins/flutter_web_plugins.dart';
8 | import 'package:get/get_navigation/src/root/get_material_app.dart';
9 | import 'package:get/get_navigation/src/routes/get_route.dart';
10 | import 'package:ocyclient/blocs/auth_bloc.dart';
11 | import 'package:ocyclient/blocs/community_bloc.dart';
12 | import 'package:ocyclient/blocs/edit_profile_bloc.dart';
13 | import 'package:ocyclient/blocs/locale_bloc.dart';
14 | import 'package:ocyclient/blocs/navigation_bloc.dart';
15 | import 'package:ocyclient/blocs/profile_bloc.dart';
16 | import 'package:ocyclient/blocs/projects_bloc.dart';
17 | import 'package:ocyclient/blocs/teams_bloc.dart';
18 | import 'package:ocyclient/configs/config.dart';
19 | import 'package:ocyclient/utils/app_translations.dart';
20 | import 'package:ocyclient/widgets/AboutUs/about_us.dart';
21 | import 'package:ocyclient/widgets/Auth/login_signup.dart';
22 | import 'package:ocyclient/widgets/Community/community.dart';
23 | import 'package:ocyclient/widgets/Home/home.dart';
24 | import 'package:ocyclient/widgets/Milestones/milestones.dart';
25 | import 'package:ocyclient/widgets/Profile/edit_profile.dart';
26 | import 'package:ocyclient/widgets/Profile/profile.dart';
27 | import 'package:ocyclient/widgets/Teams/teams.dart';
28 | import 'package:provider/provider.dart';
29 | import 'package:shared_preferences/shared_preferences.dart';
30 | import 'firebase_options.dart';
31 |
32 | void main() async {
33 | WidgetsFlutterBinding.ensureInitialized();
34 | await configureApp();
35 | runApp(OCYApp());
36 | }
37 |
38 | void enableEdgeToEdge({bool enable = true}) {
39 | ///Necessary for edge to edge
40 | SystemChrome.setSystemUIOverlayStyle(
41 | const SystemUiOverlayStyle(systemNavigationBarColor: Colors.white),
42 | );
43 | SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
44 | }
45 |
46 | Future configureApp() async {
47 | setUrlStrategy(PathUrlStrategy());
48 | await dotenv.load(fileName: "env");
49 | if (kIsWeb || Firebase.apps.isEmpty) {
50 | await Firebase.initializeApp(
51 | options: DefaultFirebaseOptions.currentPlatform);
52 | }
53 | SharedPreferences sp = await SharedPreferences.getInstance();
54 |
55 | bool isLoggedIn = sp.getBool(Config.prefIsLoggedIn) ?? false;
56 |
57 | final String defaultRouteName =
58 | WidgetsBinding.instance.window.defaultRouteName;
59 |
60 | bool allowAuthenticated =
61 | Config.authenticatedPreventAccessRoutes.contains(defaultRouteName);
62 | bool allowUnauthenticated =
63 | Config.unauthenticatedPreventAccessRoutes.contains(defaultRouteName);
64 | if (isLoggedIn && allowAuthenticated) {
65 | SystemNavigator.routeInformationUpdated(location: '/home', replace: true);
66 | }
67 | if (!isLoggedIn && allowUnauthenticated) {
68 | SystemNavigator.routeInformationUpdated(location: '/home', replace: true);
69 | }
70 |
71 | enableEdgeToEdge();
72 | }
73 |
74 | class OCYApp extends StatelessWidget {
75 | OCYApp({Key? key}) : super(key: key);
76 |
77 | final GlobalKey navigatorKey = GlobalKey();
78 |
79 | @override
80 | Widget build(BuildContext context) {
81 | return MultiProvider(
82 | providers: [
83 | ChangeNotifierProvider(
84 | create: (context) => NavigationBloc(navigatorKey),
85 | ),
86 | ChangeNotifierProvider(
87 | create: (context) => AuthenticationBloc(),
88 | ),
89 | ChangeNotifierProvider(
90 | create: (context) => ProfileBloc(),
91 | ),
92 | ChangeNotifierProvider(
93 | create: (context) => EditProfileBloc(),
94 | ),
95 | ChangeNotifierProvider(
96 | create: (context) => ProjectsBloc(),
97 | ),
98 | ChangeNotifierProvider(
99 | create: (context) => CommunityBloc(),
100 | ),
101 | ChangeNotifierProvider(
102 | create: (context) => TeamsBloc(),
103 | ),
104 | ChangeNotifierProvider(
105 | create: (context) => LocaleBLoc(navigatorKey),
106 | ),
107 | ],
108 | child: GetMaterialApp(
109 | title: "OCY Client",
110 | navigatorKey: navigatorKey,
111 | theme: ThemeData(
112 | appBarTheme: const AppBarTheme(
113 | color: Colors.white,
114 | centerTitle: false,
115 | elevation: 2,
116 | iconTheme: IconThemeData(
117 | color: Colors.black,
118 | ),
119 | titleTextStyle: TextStyle(
120 | fontSize: 15,
121 | fontWeight: FontWeight.bold,
122 | fontFamily: "PublicSans",
123 | ),
124 | ),
125 | iconTheme: const IconThemeData(
126 | color: Colors.black,
127 | ),
128 | buttonTheme: const ButtonThemeData(
129 | textTheme: ButtonTextTheme.accent,
130 | ),
131 | colorScheme: const ColorScheme.light(
132 | primary: Color(0xff0f254e),
133 | ),
134 | primaryColor: const Color(0xff0f254e),
135 | textButtonTheme: TextButtonThemeData(
136 | style: TextButton.styleFrom(
137 | textStyle: const TextStyle(
138 | fontWeight: FontWeight.bold,
139 | fontFamily: "PublicSans",
140 | fontSize: 16,
141 | ),
142 | ).copyWith(
143 | foregroundColor: MaterialStateProperty.resolveWith(
144 | (states) {
145 | if (states.contains(MaterialState.hovered)) {
146 | return const Color(0xff0f254e);
147 | }
148 | return Colors.black;
149 | },
150 | ),
151 | ),
152 | ),
153 | ),
154 | themeMode: ThemeMode.light,
155 | initialRoute: "/home",
156 | debugShowCheckedModeBanner: false,
157 | translations: AppTranslations(),
158 | supportedLocales: const [
159 | Locale('en', 'US'), //English
160 | Locale('bn', 'IN'), //Bengali
161 | ],
162 | locale: const Locale('en', 'US'),
163 | localizationsDelegates: const [
164 | GlobalMaterialLocalizations.delegate,
165 | GlobalWidgetsLocalizations.delegate,
166 | GlobalCupertinoLocalizations.delegate,
167 | ],
168 | getPages: [
169 | GetPage(
170 | name: '/home',
171 | page: () => const HomePage(),
172 | ),
173 | GetPage(
174 | name: '/',
175 | page: () => const HomePage(),
176 | ),
177 | GetPage(
178 | name: '/community',
179 | page: () => const CommunityPage(),
180 | ),
181 | GetPage(
182 | name: '/about_us',
183 | page: () => const AboutUsPage(),
184 | ),
185 | GetPage(
186 | name: '/milestones',
187 | page: () => const MilestonesPage(),
188 | ),
189 | GetPage(
190 | name: '/teams',
191 | page: () => const TeamsPage(),
192 | ),
193 | GetPage(
194 | name: '/auth',
195 | page: () => const LoginSignUp(),
196 | ),
197 | GetPage(
198 | name: '/profile',
199 | page: () => const ProfilePage(),
200 | ),
201 | GetPage(
202 | name: '/editProfile',
203 | page: () => const EditProfilePage(),
204 | ),
205 | GetPage(
206 | name: '/licenses',
207 | page: () => LicensePage(
208 | applicationIcon: Image.asset("assets/images/ocy_logo.png"),
209 | applicationName: "Open Codeyard",
210 | applicationVersion: Config.appVersion,
211 | ),
212 | ),
213 | ],
214 | ),
215 | );
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/lib/widgets/Teams/teams.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:ocyclient/blocs/teams_bloc.dart';
4 | import 'package:ocyclient/models/team/team_model.dart';
5 | import 'package:ocyclient/widgets/Teams/team_card.dart';
6 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
7 | import 'package:provider/provider.dart';
8 |
9 | class TeamsPage extends StatefulWidget {
10 | const TeamsPage({Key? key}) : super(key: key);
11 |
12 | @override
13 | State createState() => _TeamsPageState();
14 | }
15 |
16 | class _TeamsPageState extends State {
17 | @override
18 | Widget build(BuildContext context) {
19 | SystemChrome.setApplicationSwitcherDescription(
20 | ApplicationSwitcherDescription(
21 | label: 'Teams 🏘️',
22 | primaryColor: Theme.of(context).primaryColor.value,
23 | ),
24 | );
25 |
26 | Size size = MediaQuery.of(context).size;
27 |
28 | TeamsBloc tb = Provider.of(context);
29 |
30 | return OcyScaffold(
31 | body: SingleChildScrollView(
32 | physics: const BouncingScrollPhysics(),
33 | child: SizedBox(
34 | width: size.width,
35 | child: Column(
36 | crossAxisAlignment: CrossAxisAlignment.start,
37 | children: [
38 | Container(
39 | height: size.width < 650 ? size.height / 1.6 : size.height,
40 | width: size.width,
41 | padding: EdgeInsets.only(left: size.width * 0.1),
42 | decoration: const BoxDecoration(
43 | image: DecorationImage(
44 | image: NetworkImage(
45 | "https://i.imgur.com/SHXoCoG.png",
46 | ),
47 | fit: BoxFit.cover,
48 | ),
49 | color: Color(0xff071a2b),
50 | ),
51 | child: Column(
52 | crossAxisAlignment: CrossAxisAlignment.start,
53 | children: [
54 | const SizedBox(
55 | height: 150,
56 | ),
57 | SizedBox(
58 | width: size.width / (size.width > 550 ? 2 : 1),
59 | child: Text(
60 | "Teams are\nour pillars".toUpperCase(),
61 | style: TextStyle(
62 | fontFamily: "PublicSans",
63 | fontWeight: FontWeight.w700,
64 | fontSize: size.width > 1100
65 | ? 100
66 | : size.width > 800
67 | ? 60
68 | : 40,
69 | foreground: Paint()
70 | ..strokeWidth = 2
71 | ..style = PaintingStyle.stroke
72 | ..color = Colors.white,
73 | ),
74 | ),
75 | ),
76 | const SizedBox(
77 | height: 50,
78 | ),
79 | SizedBox(
80 | width: size.width / (size.width > 450 ? 2.4 : 1.2),
81 | child: Text(
82 | "If you believe in diversity, we believe you'll fit right in."
83 | " Be a part of something refreshing and revolutionary. "
84 | "Check out available roles below ",
85 | style: TextStyle(
86 | fontFamily: "PublicSans",
87 | color: Colors.white,
88 | fontWeight: FontWeight.bold,
89 | fontSize: size.width > 1100
90 | ? 25
91 | : size.width > 650
92 | ? 20
93 | : 18,
94 | ),
95 | ),
96 | ),
97 | ],
98 | ),
99 | ),
100 | Container(
101 | decoration: const BoxDecoration(
102 | color: Color(0xff071a2b),
103 | ),
104 | width: size.width,
105 | child: tb.isLoading
106 | ? SizedBox(
107 | height: 250,
108 | width: size.width,
109 | child: const Center(
110 | child: CircularProgressIndicator(
111 | color: Color(0xff8aafcc),
112 | ),
113 | ),
114 | )
115 | : Padding(
116 | padding: const EdgeInsets.only(top: 25.0),
117 | child: Column(
118 | mainAxisAlignment: MainAxisAlignment.start,
119 | children: [
120 | Padding(
121 | padding: EdgeInsets.symmetric(
122 | horizontal: size.width > 800 ? 100 : 15,
123 | ),
124 | child: size.width > 800
125 | ? Row(
126 | crossAxisAlignment:
127 | CrossAxisAlignment.center,
128 | children: [
129 | Column(
130 | children: "TEAMS"
131 | .split("")
132 | .map((string) => Text(
133 | string,
134 | style: TextStyle(
135 | fontFamily: "PublicSans",
136 | fontWeight:
137 | FontWeight.bold,
138 | fontSize:
139 | size.width > 1100
140 | ? 140
141 | : 80,
142 | height: 1.5,
143 | foreground: Paint()
144 | ..strokeWidth = 1
145 | ..style =
146 | PaintingStyle.stroke
147 | ..color = const Color(
148 | 0xff8aafcc,
149 | ),
150 | ),
151 | ))
152 | .toList(),
153 | ),
154 | const SizedBox(
155 | width: 50,
156 | ),
157 | Expanded(
158 | child: getTeams(size, tb),
159 | ),
160 | ],
161 | )
162 | : Column(
163 | children: [
164 | Text(
165 | "TEAMS",
166 | style: TextStyle(
167 | fontFamily: "PublicSans",
168 | fontWeight: FontWeight.bold,
169 | fontSize: 60,
170 | letterSpacing: 5,
171 | foreground: Paint()
172 | ..strokeWidth = 1
173 | ..style = PaintingStyle.stroke
174 | ..color = const Color(0xff8aafcc),
175 | ),
176 | ),
177 | getTeams(size, tb),
178 | ],
179 | ),
180 | )
181 | ],
182 | ),
183 | ),
184 | )
185 | ],
186 | ),
187 | ),
188 | ),
189 | );
190 | }
191 |
192 | Widget getTeams(Size size, TeamsBloc tb) {
193 | return ListView.builder(
194 | physics: const NeverScrollableScrollPhysics(),
195 | shrinkWrap: true,
196 | itemCount: tb.teams.length,
197 | itemBuilder: (context, index) {
198 | Team t = tb.teams[index];
199 | return TeamCard(
200 | size: size,
201 | title: t.name,
202 | members: t.members,
203 | );
204 | },
205 | );
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/lib/widgets/Utils/navigation_drawer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ocyclient/blocs/auth_bloc.dart';
3 | import 'package:ocyclient/blocs/navigation_bloc.dart';
4 | import 'package:ocyclient/configs/config.dart';
5 | import 'package:provider/provider.dart';
6 |
7 | class AppDrawer extends StatefulWidget {
8 | const AppDrawer({Key? key}) : super(key: key);
9 |
10 | @override
11 | AppDrawerState createState() => AppDrawerState();
12 | }
13 |
14 | class AppDrawerState extends State {
15 | String getRoute(String title) {
16 | switch (title) {
17 | case 'Events Calendar':
18 | return '/eventCalendar';
19 | case 'Best Destinations':
20 | return '/destination';
21 | case 'Special Offers':
22 | return '/specialOffer';
23 | case 'Request Artist':
24 | return '/Artists';
25 | case 'Contact Us':
26 | return '/contactus';
27 | case 'News Alert':
28 | return '/newsLetter';
29 | default:
30 | return '/home';
31 | }
32 | }
33 |
34 | final List _amIHovering = [false, false, false, false, false, false];
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | double width = MediaQuery.of(context).size.width / 1.5;
39 |
40 | double height = MediaQuery.of(context).size.height;
41 | String? name = ModalRoute.of(context)?.settings.name;
42 |
43 | NavigationBloc nb = Provider.of(context);
44 | AuthenticationBloc ab = Provider.of(context);
45 |
46 | return SizedBox(
47 | width: width,
48 | height: height,
49 | child: Drawer(
50 | backgroundColor: Colors.white,
51 | child: Column(
52 | children: [
53 | Container(
54 | height: 161 + MediaQuery.of(context).padding.top,
55 | margin: EdgeInsets.zero,
56 | padding: const EdgeInsets.all(20),
57 | decoration: BoxDecoration(
58 | borderRadius: const BorderRadius.only(
59 | bottomLeft: Radius.circular(25),
60 | // bottomRight: Radius.circular(20),
61 | ),
62 | color: const Color(0xff071a2b),
63 | border: Border.all(color: Colors.transparent),
64 | ),
65 | child: Column(
66 | crossAxisAlignment: CrossAxisAlignment.start,
67 | mainAxisAlignment: MainAxisAlignment.end,
68 | children: [
69 | Row(
70 | mainAxisAlignment: MainAxisAlignment.start,
71 | crossAxisAlignment: CrossAxisAlignment.center,
72 | children: [
73 | GestureDetector(
74 | onTap: () {
75 | if (ab.isLoggedIn) {
76 | nb.toRoute("/profile");
77 | } else {
78 | nb.toRoute("/auth");
79 | }
80 | },
81 | child: Container(
82 | height: 60,
83 | width: 60,
84 | decoration: BoxDecoration(
85 | borderRadius: BorderRadius.circular(10),
86 | color: Colors.white,
87 | border: Border.all(
88 | color: Colors.blueGrey,
89 | width: 3,
90 | ),
91 | ),
92 | child: ab.isLoggedIn
93 | ? ClipRRect(
94 | borderRadius: BorderRadius.circular(4),
95 | child:
96 | Image.network(ab.userModel.profilePicUrl),
97 | )
98 | : const Icon(
99 | Icons.person,
100 | color: Colors.black,
101 | ),
102 | ),
103 | ),
104 | const SizedBox(
105 | width: 15,
106 | ),
107 | ],
108 | ),
109 | const SizedBox(
110 | height: 15,
111 | ),
112 | Padding(
113 | padding:
114 | const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
115 | child: Text(
116 | "Hello 👋, ${ab.isLoggedIn ? getFirstName(ab.userModel.name) : "Guest"}",
117 | style: const TextStyle(
118 | color: Colors.white,
119 | fontSize: 20,
120 | ),
121 | ),
122 | ),
123 | ],
124 | ),
125 | ),
126 | const SizedBox(
127 | height: 20,
128 | ),
129 | Expanded(
130 | child: ListView(
131 | padding: const EdgeInsets.all(5),
132 | scrollDirection: Axis.vertical,
133 | physics: const BouncingScrollPhysics(),
134 | shrinkWrap: true,
135 | children: [
136 | ...List.generate(
137 | Config.routeNames.length,
138 | (index) {
139 | bool selected = isSelected(name, index);
140 | return drawerItem(
141 | index,
142 | selected,
143 | null,
144 | );
145 | },
146 | ),
147 | if (ab.isLoggedIn)
148 | drawerItem(
149 | 5,
150 | false,
151 | () {
152 | ab.signOut(context, nb);
153 | },
154 | ),
155 | ],
156 | ),
157 | ),
158 | Text(
159 | "v${Config.appVersion}",
160 | style: TextStyle(
161 | color: Theme.of(context).primaryColor,
162 | fontWeight: FontWeight.bold,
163 | fontSize: 19,
164 | fontFamily: "PublicSans",
165 | ),
166 | ),
167 | const SizedBox(
168 | height: 15,
169 | ),
170 | ],
171 | ),
172 | ),
173 | );
174 | }
175 |
176 | String getFirstName(String name) {
177 | if (name.split(" ").length > 1) {
178 | return name.split(" ")[0];
179 | } else {
180 | return name.substring(0, 8);
181 | }
182 | }
183 |
184 | bool isSelected(String? name, int index) {
185 | return name != null && name == Config.routeNames.values.toList()[index];
186 | }
187 |
188 | Widget drawerItem(int index, bool selected, void Function()? onTap) {
189 | return GestureDetector(
190 | onTap: () {
191 | if (onTap == null) {
192 | Navigator.of(context).pushNamed(
193 | Config.routeNames.values.toList()[index],
194 | );
195 | } else {
196 | onTap();
197 | }
198 | },
199 | child: MouseRegion(
200 | onEnter: (details) {
201 | setState(() {
202 | _amIHovering[index] = true;
203 | });
204 | },
205 | onExit: (details) => setState(() {
206 | _amIHovering[index] = false;
207 | }),
208 | cursor: SystemMouseCursors.click,
209 | child: Card(
210 | shape: RoundedRectangleBorder(
211 | borderRadius: BorderRadius.circular(
212 | 8,
213 | ),
214 | ),
215 | elevation: selected || _amIHovering[index] ? 5 : 0,
216 | child: ClipPath(
217 | clipper: ShapeBorderClipper(
218 | shape: RoundedRectangleBorder(
219 | borderRadius: BorderRadius.circular(
220 | 8,
221 | ),
222 | ),
223 | ),
224 | child: Container(
225 | decoration: BoxDecoration(
226 | border: selected
227 | ? const Border(
228 | left: BorderSide(
229 | color: Color(0xff071a2b),
230 | width: 5,
231 | ),
232 | )
233 | : _amIHovering[index]
234 | ? Border(
235 | left: BorderSide(
236 | color: index == 5 ? Colors.red : Colors.indigo,
237 | width: 5,
238 | ),
239 | )
240 | : null,
241 | ),
242 | padding: const EdgeInsets.symmetric(vertical: 15.0),
243 | child: Row(
244 | children: [
245 | const SizedBox(
246 | width: 10,
247 | ),
248 | Icon(
249 | selected || _amIHovering[index]
250 | ? Config.selectedAppDrawerIcons[index]
251 | : Config.appDrawerIcons[index],
252 | size: selected || _amIHovering[index] ? 18 : 25,
253 | ),
254 | const SizedBox(
255 | width: 20,
256 | ),
257 | Text(
258 | index == 5
259 | ? "Log Out"
260 | : Config.routeNames.keys.toList()[index],
261 | style: TextStyle(
262 | fontSize: 19,
263 | fontFamily: "PublicSans",
264 | fontWeight: selected || _amIHovering[index]
265 | ? FontWeight.w700
266 | : FontWeight.normal,
267 | color: selected ? const Color(0xff071a2b) : Colors.black,
268 | ),
269 | ),
270 | ],
271 | ),
272 | ),
273 | ),
274 | ),
275 | ),
276 | );
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/lib/widgets/Auth/login_signup.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ocyclient/blocs/auth_bloc.dart';
3 | import 'package:ocyclient/blocs/navigation_bloc.dart';
4 | import 'package:ocyclient/widgets/Auth/page_view/login_intro_page.dart';
5 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
6 | import 'package:ocyclient/widgets/Utils/snackbar.dart';
7 | import 'package:provider/provider.dart';
8 | import 'package:step_progress_indicator/step_progress_indicator.dart';
9 |
10 | class LoginSignUp extends StatefulWidget {
11 | const LoginSignUp({Key? key}) : super(key: key);
12 |
13 | @override
14 | LoginSignUpState createState() => LoginSignUpState();
15 | }
16 |
17 | class LoginSignUpState extends State {
18 | final PageController _pageController = PageController(keepPage: true);
19 | int _currentPage = 0;
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | Size size = MediaQuery.of(context).size;
24 | AuthenticationBloc ab = Provider.of(context);
25 | NavigationBloc nb = Provider.of(context);
26 |
27 | return OcyScaffold(
28 | enableSelection: false,
29 | body: Center(
30 | child: SizedBox(
31 | height: size.width < 600 ? size.height : size.height * 0.8,
32 | width: size.width < 600 ? size.width : size.width * 0.9,
33 | child: Card(
34 | elevation: 15,
35 | shape: size.width < 600
36 | ? null
37 | : RoundedRectangleBorder(
38 | borderRadius: BorderRadius.circular(15),
39 | ),
40 | child: size.width < 600
41 | ? loginWidget(size, ab, nb, true)
42 | : size.width < 1000
43 | ? introWidgets(size, true, ab: ab, nb: nb)
44 | : Row(
45 | children: [
46 | introWidgets(size, false),
47 | loginWidget(size, ab, nb, false),
48 | ],
49 | ),
50 | ),
51 | ),
52 | ),
53 | );
54 | }
55 |
56 | introWidgets(Size size, bool isMobile,
57 | {AuthenticationBloc? ab, NavigationBloc? nb}) {
58 | return SizedBox(
59 | width: isMobile
60 | ? size.width < 600
61 | ? size.width
62 | : size.width * 0.9
63 | : size.width * 0.45,
64 | height: size.width < 600 ? size.height : size.height * 0.8,
65 | child: Stack(
66 | children: [
67 | PageView(
68 | scrollDirection: Axis.vertical,
69 | controller: _pageController,
70 | onPageChanged: (int page) {
71 | setState(() {
72 | _currentPage = page;
73 | });
74 | },
75 | children: [
76 | const LoginIntroPage(
77 | title: "Welcome",
78 | subtitle: 'to the gateway of infinite possibilities',
79 | imagePath: "assets/images/welcome.jpg",
80 | ),
81 | const LoginIntroPage(
82 | title: "Events",
83 | subtitle: 'Gain access to exclusive events and tech fests',
84 | imagePath: "assets/images/events.jpg",
85 | ),
86 | //https://unsplash.com/@jannerboy62
87 | const LoginIntroPage(
88 | title: "Projects",
89 | subtitle:
90 | 'Manage all your teams and contributions in one place',
91 | imagePath: "assets/images/teams.jpg",
92 | ),
93 | if (isMobile) loginWidget(size, ab!, nb!, true),
94 | ],
95 | ),
96 | Positioned(
97 | top: 15,
98 | right: 30,
99 | child: StepProgressIndicator(
100 | totalSteps: isMobile ? 4 : 3,
101 | currentStep: _currentPage + 1,
102 | size: 4,
103 | padding: 0.5,
104 | selectedColor: Colors.amberAccent,
105 | unselectedColor: Colors.white,
106 | roundedEdges: const Radius.circular(10),
107 | onTap: (int index) {
108 | return () {
109 | _pageController.animateToPage(
110 | index,
111 | duration: const Duration(seconds: 1),
112 | curve: Curves.fastOutSlowIn,
113 | );
114 | };
115 | },
116 | direction: Axis.vertical,
117 | ),
118 | ),
119 | ],
120 | ),
121 | );
122 | }
123 |
124 | loginWidget(
125 | Size size, AuthenticationBloc ab, NavigationBloc nb, bool isMobile) {
126 | return SizedBox(
127 | width: isMobile
128 | ? size.width < 600
129 | ? size.width
130 | : size.width * 0.9
131 | : size.width * 0.45 - 8,
132 | child: Column(
133 | crossAxisAlignment: CrossAxisAlignment.center,
134 | mainAxisAlignment: MainAxisAlignment.center,
135 | children: [
136 | Image.asset(
137 | "assets/images/ocy_logo.png",
138 | height: 150,
139 | width: 150,
140 | ),
141 | RichText(
142 | text: TextSpan(
143 | text: "{",
144 | style: TextStyle(
145 | fontSize: size.width < 1100 && size.width > 900 ? 22 : 28,
146 | fontWeight: FontWeight.bold,
147 | color: Colors.black,
148 | ),
149 | children: [
150 | TextSpan(
151 | text: " Open ",
152 | style: TextStyle(
153 | fontSize: size.width < 1100 && size.width > 900 ? 22 : 28,
154 | fontWeight: FontWeight.normal,
155 | color: Colors.grey.shade700,
156 | fontFamily: "PublicSans",
157 | ),
158 | ),
159 | TextSpan(
160 | text: "Codeyard ",
161 | style: TextStyle(
162 | fontSize: size.width < 1100 && size.width > 900 ? 22 : 28,
163 | fontWeight: FontWeight.bold,
164 | fontFamily: "PublicSans",
165 | color: Colors.black,
166 | ),
167 | ),
168 | TextSpan(
169 | text: "} ;",
170 | style: TextStyle(
171 | fontSize: size.width < 1100 && size.width > 900 ? 22 : 28,
172 | fontWeight: FontWeight.bold,
173 | color: Colors.black,
174 | ),
175 | ),
176 | ],
177 | ),
178 | ),
179 | const SizedBox(
180 | height: 35,
181 | ),
182 | const Text(
183 | "Your journey to open source development starts here",
184 | textAlign: TextAlign.center,
185 | style: TextStyle(
186 | fontFamily: "PublicSans",
187 | fontSize: 18,
188 | ),
189 | ),
190 | const SizedBox(
191 | height: 35,
192 | ),
193 | SizedBox(
194 | height: 50,
195 | child: ElevatedButton.icon(
196 | style: ElevatedButton.styleFrom(
197 | backgroundColor: Colors.white,
198 | shape: RoundedRectangleBorder(
199 | borderRadius: BorderRadius.circular(15),
200 | ),
201 | padding: const EdgeInsets.all(15),
202 | ).copyWith(
203 | elevation: MaterialStateProperty.resolveWith(
204 | (Set states) {
205 | // if the button is pressed the elevation is 10.0, if not
206 | // it is 5.0
207 | if (states.contains(MaterialState.pressed)) {
208 | return 5.0;
209 | }
210 | return 10.0;
211 | },
212 | ),
213 | ),
214 | onPressed: () {
215 | if (ab.inProgress) {
216 | showToast("Please wait. Login in progress");
217 | return;
218 | }
219 | ab.authWithGoogle(nb, false);
220 | },
221 | icon: !isMobile && ab.isGoogleSignInOngoing
222 | ? Stack(
223 | alignment: Alignment.center,
224 | children: [
225 | Image.asset(
226 | "assets/images/google_logo.png",
227 | width: 30,
228 | height: 30,
229 | ),
230 | const Center(
231 | child: CircularProgressIndicator(
232 | color: Color(0xff87ceeb),
233 | ),
234 | ),
235 | ],
236 | )
237 | : Image.asset(
238 | "assets/images/google_logo.png",
239 | width: 30,
240 | height: 30,
241 | ),
242 | label: const Text(
243 | "Continue with Google",
244 | style: TextStyle(
245 | color: Colors.black,
246 | fontWeight: FontWeight.bold,
247 | fontSize: 16,
248 | ),
249 | ),
250 | ),
251 | ),
252 | const SizedBox(
253 | height: 30,
254 | ),
255 | SizedBox(
256 | height: 50,
257 | child: ElevatedButton.icon(
258 | style: ElevatedButton.styleFrom(
259 | backgroundColor: Colors.white,
260 | shape: RoundedRectangleBorder(
261 | borderRadius: BorderRadius.circular(15),
262 | ),
263 | padding: const EdgeInsets.all(15),
264 | ).copyWith(
265 | elevation: MaterialStateProperty.resolveWith(
266 | (Set states) {
267 | // if the button is pressed the elevation is 10.0, if not
268 | // it is 5.0
269 | if (states.contains(MaterialState.pressed)) {
270 | return 5.0;
271 | }
272 | return 10.0;
273 | },
274 | ),
275 | ),
276 | onPressed: () {
277 | if (ab.inProgress) {
278 | showToast("Please wait. Login in progress");
279 | return;
280 | }
281 | ab.authWithGithub(context, nb, false);
282 | },
283 | icon: !isMobile && ab.isGithubSignInOngoing
284 | ? Stack(
285 | alignment: Alignment.center,
286 | children: [
287 | Image.asset(
288 | "assets/images/github_logo.png",
289 | width: 30,
290 | height: 30,
291 | ),
292 | const Center(
293 | child: CircularProgressIndicator(
294 | color: Color(0xff87ceeb),
295 | ),
296 | ),
297 | ],
298 | )
299 | : Image.asset(
300 | "assets/images/github_logo.png",
301 | width: 30,
302 | height: 30,
303 | ),
304 | label: const Text(
305 | "Continue with Github",
306 | style: TextStyle(
307 | color: Colors.black,
308 | fontWeight: FontWeight.bold,
309 | fontSize: 16,
310 | ),
311 | ),
312 | ),
313 | ),
314 | ],
315 | ),
316 | );
317 | }
318 | }
319 |
--------------------------------------------------------------------------------
/lib/widgets/Home/sub_pages/benefits.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:line_icons/line_icons.dart';
3 | import 'package:ocyclient/configs/config.dart';
4 | import 'package:ocyclient/widgets/Utils/measure_size_render_object.dart';
5 | import 'package:ocyclient/widgets/Utils/snackbar.dart';
6 | import 'package:url_launcher/url_launcher_string.dart';
7 |
8 | class Benefits extends StatefulWidget {
9 | const Benefits({Key? key}) : super(key: key);
10 |
11 | @override
12 | BenefitsState createState() => BenefitsState();
13 | }
14 |
15 | class BenefitsState extends State {
16 | final List _amIHovering = [false, false, false];
17 |
18 | double cardHeight = 0;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | Size size = MediaQuery.of(context).size;
23 |
24 | return SizedBox(
25 | width: size.width,
26 | height: size.width > 950
27 | ? size.height * 0.8 - 50
28 | : size.width > 800
29 | ? size.height * 0.8 - 20
30 | : size.height * 0.9 - 100,
31 | child: Column(
32 | children: [
33 | const SizedBox(
34 | height: 25,
35 | ),
36 | Text(
37 | "Why Open Source ?",
38 | style: TextStyle(
39 | fontSize: size.width > 800
40 | ? 40
41 | : size.width > 400
42 | ? 35
43 | : 25,
44 | fontWeight: FontWeight.w700,
45 | fontFamily: "PublicSans",
46 | color: const Color(0xff071a2b),
47 | ),
48 | ),
49 | const SizedBox(
50 | height: 40,
51 | ),
52 | SizedBox(
53 | width: size.width > 400 ? size.width / 1.5 : size.width,
54 | child: Text(
55 | "We believe software should be free for all."
56 | "\nUnder our open source program we plan to reduce the economic gaps of society.",
57 | textAlign: TextAlign.center,
58 | style: TextStyle(
59 | fontSize: size.width > 800 ? 16 : 14,
60 | fontFamily: "PublicSans",
61 | color: Colors.black,
62 | ),
63 | ),
64 | ),
65 | const SizedBox(
66 | height: 40,
67 | ),
68 | Flexible(
69 | child: Center(
70 | child: ListView(
71 | shrinkWrap: true,
72 | padding: const EdgeInsets.all(20),
73 | physics: const BouncingScrollPhysics(),
74 | scrollDirection: Axis.horizontal,
75 | children: [
76 | getBenefitsCard(
77 | size,
78 | "Learn",
79 | "Be a part of great projects that enhance your career and skills.",
80 | 0,
81 | const Color(0xff071a2b),
82 | LineIcons.graduationCap,
83 | Row(
84 | mainAxisAlignment: MainAxisAlignment.center,
85 | children: [
86 | IconButton(
87 | icon: Icon(
88 | LineIcons.github,
89 | color: _amIHovering[0]
90 | ? const Color(0xffe8f9ff)
91 | : Colors.black,
92 | ),
93 | iconSize: 35,
94 | tooltip: "GitHub",
95 | onPressed: () {
96 | launchUrlString("https://github.com/OpenCodeyard");
97 | },
98 | ),
99 | ],
100 | ),
101 | ),
102 | const SizedBox(
103 | width: 40,
104 | ),
105 | getBenefitsCard(
106 | size,
107 | "Community",
108 | "Projects powered by a community that will "
109 | "always have a people first approach.",
110 | 1,
111 | const Color(0xff1e2e68),
112 | LineIcons.peopleCarry,
113 | Row(
114 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
115 | children: [
116 | IconButton(
117 | icon: Icon(
118 | LineIcons.linkedinIn,
119 | color: _amIHovering[1]
120 | ? const Color(0xffe8f9ff)
121 | : Colors.black,
122 | ),
123 | iconSize: 35,
124 | tooltip: "LinkedIn",
125 | onPressed: () {
126 | launchUrlString(Config.linkedInUrl);
127 | },
128 | ),
129 | IconButton(
130 | icon: Icon(
131 | LineIcons.discord,
132 | color: _amIHovering[1]
133 | ? const Color(0xffe8f9ff)
134 | : Colors.black,
135 | ),
136 | tooltip: "Discord",
137 | iconSize: 35,
138 | onPressed: () {
139 | showToast("Coming Soon");
140 | },
141 | ),
142 | IconButton(
143 | icon: Icon(
144 | LineIcons.telegram,
145 | color: _amIHovering[1]
146 | ? const Color(0xffe8f9ff)
147 | : Colors.black,
148 | ),
149 | tooltip: "Telegram",
150 | iconSize: 35,
151 | onPressed: () {
152 | launchUrlString(Config.telegramUrl);
153 | },
154 | ),
155 | ],
156 | ),
157 | ),
158 | const SizedBox(
159 | width: 40,
160 | ),
161 | getBenefitsCard(
162 | size,
163 | "Events",
164 | "Join live events that are great fun.",
165 | 2,
166 | const Color(0xff242435),
167 | LineIcons.calendarWithWeekFocus,
168 | null,
169 | ),
170 | ],
171 | ),
172 | ),
173 | ),
174 | ],
175 | ),
176 | );
177 | }
178 |
179 | Widget getBenefitsCard(
180 | Size size,
181 | String title,
182 | String subtitle,
183 | int index,
184 | Color iconColor,
185 | IconData icon,
186 | Widget? extra,
187 | ) {
188 | return MeasureSize(
189 | onChange: (Size size) {
190 | cardHeight = size.height;
191 | },
192 | key: Key(index.toString()),
193 | child: MouseRegion(
194 | onEnter: (details) {
195 | setState(() {
196 | _amIHovering[index] = true;
197 | });
198 | },
199 | onExit: (details) => setState(() {
200 | _amIHovering[index] = false;
201 | }),
202 | child: SizedBox(
203 | width: size.width / 5 < 300 ? 300 : size.width / 5,
204 | child: Card(
205 | elevation: _amIHovering[index] ? 35 : 5,
206 | shape: RoundedRectangleBorder(
207 | borderRadius: BorderRadius.circular(20),
208 | ),
209 | child: Stack(
210 | children: [
211 | Positioned(
212 | left: 0,
213 | bottom: 0,
214 | child: AnimatedContainer(
215 | width: _amIHovering[index]
216 | ? size.width / 5 < 300
217 | ? 300 - 8
218 | : size.width / 5 - 8
219 | : 0,
220 | height: _amIHovering[index] ? cardHeight - 8 : 0,
221 | decoration: BoxDecoration(
222 | borderRadius: BorderRadius.circular(20),
223 | color: iconColor,
224 | ),
225 | duration: const Duration(
226 | milliseconds: 1000,
227 | ),
228 | curve: Curves.easeOutQuint,
229 | ),
230 | ),
231 | Padding(
232 | padding:
233 | const EdgeInsets.only(left: 25.0, right: 25.0, top: 25.0),
234 | child: Column(
235 | crossAxisAlignment: CrossAxisAlignment.center,
236 | children: [
237 | Icon(
238 | icon,
239 | size: 60,
240 | color: _amIHovering[index]
241 | ? const Color(0xffe8f9ff)
242 | : Colors.black,
243 | ),
244 | const SizedBox(
245 | height: 15,
246 | ),
247 | Text(
248 | title,
249 | style: TextStyle(
250 | fontSize: 25,
251 | fontFamily: "PublicSans",
252 | color: _amIHovering[index]
253 | ? const Color(0xffe8f9ff)
254 | : Colors.black,
255 | fontWeight: FontWeight.w700,
256 | ),
257 | ),
258 | const SizedBox(
259 | height: 25,
260 | ),
261 | Text(
262 | subtitle,
263 | textAlign: TextAlign.center,
264 | style: TextStyle(
265 | fontSize: 16,
266 | height: 1.5,
267 | color: _amIHovering[index]
268 | ? const Color(0xffe8f9ff)
269 | : Colors.black,
270 | fontFamily: "PublicSans",
271 | ),
272 | ),
273 | const SizedBox(
274 | height: 25,
275 | ),
276 | extra ?? const SizedBox(),
277 | ],
278 | ),
279 | ),
280 | Positioned(
281 | right: -(size.width / 5 < 300 ? 300 : size.width / 5) / 10,
282 | bottom: -(size.width / 5 < 300 ? 300 : size.width / 5) / 10,
283 | child: AnimatedContainer(
284 | width: _amIHovering[index]
285 | ? (size.width / 5 < 300 ? 300 : size.width / 5) / 4
286 | : 0,
287 | height: _amIHovering[index]
288 | ? (size.width / 5 < 300 ? 300 : size.width / 5) / 4
289 | : 0,
290 | decoration: BoxDecoration(
291 | borderRadius: BorderRadius.circular(40),
292 | border: Border.all(
293 | color: const Color(0xffe8f9ff),
294 | width: 4,
295 | ),
296 | color: Colors.transparent,
297 | ),
298 | duration: const Duration(
299 | milliseconds: 1400,
300 | ),
301 | curve: Curves.easeOutQuint,
302 | ),
303 | ),
304 | Positioned(
305 | left: -(size.width / 5 < 300 ? 300 : size.width / 5) / 10,
306 | top: -(size.width / 5 < 300 ? 300 : size.width / 5) / 10,
307 | child: AnimatedContainer(
308 | width: _amIHovering[index]
309 | ? (size.width / 5 < 300 ? 300 : size.width / 5) / 4
310 | : 0,
311 | height: _amIHovering[index]
312 | ? (size.width / 5 < 300 ? 300 : size.width / 5) / 4
313 | : 0,
314 | decoration: BoxDecoration(
315 | borderRadius: BorderRadius.circular(40),
316 | border: Border.all(
317 | color: const Color(0xffe8f9ff),
318 | width: 4,
319 | ),
320 | color: Colors.transparent,
321 | ),
322 | duration: const Duration(
323 | milliseconds: 1400,
324 | ),
325 | curve: Curves.easeOutQuint,
326 | ),
327 | ),
328 | ],
329 | ),
330 | ),
331 | ),
332 | ),
333 | );
334 | }
335 | }
336 |
--------------------------------------------------------------------------------
/lib/widgets/Profile/profile.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart';
3 | import 'package:ocyclient/blocs/auth_bloc.dart';
4 | import 'package:ocyclient/blocs/navigation_bloc.dart';
5 | import 'package:ocyclient/blocs/profile_bloc.dart';
6 | import 'package:ocyclient/widgets/Profile/sub_pages/profile_user.dart';
7 | import 'package:ocyclient/widgets/Utils/common_widgets.dart';
8 | import 'package:ocyclient/widgets/Utils/ocy_scaffold.dart';
9 | import 'package:provider/provider.dart';
10 |
11 | class ProfilePage extends StatefulWidget {
12 | const ProfilePage({Key? key}) : super(key: key);
13 |
14 | @override
15 | ProfilePageState createState() => ProfilePageState();
16 | }
17 |
18 | class ProfilePageState extends State {
19 | ///TODO cover attribution Background vector created by freepik - www.freepik.com
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | Size size = MediaQuery.of(context).size;
24 |
25 | ProfileBloc pb = Provider.of(context);
26 | AuthenticationBloc ab = Provider.of(context);
27 | NavigationBloc nb = Provider.of(context);
28 |
29 | return OcyScaffold(
30 | body: SizedBox(
31 | height: size.height - 70,
32 | child: size.width < 1000
33 | ? SingleChildScrollView(
34 | physics: const BouncingScrollPhysics(),
35 | child: Column(
36 | children: [
37 | const SizedBox(
38 | height: 20,
39 | ),
40 | Padding(
41 | padding: const EdgeInsets.symmetric(horizontal: 8.0),
42 | child: Card(
43 | elevation: 10,
44 | shape: RoundedRectangleBorder(
45 | borderRadius: BorderRadius.circular(15),
46 | ),
47 | child: SingleChildScrollView(
48 | scrollDirection: Axis.horizontal,
49 | padding: const EdgeInsets.symmetric(
50 | horizontal: 5,
51 | vertical: 10,
52 | ),
53 | child: Row(
54 | mainAxisAlignment: MainAxisAlignment.center,
55 | children: getProfileMenu(size, pb, ab, nb),
56 | ),
57 | ),
58 | ),
59 | ),
60 | const UserTab(),
61 | ],
62 | ),
63 | )
64 | : Row(
65 | children: [
66 | Card(
67 | elevation: 10,
68 | margin: EdgeInsets.zero,
69 | child: SizedBox(
70 | height: size.height,
71 | width: 230,
72 | child: SingleChildScrollView(
73 | physics: const BouncingScrollPhysics(),
74 | padding: const EdgeInsets.symmetric(
75 | horizontal: 25,
76 | vertical: 10,
77 | ),
78 | child: Column(
79 | children: getProfileMenu(size, pb, ab, nb),
80 | ),
81 | ),
82 | ),
83 | ),
84 | getVerticalDivider(),
85 | const UserTab(),
86 | // getVerticalDivider(),
87 | // Column(
88 | // children: [
89 | //
90 | // Column(
91 | // crossAxisAlignment: CrossAxisAlignment.start,
92 | // children: [
93 | // Container(
94 | // margin: const EdgeInsets.all(10),
95 | // child: const Text(
96 | // "Details",
97 | // style: TextStyle(
98 | // fontWeight: FontWeight.bold,
99 | // fontSize: 40,
100 | // fontFamily: "PublicSans",
101 | // ),
102 | // ),
103 | // ),
104 | // Container(
105 | // width: 295,
106 | // margin: const EdgeInsets.all(10),
107 | // child: Card(
108 | // elevation: 10,
109 | // shape: RoundedRectangleBorder(
110 | // borderRadius: BorderRadius.circular(20),
111 | // ),
112 | // child: Container(
113 | // padding: const EdgeInsets.all(20),
114 | // child: Column(
115 | // crossAxisAlignment:
116 | // CrossAxisAlignment.center,
117 | // children: [
118 | // getIconifiedDetail(
119 | // ab.userModel.email.isEmpty
120 | // ? "Not Provided"
121 | // : ab.userModel.email,
122 | // FontAwesomeIcons.envelope,
123 | // Colors.red,
124 | // 200,
125 | // ),
126 | // const SizedBox(
127 | // height: 15,
128 | // ),
129 | // getIconifiedDetail(
130 | // "Government College of Engineering and Leather Technology",
131 | // FontAwesomeIcons.buildingColumns,
132 | // Colors.blue,
133 | // 200),
134 | // ],
135 | // ),
136 | // ),
137 | // ),
138 | // ),
139 | // ],
140 | // ),
141 | // Column(
142 | // crossAxisAlignment: CrossAxisAlignment.start,
143 | // children: [
144 | // Container(
145 | // margin: const EdgeInsets.all(10),
146 | // child: const Text(
147 | // "Details",
148 | // style: TextStyle(
149 | // fontWeight: FontWeight.bold,
150 | // fontSize: 40,
151 | // fontFamily: "PublicSans",
152 | // ),
153 | // ),
154 | // ),
155 | // Container(
156 | // width: 260,
157 | // margin: const EdgeInsets.all(10),
158 | // child: Card(
159 | // elevation: 10,
160 | // shape: RoundedRectangleBorder(
161 | // borderRadius: BorderRadius.circular(20),
162 | // ),
163 | // child: Container(
164 | // padding: const EdgeInsets.all(20),
165 | // child: Column(
166 | // crossAxisAlignment:
167 | // CrossAxisAlignment.center,
168 | // children: [
169 | // getIconifiedDetail(
170 | // (ab.userModel.locality?.isEmpty ?? true)
171 | // ? "Not Provided"
172 | // : ab.userModel.locality ?? "",
173 | // FontAwesomeIcons.locationDot,
174 | // Colors.red,
175 | // 170,
176 | // ),
177 | // const SizedBox(
178 | // height: 15,
179 | // ),
180 | // getIconifiedDetail(
181 | // (ab.userModel.dob?.isEmpty ?? true)
182 | // ? "Not Provided"
183 | // : ab.userModel.dob ?? "",
184 | // FontAwesomeIcons.calendarDays,
185 | // Colors.blue,
186 | // 170),
187 | // ],
188 | // ),
189 | // ),
190 | // ),
191 | // ),
192 | // ],
193 | // ),
194 | // ],
195 | // )
196 | ],
197 | ),
198 | ),
199 | );
200 | }
201 |
202 | Widget getVerticalDivider() {
203 | return const VerticalDivider(
204 | width: 1,
205 | color: Colors.black12,
206 | );
207 | }
208 |
209 | List getProfileMenu(
210 | Size size,
211 | ProfileBloc pb,
212 | AuthenticationBloc ab,
213 | NavigationBloc nb,
214 | ) {
215 | bool isHorizontal = false;
216 | if (size.width < 1000) {
217 | isHorizontal = true;
218 | }
219 | return [
220 | getCustomSizedBoxForMenu(isHorizontal),
221 | if (!isHorizontal) ...[
222 | Image.asset(
223 | "assets/images/ocy_logo.png",
224 | width: 100,
225 | height: 100,
226 | ),
227 | const SizedBox(
228 | height: 30,
229 | ),
230 | ],
231 | getSideMenuButton(
232 | pb,
233 | "User",
234 | FontAwesomeIcons.userLarge,
235 | 0,
236 | isHorizontal,
237 | ),
238 | getCustomSizedBoxForMenu(isHorizontal),
239 | getSideMenuButton(
240 | pb,
241 | "My Events",
242 | FontAwesomeIcons.solidCalendarCheck,
243 | 1,
244 | isHorizontal,
245 | ),
246 | getCustomSizedBoxForMenu(isHorizontal),
247 | getSideMenuButton(
248 | pb,
249 | "My Projects",
250 | FontAwesomeIcons.codeBranch,
251 | 2,
252 | isHorizontal,
253 | ),
254 | getCustomSizedBoxForMenu(isHorizontal),
255 | getSideMenuButton(
256 | pb,
257 | "Log Out",
258 | FontAwesomeIcons.rightFromBracket,
259 | 3,
260 | isHorizontal,
261 | authBloc: ab,
262 | navBloc: nb,
263 | ),
264 | getCustomSizedBoxForMenu(isHorizontal),
265 | ];
266 | }
267 |
268 | Widget getSideMenuButton(
269 | ProfileBloc pb,
270 | String title,
271 | IconData icon,
272 | int index,
273 | bool isHorizontal, {
274 | AuthenticationBloc? authBloc,
275 | NavigationBloc? navBloc,
276 | }) {
277 | return MouseRegion(
278 | cursor: SystemMouseCursors.click,
279 | child: GestureDetector(
280 | onTap: () {
281 | if (index == 3) {
282 | authBloc?.signOut(context, navBloc!);
283 | } else {
284 | pb.setCurrentSelectedItem(index);
285 | }
286 | },
287 | child: AnimatedContainer(
288 | padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
289 | decoration: BoxDecoration(
290 | color: pb.currentSelectedMenuItem == index
291 | ? const Color(0x73c6dbec)
292 | : Colors.white,
293 | borderRadius: BorderRadius.circular(10),
294 | ),
295 | duration: const Duration(milliseconds: 500),
296 | curve: Curves.fastOutSlowIn,
297 | child: SizedBox(
298 | child: Row(
299 | children: [
300 | Text(
301 | title,
302 | style: TextStyle(
303 | color: pb.currentSelectedMenuItem == index
304 | ? Colors.black
305 | : Colors.grey,
306 | fontWeight: pb.currentSelectedMenuItem == index
307 | ? FontWeight.bold
308 | : FontWeight.normal,
309 | fontSize: 14,
310 | fontFamily: "PublicSans"),
311 | ),
312 | if (isHorizontal)
313 | const SizedBox(
314 | width: 20,
315 | )
316 | else
317 | const Spacer(),
318 | getIconForButton(icon),
319 | if (isHorizontal)
320 | const SizedBox(
321 | width: 10,
322 | )
323 | ],
324 | ),
325 | ),
326 | ),
327 | ),
328 | );
329 | }
330 |
331 | Widget getCustomSizedBoxForMenu(bool isHorizontal) {
332 | return isHorizontal
333 | ? const SizedBox(
334 | width: 30,
335 | )
336 | : const SizedBox(
337 | height: 30,
338 | );
339 | }
340 | }
341 |
--------------------------------------------------------------------------------