Skip to content

Commit

Permalink
Request a Concert and Dance Club forms (#77)
Browse files Browse the repository at this point in the history
* add time slot component

* adjust validation (TODO: maximum start time (5 pm))

* add MultiSelect component

* make slot component compatible with question state

* add on layout and make slots work with state and not state.value

* fix styling, add questions.js

* add questions for all forms, refractor them into index.js, and add request concert form screen navigate (todo: fix cannot read property map of undefined when request concert button pressed)

* Add support for Request Concert and Dance Club. Note that as of right now they are in the volunteer forms spreadsheet, not yet a button in other opportunities

* Fix Bugs

* Make 4 favorite music pieces question in dance club form a list of 4 input boxes. Bugs: validation (only for this form, probably this specific question), margin 20 instead of 0

* make submit forms concise

* merge more

* add request concert and dance club functionality to other opportunities

* fix checkboxquery, fixing favoritePieces question in dance form attempt 1

* 'bout to do pr

* styling

* do requested changes

* formatting

* fix MultipleChoice component showing indices only, now shows actual content (performanceType dynamic changing still works)

* ```npm run format```-ing

* Refactor forms into files & fix multiple bugs

- Fix circular dependency errors
- Fix LMH/MBT time limit validation
- Align with OOP by refactoring common methods into the base Form class

* Clean up (minor readability improvements)

- Remove unused imports
- Organize imports
- Add required indicator to the RequestConcert time slot
- Rename Slot -> TimeSlotList to prevent ambiguity

---------

Co-authored-by: TenType <55125103+TenType@users.noreply.github.com>
  • Loading branch information
Pramad712 and TenType authored Sep 11, 2024
1 parent 4bb2939 commit 7e37908
Show file tree
Hide file tree
Showing 35 changed files with 1,627 additions and 572 deletions.
17 changes: 9 additions & 8 deletions App.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import "@expo/metro-runtime";
import { useState, useEffect } from "react";
import { ActivityIndicator } from "react-native";
import { StatusBar } from "expo-status-bar";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { StatusBar } from "expo-status-bar";
import { useEffect, useState } from "react";
import { ActivityIndicator } from "react-native";

import colors from "./src/constants/colors";
import HomeScreen from "./src/screens/HomeScreen";
import AccountScreen from "./src/screens/AccountScreen";
import EmbeddedFormScreen from "./src/screens/EmbeddedFormScreen";
import EndScreen from "./src/screens/EndScreen";
import HomeScreen from "./src/screens/HomeScreen";
import SignInScreen from "./src/screens/SignInScreen";
import VolunteerFormScreen from "./src/screens/VolunteerFormScreen";
import EmbeddedFormScreen from "./src/screens/EmbeddedFormScreen";
import VolunteerOpportunityScreen from "./src/screens/VolunteerOpportunityScreen";
import EndScreen from "./src/screens/EndScreen";

import HomeHeader from "./src/components/HomeHeader";
import colors from "./src/constants/colors";
import { alertError } from "./src/utils";

const Stack = createNativeStackNavigator();
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"react": "18.2.0",
"react-native": "0.74.5",
"react-native-animated-dots-carousel": "^1.0.2",
"react-native-date-picker": "^5.0.4",
"react-native-document-picker": "^9.3.0",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.16.1",
Expand Down
5 changes: 3 additions & 2 deletions src/components/CarouselPage.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useState } from "react";
import { Alert, Pressable, StyleSheet, View, Dimensions } from "react-native";
import { Alert, Dimensions, Pressable, StyleSheet, View } from "react-native";
import AnimatedDotsCarousel from "react-native-animated-dots-carousel";
import VolunteerOpportunity from "./VolunteerOpportunity";
import Carousel from "react-native-reanimated-carousel";

import Heading from "./Heading";
import RefreshButton from "./RefreshButton";
import VolunteerOpportunity from "./VolunteerOpportunity";

export default function CarouselPage({ navigation, data, onRefresh }) {
const [dotIndex, setDotIndex] = useState(0);
Expand Down
23 changes: 13 additions & 10 deletions src/components/CheckBoxQuery.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StyleSheet, Text, View } from "react-native";
import { Checkbox } from "expo-checkbox";
import { StyleSheet, Text, View } from "react-native";

import colors from "../constants/colors";

export default function CheckBoxQuery({ question, state, setState }) {
Expand All @@ -13,18 +14,23 @@ export default function CheckBoxQuery({ question, state, setState }) {
}));
}}
>
<Text style={styles.header}>
<Text
style={[
styles.header,
{ color: state.valid ? "black" : colors.danger },
]}
>
{question}
<Text style={{ color: "red" }}>{" *"}</Text>
</Text>
<View style={styles.checkBoxContainer}>
<Checkbox
color={"#0d79ff"}
value={state.value == true}
value={state.value == "Yes"}
onValueChange={() => {
setState((prevState) => ({
...prevState,
value: true,
value: "Yes",
}));
}}
style={{ borderRadius: 20, transform: [{ scale: 1.3 }] }}
Expand All @@ -40,11 +46,11 @@ export default function CheckBoxQuery({ question, state, setState }) {
<Text> </Text>
<Checkbox
color={"#0d79ff"}
value={state.value == false}
value={state.value == "No"}
onValueChange={() => {
setState((prevState) => ({
...prevState,
value: false,
value: "No",
}));
}}
style={{ borderRadius: 20, transform: [{ scale: 1.3 }] }}
Expand All @@ -66,13 +72,10 @@ const styles = StyleSheet.create({
container: {
flexGrow: 1,
marginBottom: 25,
justifyContent: "center",
alignItems: "center",
alignSelf: "center",
alignSelf: "flex-start",
},
checkBoxContainer: {
flexDirection: "row",
alignItems: "center",
paddingTop: 15,
},
text: {
Expand Down
2 changes: 1 addition & 1 deletion src/components/FullWidthButton.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { StyleSheet, Text, Pressable } from "react-native";
import { Pressable, StyleSheet, Text } from "react-native";

export default function FullWidthButton({
buttonStyle,
Expand Down
4 changes: 2 additions & 2 deletions src/components/Heading.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { StyleSheet, Text } from "react-native";

export default function Heading({ children }) {
return <Text style={styles.heading}>{children}</Text>;
return <Text style={styles.container}>{children}</Text>;
}

const styles = StyleSheet.create({
heading: {
container: {
fontSize: 18,
fontWeight: "bold",
marginBottom: 5,
Expand Down
10 changes: 5 additions & 5 deletions src/components/HomeHeader.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useState, useEffect } from "react";
import { LinearGradient } from "expo-linear-gradient";
import { useEffect, useState } from "react";
import {
ActivityIndicator,
Image,
Text,
StyleSheet,
Pressable,
SafeAreaView,
ActivityIndicator,
StyleSheet,
Text,
} from "react-native";
import { LinearGradient } from "expo-linear-gradient";

import colors from "../constants/colors";
import { getUser } from "../utils";
Expand Down
77 changes: 77 additions & 0 deletions src/components/MultiSelect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";
import { useState } from "react";
import { Pressable, StyleSheet, Text, View } from "react-native";

export default function MultiSelect({ state, setState, title, options }) {
const [selected, setSelected] = useState(
new Array(options.length).fill(false),
);

return (
<View
onLayout={(event) => {
setState((prevState) => ({
...prevState,
y: event.nativeEvent.layout.y,
}));
}}
style={styles.container}
>
<Text style={[styles.title, { color: state.valid ? "black" : "red" }]}>
{title}
</Text>
{options.map((option, index) => (
<Pressable
key={index * 4}
onPress={() => {
setState((previous) => {
const newValue = selected[index]
? previous.value.filter((item) => item !== option)
: [...previous.value, option];
return { ...previous, value: newValue };
});

setSelected((previous) => {
const next = [...previous]; // Create a new copy of the array
next[index] = !previous[index];
return next;
});
}}
>
<View key={index * 4 + 1} style={{ flexDirection: "row" }}>
<MaterialCommunityIcons
key={index * 4 + 2}
name={
selected[index] ? "checkbox-marked" : "checkbox-blank-outline"
}
size={24}
color={selected[index] ? "blue" : "black"}
/>
<Text key={index * 4 + 3} style={styles.optionText}>
{option}
</Text>
</View>
</Pressable>
))}
</View>
);
}

const styles = StyleSheet.create({
container: {
marginBottom: 20,
},

title: {
fontSize: 18,
fontWeight: "600",
marginBottom: 10,
flexWrap: "wrap",
},

optionText: {
fontSize: 16,
marginLeft: 10,
flexWrap: "wrap",
},
});
26 changes: 9 additions & 17 deletions src/components/MultipleChoice.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { View, Text, Pressable, StyleSheet } from "react-native";
import { Pressable, StyleSheet, Text, View } from "react-native";
import colors from "../constants/colors";

export default function MultipleChoice({
Expand All @@ -18,28 +18,28 @@ export default function MultipleChoice({
}));
}}
>
<Text style={styles.label}>
<Text style={styles.title}>
<Text style={{ color: state.valid ? "black" : colors.danger }}>
{title}
</Text>
<Text style={{ color: "red" }}> *</Text>
</Text>
{mapObject(options, (key) => (
{options.map((value) => (
<Pressable
key={key}
key={value}
style={styles.option}
onPress={() => onSelect(key)}
onPress={() => onSelect(value)}
>
<View style={styles.radioCircle}>
{state.value === key && <View style={styles.selectedRb} />}
{state.value === value && <View style={styles.selectedRb} />}
</View>
<Text
style={[
styles.optionText,
state.value === key && styles.selectedText,
state.value === value && styles.selectedText,
]}
>
{key}
{value}
</Text>
</Pressable>
))}
Expand All @@ -48,7 +48,7 @@ export default function MultipleChoice({
}

const styles = StyleSheet.create({
label: {
title: {
fontSize: 18,
fontWeight: "600",
marginBottom: 10,
Expand Down Expand Up @@ -83,11 +83,3 @@ const styles = StyleSheet.create({
fontWeight: "condensedBold",
},
});

function mapObject(obj, callback) {
const items = [];
for (const key in obj) {
items.push(callback(key));
}
return items;
}
6 changes: 3 additions & 3 deletions src/components/NextButton.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { StyleSheet, Text, View, Image } from "react-native";
import Feather from "@expo/vector-icons/Feather";
import { StyleSheet, Text, View } from "react-native";

export default function NextButton() {
return (
<View style={styles.back}>
<View style={styles.container}>
<Text style={styles.nextText}>{"Next"}</Text>
<Feather name="chevron-right" size={32} color="white" />
</View>
);
}

const styles = StyleSheet.create({
back: {
container: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
Expand Down
Loading

0 comments on commit 7e37908

Please sign in to comment.