Refactored types for better readability

This commit is contained in:
Keannu Bernasol 2023-08-14 23:29:53 +08:00
parent ce2bffe1cb
commit 497e50f2a4
9 changed files with 157 additions and 117 deletions

View file

@ -1,12 +1,12 @@
import axios from "axios";
import AsyncStorage from "@react-native-async-storage/async-storage";
import {
ActivationParams,
LoginParams,
OnboardingParams,
PatchStudentData,
RegistrationParams,
StudentStatus,
ActivationType,
LoginType,
OnboardingType,
PatchUserInfoType,
RegistrationType,
StudentStatusType,
} from "../../interfaces/Interfaces";
export let backendURL = "https://stude.keannu1.duckdns.org";
@ -67,7 +67,7 @@ export async function GetConfig() {
}
// User APIs
export function UserRegister(register: RegistrationParams) {
export function UserRegister(register: RegistrationType) {
console.log(JSON.stringify(register));
return instance
.post("/api/v1/accounts/users/", register)
@ -82,7 +82,7 @@ export function UserRegister(register: RegistrationParams) {
});
}
export function UserLogin(user: LoginParams) {
export function UserLogin(user: LoginType) {
return instance
.post("/api/v1/accounts/jwt/create/", user)
.then(async (response) => {
@ -128,7 +128,7 @@ export async function TokenRefresh() {
return false;
});
}
export async function UserInfo() {
export async function GetUserInfo() {
const config = await GetConfig();
return instance
.get("/api/v1/accounts/users/me/", config)
@ -144,7 +144,7 @@ export async function UserInfo() {
});
}
export async function PatchUserInfo(info: PatchStudentData) {
export async function PatchUserInfo(info: PatchUserInfoType) {
const config = await GetConfig();
return instance
.patch("/api/v1/accounts/users/me/", info, config)
@ -160,13 +160,13 @@ export async function PatchUserInfo(info: PatchStudentData) {
});
}
export function UserActivate(activation: ActivationParams) {
export function UserActivate(activation: ActivationType) {
return instance
.post("/api/v1/accounts/users/activation/", activation)
.then(async (response) => {
.then(() => {
return true;
})
.catch((error) => {
.catch(() => {
return false;
});
}
@ -244,23 +244,6 @@ export async function GetSubjects() {
});
}
export async function OnboardingUpdateStudentInfo(info: OnboardingParams) {
const config = await GetConfig();
return instance
.patch("/api/v1/accounts/users/me/", info, config)
.then((response) => {
console.log(JSON.stringify(response.data));
return [true, response.data];
})
.catch((error) => {
let error_message = "";
if (error.response) error_message = error.response.data;
else error_message = "Unable to reach servers";
console.log("Error updating onboarding info", error_message);
return [false, error_message];
});
}
export async function GetStudentStatus() {
const config = await GetConfig();
return instance
@ -277,7 +260,7 @@ export async function GetStudentStatus() {
});
}
export async function PatchStudentStatus(info: StudentStatus) {
export async function PatchStudentStatus(info: StudentStatusType) {
const config = await GetConfig();
console.log(info);
return instance

View file

@ -30,7 +30,7 @@ export interface LoggedInUserState {
// API Interfaces
export interface RegistrationParams {
export interface RegistrationType {
email: string;
username: string;
password: string;
@ -39,12 +39,12 @@ export interface RegistrationParams {
student_id_number: string;
}
export interface LoginParams {
export interface LoginType {
username: string;
password: string;
}
export interface ActivationParams {
export interface ActivationType {
uid: string;
token: string;
}
@ -55,38 +55,38 @@ export interface OptionType {
}
// Semester
export interface Semester {
export interface SemesterType {
id: string;
name: string;
shortname: string;
}
export type Semesters = Array<Semester>;
export type SemestersType = Array<SemesterType>;
export type SemesterParams = [boolean, Semesters];
export type SemesterReturnType = [boolean, SemestersType];
// Year Level
export interface YearLevel {
export interface YearLevelType {
id: string;
name: string;
shortname: string;
}
export type YearLevels = Array<YearLevel>;
export type YearLevelsType = Array<YearLevelType>;
export type YearLevelParams = [boolean, YearLevels];
export type YearLevelReturnType = [boolean, YearLevelsType];
// Course
export interface Course {
export interface CourseType {
id: string;
name: string;
shortname: string;
}
export type Courses = Array<Course>;
export type CourseParams = [boolean, Courses];
export type CoursesType = Array<CourseType>;
export type CourseReturnType = [boolean, CoursesType];
// Subject
export interface Subject {
export interface SubjectType {
id: number;
name: string;
code: string;
@ -95,31 +95,31 @@ export interface Subject {
semester: string;
}
export type Subjects = Array<Subject>;
export type SubjectParams = [boolean, Subjects];
export type SubjectsType = Array<SubjectType>;
export type SubjectsReturnType = [boolean, SubjectsType];
export type avatar = {
export type AvatarType = {
uri: string;
type: string;
name: string;
};
// For dropdown menu
export interface OnboardingParams {
export interface OnboardingType {
year_level: string;
course: string;
semester: string;
}
export interface PatchStudentData {
course?: string | null;
first_name?: string | null;
last_name?: string | null;
semester?: string | null;
subjects?: any[] | null; // To-do, replace 'any' with your actual type
year_level?: string | null;
irregular?: boolean | null;
avatar?: string | null;
export interface PatchUserInfoType {
course?: string;
first_name?: string;
last_name?: string;
semester?: string;
subjects?: string[];
year_level?: string;
irregular?: boolean;
avatar?: string;
}
interface Location {
@ -127,7 +127,7 @@ interface Location {
longitude: number;
}
export interface StudentStatus {
export interface StudentStatusType {
user?: string;
subject?: string;
location?: Location;
@ -135,11 +135,11 @@ export interface StudentStatus {
active?: boolean;
}
export type StudentStatusParams = [boolean, StudentStatus];
export type StudentStatusReturnType = [boolean, StudentStatusType];
export type LocationType = Location.LocationObject;
export interface StudentData {
export interface UserInfoType {
first_name: string;
last_name: string;
email: string;
@ -156,4 +156,4 @@ export interface StudentData {
username: string;
}
export type UserInfoParams = [boolean, StudentData];
export type UserInfoReturnType = [boolean, UserInfoType];

View file

@ -8,9 +8,10 @@ import GetDistance from "../../components/GetDistance/GetDistance";
import Button from "../../components/Button/Button";
import {
RootDrawerParamList,
StudentStatusParams,
StudentStatusReturnType,
LocationType,
StudentStatusType,
} from "../../interfaces/Interfaces";
import { LocationType } from "../../interfaces/Interfaces";
import { useNavigation } from "@react-navigation/native";
import {
GetStudentStatus,
@ -104,8 +105,14 @@ export default function Home() {
const [buttonLabel, setButtonLabel] = useState("Start studying");
const StudentStatus = useQuery({
queryKey: ["user_status"],
queryFn: GetStudentStatus,
onSuccess: (data: StudentStatusParams) => {
queryFn: async () => {
const data = await GetStudentStatus();
if (data[0] == false) {
return Promise.reject(new Error());
}
return data;
},
onSuccess: (data: StudentStatusReturnType) => {
if (data[1].active !== undefined) {
setStudying(data[1].active);
}
@ -125,7 +132,13 @@ export default function Home() {
});
const mutation = useMutation({
mutationFn: PatchStudentStatus,
mutationFn: async (info: StudentStatusType) => {
const data = await PatchStudentStatus(info);
if (data[0] != true) {
return Promise.reject(new Error());
}
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["user_status"] });

View file

@ -3,10 +3,10 @@ import styles from "../../styles";
import { View, Text } from "react-native";
import { useNavigation } from "@react-navigation/native";
import {
Course,
RootDrawerParamList,
Semester,
YearLevel,
CourseType,
SemesterType,
YearLevelType,
} from "../../interfaces/Interfaces";
import { colors } from "../../styles";
import { MotiView } from "moti";
@ -18,12 +18,11 @@ import {
GetCourses,
GetSemesters,
GetYearLevels,
OnboardingUpdateStudentInfo,
PatchUserInfo,
} from "../../components/Api/Api";
import { useDispatch } from "react-redux";
import { unsetOnboarding } from "../../features/redux/slices/StatusSlice/StatusSlice";
import { setUser } from "../../features/redux/slices/UserSlice/UserSlice";
import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer";
import AnimatedContainerNoScroll from "../../components/AnimatedContainer/AnimatedContainerNoScroll";
import { useToast } from "react-native-toast-notifications";
export default function Onboarding() {
@ -42,7 +41,7 @@ export default function Onboarding() {
queryKey: ["semesters"],
queryFn: GetSemesters,
onSuccess: (data) => {
let semesters = data[1].map((item: Semester) => ({
let semesters = data[1].map((item: SemesterType) => ({
label: item.name,
value: item.name,
}));
@ -68,7 +67,7 @@ export default function Onboarding() {
queryKey: ["year_levels"],
queryFn: GetYearLevels,
onSuccess: (data) => {
let year_levels = data[1].map((item: YearLevel) => ({
let year_levels = data[1].map((item: YearLevelType) => ({
label: item.name,
value: item.name,
}));
@ -97,7 +96,7 @@ export default function Onboarding() {
queryKey: ["courses"],
queryFn: GetCourses,
onSuccess: (data) => {
let courses = data[1].map((item: Course) => ({
let courses = data[1].map((item: CourseType) => ({
label: item.name,
value: item.name,
}));
@ -241,7 +240,7 @@ export default function Onboarding() {
!selected_yearlevel || !selected_course || !selected_semester
}
onPress={async () => {
let result = await OnboardingUpdateStudentInfo({
let result = await PatchUserInfo({
semester: selected_semester,
course: selected_course,
year_level: selected_yearlevel,

View file

@ -15,7 +15,6 @@ import { RootDrawerParamList } from "../../interfaces/Interfaces";
import SignupIcon from "../../icons/SignupIcon/SignupIcon";
import { UserRegister } from "../../components/Api/Api";
import IsNumber from "../../components/IsNumber/IsNumber";
import ParseError from "../../components/ParseError/ParseError";
import AnimatedContainer from "../../components/AnimatedContainer/AnimatedContainer";
import { useToast } from "react-native-toast-notifications";

View file

@ -1,7 +1,7 @@
import * as React from "react";
import styles from "../../styles";
import { View, Text, ActivityIndicator } from "react-native";
import { TokenRefresh, UserInfo } from "../../components/Api/Api";
import { TokenRefresh, GetUserInfo } from "../../components/Api/Api";
import { useDispatch } from "react-redux";
import { colors } from "../../styles";
import { useEffect, useState } from "react";
@ -25,7 +25,7 @@ export default function Revalidation() {
useEffect(() => {
setState("Previous session found");
TokenRefresh().then(async (response) => {
let user_info = await UserInfo();
let user_info = await GetUserInfo();
if (response && user_info[0]) {
dispatch(login());
dispatch(setUser(user_info[1]));

View file

@ -3,13 +3,14 @@ import styles, { Viewport } from "../../styles";
import { View, Text, ToastAndroid } from "react-native";
import { useState } from "react";
import {
UserInfoParams,
UserInfoReturnType,
OptionType,
RootDrawerParamList,
StudentStatusType,
} from "../../interfaces/Interfaces";
import Button from "../../components/Button/Button";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { PatchStudentStatus, UserInfo } from "../../components/Api/Api";
import { PatchStudentStatus, GetUserInfo } from "../../components/Api/Api";
import { colors } from "../../styles";
import DropDownPicker from "react-native-dropdown-picker";
import AnimatedContainerNoScroll from "../../components/AnimatedContainer/AnimatedContainerNoScroll";
@ -30,8 +31,8 @@ export default function StartStudying({ route }: any) {
const [subjects, setSubjects] = useState<OptionType[]>([]);
const StudentInfo = useQuery({
queryKey: ["user"],
queryFn: UserInfo,
onSuccess: (data: UserInfoParams) => {
queryFn: GetUserInfo,
onSuccess: (data: UserInfoReturnType) => {
let subjects = data[1].subjects.map((subject: string) => ({
label: subject,
value: subject,
@ -49,7 +50,13 @@ export default function StartStudying({ route }: any) {
});
const mutation = useMutation({
mutationFn: PatchStudentStatus,
mutationFn: async (info: StudentStatusType) => {
const data = await PatchStudentStatus(info);
if (data[0] == false) {
return Promise.reject(new Error("Error updating student status"));
}
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["user_status"] });

View file

@ -3,15 +3,21 @@ import styles from "../../styles";
import { View, Text } from "react-native";
import { useState } from "react";
import {
UserInfoParams,
SubjectParams,
Subject,
UserInfoReturnType,
SubjectsReturnType,
SubjectType,
OptionType,
StudentStatusType,
} from "../../interfaces/Interfaces";
import Button from "../../components/Button/Button";
import { Image } from "react-native";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { GetSubjects, PatchUserInfo, UserInfo } from "../../components/Api/Api";
import {
GetSubjects,
PatchUserInfo,
GetUserInfo,
PatchStudentStatus,
} from "../../components/Api/Api";
import { colors } from "../../styles";
import DropDownPicker from "react-native-dropdown-picker";
import AnimatedContainerNoScroll from "../../components/AnimatedContainer/AnimatedContainerNoScroll";
@ -23,6 +29,30 @@ export default function SubjectsPage() {
const logged_in_user = useSelector((state: RootState) => state.user.user);
const queryClient = useQueryClient();
const toast = useToast();
// Student Status
const studentstatus_mutation = useMutation({
mutationFn: async (info: StudentStatusType) => {
const data = await PatchStudentStatus(info);
if (data[0] != true) {
return Promise.reject(new Error());
}
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["user_status"] });
},
onError: () => {
toast.show("An error has occured\nChanges have not been saved", {
type: "warning",
placement: "top",
duration: 2000,
animationType: "slide-in",
});
},
});
// User Info
const [user, setUser] = useState({
first_name: "",
@ -39,8 +69,8 @@ export default function SubjectsPage() {
});
const StudentInfo = useQuery({
queryKey: ["user"],
queryFn: UserInfo,
onSuccess: (data: UserInfoParams) => {
queryFn: GetUserInfo,
onSuccess: (data: UserInfoReturnType) => {
setUser({
...user,
first_name: data[1].first_name,
@ -69,7 +99,11 @@ export default function SubjectsPage() {
queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["subjects"] });
setSelectedSubjects([]);
toast.show("Changes applied successfully", {
// Reset student status when changing user info to prevent bugs
studentstatus_mutation.mutate({
active: false,
});
toast.show("Changes applied successfully.\nStudent status reset", {
type: "success",
placement: "top",
duration: 2000,
@ -88,9 +122,9 @@ export default function SubjectsPage() {
enabled: StudentInfo.isFetched,
queryKey: ["subjects"],
queryFn: GetSubjects,
onSuccess: (data: SubjectParams) => {
onSuccess: (data: SubjectsReturnType) => {
if (data[1]) {
let subjects = data[1].map((subject: Subject) => ({
let subjects = data[1].map((subject: SubjectType) => ({
label: subject.name,
value: subject.name,
}));

View file

@ -10,15 +10,15 @@ import {
} from "react-native";
import { useState } from "react";
import {
SemesterParams,
UserInfoParams,
Semester,
SubjectParams,
Subject,
YearLevel,
Course,
SemesterReturnType,
UserInfoReturnType,
SemesterType,
YearLevelType,
CourseType,
OptionType,
Subjects,
StudentStatusType,
UserInfoType,
PatchUserInfoType,
} from "../../interfaces/Interfaces";
import Button from "../../components/Button/Button";
import { Image } from "react-native";
@ -26,11 +26,10 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
GetCourses,
GetSemesters,
GetSubjects,
GetYearLevels,
PatchStudentStatus,
PatchUserInfo,
UserInfo,
GetUserInfo,
} from "../../components/Api/Api";
import { colors } from "../../styles";
import DropDownPicker from "react-native-dropdown-picker";
@ -52,16 +51,16 @@ export default function UserInfoPage() {
// Student Status
const studentstatus_mutation = useMutation({
mutationFn: PatchStudentStatus,
mutationFn: async (info: StudentStatusType) => {
const data = await PatchStudentStatus(info);
if (data[0] != true) {
return Promise.reject(new Error());
}
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["user_status"] });
toast.show("Student Status has been reset", {
type: "success",
placement: "top",
duration: 2000,
animationType: "slide-in",
});
},
onError: () => {
toast.show("An error has occured\nChanges have not been saved", {
@ -89,8 +88,8 @@ export default function UserInfoPage() {
});
const StudentInfo = useQuery({
queryKey: ["user"],
queryFn: UserInfo,
onSuccess: (data: UserInfoParams) => {
queryFn: GetUserInfo,
onSuccess: (data: UserInfoReturnType) => {
// console.log(data[1]);
setUser({
...user,
@ -119,7 +118,13 @@ export default function UserInfoPage() {
});
const mutation = useMutation({
mutationFn: PatchUserInfo,
mutationFn: async (info: PatchUserInfoType) => {
const data = await PatchUserInfo(info);
if (data[0] == false) {
return Promise.reject(new Error());
}
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["user"] });
queryClient.invalidateQueries({ queryKey: ["subjects"] });
@ -127,7 +132,7 @@ export default function UserInfoPage() {
studentstatus_mutation.mutate({
active: false,
});
toast.show("Changes applied successfully", {
toast.show("Changes applied successfully.\nStudent status reset", {
type: "success",
placement: "top",
duration: 2000,
@ -152,8 +157,8 @@ export default function UserInfoPage() {
const Semesters = useQuery({
queryKey: ["semesters"],
queryFn: GetSemesters,
onSuccess: (data: SemesterParams) => {
let semestersData = data[1].map((semester: Semester) => ({
onSuccess: (data: SemesterReturnType) => {
let semestersData = data[1].map((semester: SemesterType) => ({
label: semester.name,
value: semester.name,
shortname: semester.shortname,
@ -179,7 +184,7 @@ export default function UserInfoPage() {
queryKey: ["year_levels"],
queryFn: GetYearLevels,
onSuccess: (data) => {
let year_levels = data[1].map((yearlevel: YearLevel) => ({
let year_levels = data[1].map((yearlevel: YearLevelType) => ({
label: yearlevel.name,
value: yearlevel.name,
}));
@ -203,7 +208,7 @@ export default function UserInfoPage() {
queryKey: ["courses"],
queryFn: GetCourses,
onSuccess: (data) => {
let courses = data[1].map((course: Course) => ({
let courses = data[1].map((course: CourseType) => ({
label: course.name,
value: course.name,
}));