Skip to content

LambertQuiz is a React Native-based and cross-platform mobile app that offers interactive and timed quizzes on various topics, including mathematics, science, history, geographics, and more πŸ‘½.

Notifications You must be signed in to change notification settings

MattDEV02/LambertQuiz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

82 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LambertQuiz

LambertQuiz Logo

LambertQuiz is a React Native-based and cross-platform mobile app that offers interactive and timed quizzes on various topics.

P.S. = Go to Releases section and download only the latest release (the fourth one).

Key Features ✨

  • Quiz on various topics: Users can choose from a wide range of topics for the quiz, including mathematics, science, history, geographics, and more.

  • Game Modes: Timed gameplay with final scoring.

  • Results Display: Shows the final score and correct / incorrect answers.

  • Dynamic sounds: Quizzes with beatiful sounds!

  • Security: The user's sensitive data, such as their password, are encrypted and stored in a very robust database.

  • Language: There is only the English language.

Screenshots πŸ“Έ

Sign Up page

LambertQuiz RegScreen screenshoot 1 LambertQuiz RegScreen screenshoot 2 LambertQuiz RegScreen screenshoot 3 LambertQuiz RegScreen screenshoot 4

Sign In page

LambertQuiz LoginScreen screenshoot 1 LambertQuiz LoginScreen screenshoot 2 LambertQuiz LoginScreen screenshoot 3

Home page

LambertQuiz HomeScreen screenshoot 1 LambertQuiz HomeScreen screenshoot 2 LambertQuiz HomeScreen screenshoot 3

Play Quiz page

LambertQuiz PlayQuizScreen screenshoot 1 LambertQuiz PlayQuizScreen screenshoot 2 LambertQuiz PlayQuizScreen screenshoot 3

Account page

LambertQuiz AccountScreen screenshoot 1 LambertQuiz AccountScreen screenshoot 2 LambertQuiz AccountScreen screenshoot 3 LambertQuiz AccountScreen screenshoot 4

Help page

LambertQuiz HelpScreen screenshoot 1 LambertQuiz HelpScreen screenshoot 2

Stats page

LambertQuiz StatsScreen screenshoot 1 LambertQuiz StatsScreen screenshoot 2 LambertQuiz StatsScreen screenshoot 3 LambertQuiz StatsScreen screenshoot 4

Installation πŸš€ and usage⚑

Requirements

  • Node.js

  • React Native

  • NPM or Yarn

Installation Instructions

  1. Clone the repository:
git clone https://github.com/MattDEV02/LambertQuiz.git
  1. Navigate to the project directory:
cd LambertQuiz
  1. Install dependencies:
npm install

# or using yarn

# yarn install
  1. Start the application:
npm  start

# or using yarn

# yarn start

P.S. = You can do both third and fourth step with "my comand script":

npm run all

Some code examples πŸ€–

App.js

import React, { useState, useEffect } from "react";
import "react-native-gesture-handler";
import { NavigationContainer } from "@react-navigation/native";
import { RootSiblingParent } from "react-native-root-siblings";
import AuthStackNavigator from "./navigators/AuthStackNavigator";
import AppStackNavigator from "./navigators/AppStackNavigator";
import { supabase } from "./app/lib/supabase-client";
import { validateObject } from "./utils/validators";

const App = () => {
	const [session, setSession] = useState(null);

	useEffect(() => {
		supabase.auth
			.getSession()
			.then(({ data: { session } }) => {
				setSession(session);
			})
			.catch((error) => console.error(error));

		supabase.auth.onAuthStateChange(async (_event, session) => {
			console.log(_event); //  INITIAL_SESSION / SIGNED_IN / SIGNED_OUT
			setSession(session);
		});
	}, []);
	return (
		<RootSiblingParent>
			<NavigationContainer>
				{validateObject(session) && validateObject(session.user) ? (
					<AppStackNavigator sessionUser={session.user} />
				) : (
					<AuthStackNavigator />
				)}
			</NavigationContainer>
		</RootSiblingParent>
	);
};

export default App;

HomeScreen.js

import React, { useState, useEffect } from "react";
import {
	View,
	Text,
	SafeAreaView,
	FlatList,
	ScrollView,
	StyleSheet,
} from "react-native";
import { supabase } from "../app/lib/supabase-client";
import Quiz from "../components/screens/HomeScreen/Quiz";
import FormInput from "../components/shared/FormInput";
import { COLORS } from "../constants/theme";
import {
	validateObject,
	validateString,
	validateArray,
} from "../utils/validators";
import { playClickSound } from "../utils/sounds";

const HomeScreen = ({ navigation, route }) => {
	const user = route.params.user;

	const [quizzes, setQuizzes] = useState([]);
	const [quiz, setQuiz] = useState("");
	const [searching, setSearching] = useState(false);
	const [refreshing, setRefreshing] = useState(false);

	useEffect(() => {
		const getQuizzes = async () => {
			setRefreshing(true);
			const { data, error } = await supabase
				.from("quizzes")
				.select()
				.order("category");
			if (validateObject(error)) {
				console.error(error);
				setRefreshing(false);
			} else if (validateArray(data, 1)) {
				setQuizzes(data);
			}
			setRefreshing(false);
		};

		const getQuizzesWithSearching = async () => {
			setRefreshing(true);
			const { data, error } = await supabase.rpc("get_searched_quizzes", {
				quiz_category: quiz,
			});
			if (validateObject(error)) {
				console.error(error);
				setRefreshing(false);
			} else if (validateArray(data, 0)) {
				setQuizzes(data);
			} else if (!validateString(quiz)) {
				setSearching(false);
				getQuizzes();
			}
			setRefreshing(false);
		};

		searching ? getQuizzesWithSearching() : getQuizzes();
	}, [quiz]);

	const handleOnPlayPress = async (quiz_id) => {
		await playClickSound();
		navigation.setParams({ quizId: quiz_id });
		navigation.navigate("Play Quiz page", {
			quizId: quiz_id,
			openedQuiz: true,
		});
	};

	return (
		<SafeAreaView
			style={{
				flex: 1,
				backgroundColor: COLORS.background,
				position: "relative",
			}}
		>
			{/* TOP BAR */}
			<ScrollView
				style={{
					marginBottom: 6.75,
				}}
			>
				<View>
					{/* Welcome title */}
					<View
						style={{
							...styles.container,
							marginTop: 27.5,
						}}
					>
						<Text style={{ ...styles.text, fontSize: 29 }}>
							Welcome{" "}
							{validateObject(user) && validateString(user.username)
								? user.username
								: null}{" "}
							!
						</Text>
					</View>

					{/* Quiz search form */}
					<View style={styles.container}>
						<FormInput
							placeholderText={"Search for a Quiz"}
							value={quiz}
							maxLength={15}
							autoComplete={"name"}
							autoCorrect={true}
							inputMode={"text"}
							keyboardType={"default"}
							inputError={false}
							inputSuccess={false}
							onChangeText={(quiz) => {
								setQuiz(quiz);
								setSearching(true);
							}}
							style={{ width: "89.5%" }}
							inputStyle={{
								marginTop: 7.5,
								marginBottom: 5,
								paddingVertical: 15,
								backgroundColor: COLORS.white,
								borderWidth: 0.35,
								borderColor: COLORS.secondary,
								borderRadius: 12,
								fontSize: 16,
							}}
						/>
					</View>
					{/* Quiz list */}
					<View style={{ marginBottom: 20 }}>
						{validateArray(quizzes, 1) ? (
							<FlatList
								data={quizzes}
								scrollEnabled={false}
								onRefresh={() => undefined}
								refreshing={refreshing}
								showsVerticalScrollIndicator={false}
								keyExtractor={(item) => item.quiz_id}
								renderItem={({ item: quiz }) => (
									<Quiz
										quiz={quiz}
										handleOnPlayPress={() =>
											handleOnPlayPress(quiz.quiz_id)
										}
									/>
								)}
							/>
						) : searching ? (
							<View style={{ ...styles.container, marginTop: 47 }}>
								<Text style={{ ...styles.text, color: "#EF0909" }}>
									NO Quizzes found.
								</Text>
							</View>
						) : null}
					</View>
				</View>
			</ScrollView>
		</SafeAreaView>
	);
};

const styles = StyleSheet.create({
	container: {
		flexDirection: "row",
		alignItems: "center",
		justifyContent: "center",
	},
	text: {
		fontSize: 26.5,
		color: COLORS.black,
		fontWeight: "bold",
	},
});

export default HomeScreen;

HelpScreen.js

import React from "react";
import { SafeAreaView, ScrollView } from "react-native";
import AccordionItem from "../components/screens/HelpScreen/AccordionItem";
import HelpFooter from "../components/screens/HelpScreen/HelpFooter";
import { appName, questionsNumber } from "../constants/theme";
import { passwordMaxLength } from "../constants/fieldsConstants";

const HelpScreen = () => {
	const accordionList = [
		{
			question: "",
			response: "",
		},
	];
	return (
		<SafeAreaView>
			<ScrollView>
				{accordionList.map((item, index) => (
					<AccordionItem
						question={item.question}
						response={item.response}
						key={index}
					/>
				))}
				<HelpFooter />
			</ScrollView>
		</SafeAreaView>
	);
};

export default HelpScreen;

Author ©️

Made with ❀️ and a lot of hard work πŸ‹οΈβ€β™‚οΈ by:

I am the only author of this beatiful app πŸ˜‰

Technologies used πŸ§‘β€πŸ’»

Name Version
Javascript ES6
React native 0.72.6
NodeJS 20.4.0
NPM 9.7.2
PostgreSQL 16.0
Visual Studio Code 1.85
Altervista //
Bootstrap 5
HTML 5
CSS 4.15
Markdown //
Windows 11

Project structure 🏠

  • src/: The main folder for the application source code.

    • src/components/: Contains all reusable components of the application.

    • src/screens/: Primary screens of the application, each associated with specific functionalities.

    • src/navigators/: Configuration and management of application navigation, using React Navigation or a similar library.

    • src/utils/: Utility functions, or helpers used across multiple parts of the code.

    • src/constants/: Utility constants, or helpers used across multiple parts of the code.

    • src/App.js: The main component of this project, it gets rendered in the index.js file (see below).

  • assets/: Images, fonts, or other multimedia assets used in the application.

  • index.js: The main entry of this project.

  • lambertquiz.sql: A SQL (PostGreSQL) script file that allows to create the database that I used for this App.

  • package.json: JSON metadata file that to define various properties and configurations related to the project, including its dependencies, scripts, version information, and other metadata.

  • README.md: Markdown documentation of this project.

Sources 🀝

ER Model πŸ”’

LambertQuiz ER model

Relational model πŸ”£

LambertQuiz Relational model

BCNF functional dependencies πŸ‘¨β€πŸŽ“

LambertQuiz Relational model

License πŸ—’οΈ

This project is licensed under the MIT License - see the LICENSE file for more details.