Open In App

Create a GPA Calculator using React Native

Last Updated : 16 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

A GPA calculator proves to be a useful tool for students who want to monitor their academic progress. In this article, we will build a GPA calculator using React Native, a popular framework for building mobile applications.

Preview Image

Prerequisites

Steps to Create React Native Application

Step 1: Create a React Native Application

Create a new React Native project for gpaCalculatorApp

npx create-expo-app gpaCalculatorApp

Step 2: ​Change the directory to the project folder:

cd gpaCalculatorApp

Project Structure

Package.json

{
  "dependencies": {
    "react-native-paper": "4.9.2",
    "@expo/vector-icons": "^13.0.0"
  }
}

Approach

The GPA Calculator app, de­veloped using React Native­, offers a seamless e­xperience for use­rs to input their course information including course name­, credit hours, and grade. With its user-frie­ndly interface featuring te­xt input fields, a grade picker, and inte­ractive buttons for adding and deleting course­s, the app dynamically calculates the use­r’s GPA based on the ente­red data. Powered by Re­act Native’s state manageme­nt capabilities, it efficiently capture­s user input, performs calculations, and showcases the­ comprehensive course­ list alongside the calculated GPA.

Example: The give­n code provides an illustration of a mobile app calle­d GPA Calculator, developed using Re­act Native. This app comprises three­ main components: CourseForm, CourseList, and GPACalculator. The­ CourseForm component is responsible­ for managing the input of course data and ensure­s validation before adding new course­s. On the other hand, the Course­List component displays the list of courses with options to de­lete entrie­s. Lastly, the GPACalculator component orchestrate­s the entire application by calculating the­ GPA based on entere­d courses and presenting it alongside­ the course list.

Javascript




import React, { useState } from "react";
import {
    View,
    Text,
    TextInput,
    TouchableOpacity,
    ScrollView,
    StyleSheet,
} from "react-native";
import RNPickerSelect from "react-native-picker-select";
import { styles } from "./styles";
  
const gradePoints = {
    "A+": 4.0,
    A: 4.0,
    "A-": 3.7,
    "B+": 3.3,
    B: 3.0,
    "B-": 2.7,
    "C+": 2.3,
    C: 2.0,
    "C-": 1.7,
    "D+": 1.3,
    D: 1.0,
    "D-": 0.7,
};
  
const CustomButton = ({ title, onPress, style }) => {
    return (
        <TouchableOpacity onPress={onPress}>
            <View style={[styles.customButton, style]}>
                <Text style={styles.customButtonText}>
                    {title}
                </Text>
            </View>
        </TouchableOpacity>
    );
};
  
const CourseForm = ({ onAddCourse }) => {
    const [courseInfo, setCourseInfo] = useState({
        courseName: "",
        creditHours: "0",
        grade: "A+",
    });
  
    const handleInputChange = (name, value) => {
        setCourseInfo({
            ...courseInfo,
            [name]: value,
        });
    };
  
    const handleAddCourse = () => {
        const { courseName, creditHours, grade } =
            courseInfo;
        if (
            courseName &&
            parseFloat(creditHours) > 0 &&
            grade
        ) {
            const newCourse = {
                courseName,
                creditHours: parseFloat(creditHours),
                grade,
            };
  
            onAddCourse(newCourse);
            setCourseInfo({
                courseName: "",
                creditHours: "0",
                grade: "A+",
            });
        } else {
            alert("Please enter valid course details.");
        }
    };
  
    return (
        <View style={styles.section}>
            <Text style={styles.label}>Course</Text>
            <TextInput
                value={courseInfo.courseName}
                onChangeText={(text) =>
                    handleInputChange("courseName", text)
                }
                style={styles.input}
            />
  
            <Text style={styles.label}>Credits</Text>
            <TextInput
                value={courseInfo.creditHours}
                onChangeText={(text) =>
                    handleInputChange("creditHours", text)
                }
                keyboardType="numeric"
                style={styles.input}
            />
  
            <Text style={styles.label}>Grade</Text>
            <RNPickerSelect
                value={courseInfo.grade}
                onValueChange={(value) =>
                    handleInputChange("grade", value)
                }
                style={styles.picker}
                items={Object.keys(gradePoints).map(
                    (key) => ({
                        label: key,
                        value: key,
                    })
                )}
            />
  
            <CustomButton
                title="Add"
                onPress={handleAddCourse}
                style={[
                    styles.addButton,
                    courseInfo.courseName &&
                    parseFloat(courseInfo.creditHours) >
                        0 &&
                    courseInfo.grade
                        ? styles.addButtonHover
                        : null,
                ]}
            />
        </View>
    );
};
  
const CourseList = ({
    courses,
    onDeleteCourse,
    calculateGPA,
}) => {
    return (
        <View style={styles.section}>
            <Text style={styles.header}>Course List</Text>
            <ScrollView style={styles.list}>
                <View style={styles.listHeader}>
                    <Text>Course</Text>
                    <Text>Credits</Text>
                    <Text>Grade</Text>
                    <Text>Action</Text>
                </View>
                {courses.map((course, index) => (
                    <View
                        style={styles.listItem}
                        key={index}
                    >
                        <Text>{course.courseName}</Text>
                        <Text>{course.creditHours}</Text>
                        <Text>{course.grade}</Text>
                        <TouchableOpacity
                            style={styles.deletebtn}
                            onPress={() =>
                                onDeleteCourse(index)
                            }
                        >
                            <Text
                                style={styles.deletebtntext}
                            >
                                Delete
                            </Text>
                        </TouchableOpacity>
                    </View>
                ))}
            </ScrollView>
  
            <Text style={styles.gpa}>
                GPA: {calculateGPA().toFixed(2)}
            </Text>
        </View>
    );
};
  
const App = () => {
    const [courses, setCourses] = useState([]);
  
    const addCourse = (newCourse) => {
        setCourses([...courses, newCourse]);
    };
  
    const deleteCourse = (index) => {
        const updatedCourses = courses.filter(
            (course, i) => i !== index
        );
        setCourses(updatedCourses);
    };
  
    const calculateGPA = () => {
        let totalGradePoints = 0;
        let totalCreditHours = 0;
  
        courses.forEach((course) => {
            totalGradePoints +=
                gradePoints[course.grade] *
                course.creditHours;
            totalCreditHours += course.creditHours;
        });
  
        return totalCreditHours === 0
            ? 0
            : totalGradePoints / totalCreditHours;
    };
  
    return (
        <View style={styles.container}>
            <Text style={styles.title}>GPA Calculator</Text>
            <CourseForm onAddCourse={addCourse} />
            <CourseList
                courses={courses}
                onDeleteCourse={deleteCourse}
                calculateGPA={calculateGPA}
            />
        </View>
    );
};
  
export default App;


Javascript




//styles.js
  
import { StyleSheet } from "react-native";
  
const styles = StyleSheet.create({
    container: {
        flex: 1,
        padding: 16,
        backgroundColor: "#f0f0f0",
    },
    title: {
        fontSize: 25,
        fontWeight: "bold",
        marginBottom: 10,
        textAlign: "center",
        color: "#333",
        margin: 10,
    },
    section: {
        marginBottom: 16,
        backgroundColor: "#fff",
        padding: 20,
        borderRadius: 5,
        borderWidth: 1,
        borderColor: "#ced4da",
        shadowColor: "grey",
        shadowOffset: {
            width: 0,
            height: 6,
        },
        shadowOpacity: 1,
        shadowRadius: 15,
        elevation: 5,
    },
    label: {
        fontSize: 16,
        marginBottom: 8,
        color: "#333",
    },
    input: {
        borderColor: "#ced4da",
        borderWidth: 1,
        borderRadius: 4,
        padding: 8,
        marginBottom: 8,
        fontSize: 16,
        color: "#333",
    },
    header: {
        fontSize: 18,
        fontWeight: "bold",
        marginBottom: 10,
        textAlign: "center",
        color: "#333",
    },
    list: {
        maxHeight: 200,
    },
    listHeader: {
        flexDirection: "row",
        justifyContent: "space-between",
        borderBottomWidth: 1,
        borderColor: "#ccc",
        marginBottom: 10,
        paddingBottom: 10,
    },
    listItem: {
        flexDirection: "row",
        justifyContent: "space-between",
        borderBottomWidth: 1,
        borderColor: "#ccc",
        marginBottom: 8,
        paddingBottom: 8,
    },
    gpa: {
        fontSize: 20,
        fontWeight: "bold",
        marginTop: 10,
        textAlign: "center",
        color: "#333",
    },
    addButton: {
        padding: 9.5,
        backgroundColor: "#fff",
        color: "#1d9bf0",
        borderWidth: 1,
        borderColor: "#1d9bf0",
        borderRadius: 4,
        fontWeight: "bold",
        transition: "0.5s all",
        textAlign: "center",
    },
    addButtonHover: {
        color: "white",
        backgroundColor: "#1d9bf0",
        borderColor: "#1d9bf0",
        borderWidth: 1,
    },
    deletebtn: {
        padding: 9.5,
        color: "#1d9bf0",
        fontWeight: "bold",
        textAlign: "center",
        backgroundColor: "red",
        borderRadius: 15,
    },
    deletebtntext: {
        color: "white",
    },
    picker: {
        fontSize: 16,
        paddingVertical: 12,
        paddingHorizontal: 10,
        borderWidth: 1,
        borderColor: "gray",
        borderRadius: 4,
        color: "black",
        paddingRight: 30,
    },
});
  
export { styles };


Steps to Run:

To run react native application use the following command:

npx expo start
  • To run on Android:
npx react-native run-android
  • To run on iOS:
npx react-native run-ios

Output:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads