added confirmation dialogs, fixed scroll wheels ui tweaks

This commit is contained in:
ivic00
2024-10-30 00:02:25 +01:00
parent 74d82e2029
commit 7f79a1c819
14 changed files with 1077 additions and 654 deletions

View File

@ -26,6 +26,7 @@ import NavSettingsIcon from "@/assets/svgs/NavSettingsIcon";
import { useAtom } from "jotai";
import {
settingsPageIndex,
toDosPageIndex,
userSettingsView,
} from "@/components/pages/calendar/atoms";
@ -33,6 +34,7 @@ export default function TabLayout() {
const { mutateAsync: signOut } = useSignOut();
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex);
const [userView, setUserView] = useAtom(userSettingsView);
const [toDosIndex, setToDosIndex] = useAtom(toDosPageIndex);
return (
<Drawer
@ -76,6 +78,7 @@ export default function TabLayout() {
pressFunc={() => {
props.navigation.navigate("calendar");
setPageIndex(0);
setToDosIndex(0);
setUserView(true);
}}
icon={<NavCalendarIcon />}
@ -87,6 +90,7 @@ export default function TabLayout() {
pressFunc={() => {
props.navigation.navigate("grocery");
setPageIndex(0);
setToDosIndex(0);
setUserView(true);
}}
icon={<NavGroceryIcon />}
@ -113,6 +117,7 @@ export default function TabLayout() {
pressFunc={() => {
props.navigation.navigate("todos");
setPageIndex(0);
setToDosIndex(0);
setUserView(true);
}}
icon={<NavToDosIcon />}
@ -124,6 +129,7 @@ export default function TabLayout() {
pressFunc={() => {
props.navigation.navigate("brain_dump");
setPageIndex(0);
setToDosIndex(0);
setUserView(true);
}}
icon={<NavBrainDumpIcon />}
@ -135,6 +141,7 @@ export default function TabLayout() {
onPress={() => {
props.navigation.navigate("settings");
setPageIndex(0);
setToDosIndex(0);
setUserView(true);
}}
label={"Manage Settings"}

View File

@ -3,8 +3,8 @@ import Svg, { Path, LinearGradient, Stop, SvgProps } from "react-native-svg";
const OutlookIcon: React.FC<SvgProps> = (props) => (
<Svg
width={34}
height={34}
width={props.width || 34}
height={props.height || 34}
viewBox="0 0 48 48"
{...props}
>

View File

@ -0,0 +1,82 @@
import React from "react";
import { Dialog, Button, Text, View } from "react-native-ui-lib";
import { StyleSheet } from "react-native";
interface BrainDumpDialogProps {
visible: boolean;
title: string;
onDismiss: () => void;
onConfirm: () => void;
}
const BrainDumpDialog: React.FC<BrainDumpDialogProps> = ({
visible,
title,
onDismiss,
onConfirm,
}) => {
return (
<Dialog
visible={visible}
onDismiss={onDismiss}
containerStyle={styles.dialog}
>
<Text center style={styles.title}>
Delete Note
</Text>
<View center>
<Text style={styles.text} center>
Are you sure you want to delete the {"\n"}
<Text style={{ fontSize: 16, fontFamily: "PlusJakartaSans_700Bold" }}>
{title}
</Text>{" "}
Note?
</Text>
</View>
<View row right gap-8>
<Button
label="Cancel"
onPress={onDismiss}
style={styles.cancelBtn}
color="#999999"
labelStyle={{ fontFamily: "Poppins_500Medium", fontSize: 13.53 }}
/>
<Button
label="Yes"
onPress={onConfirm}
style={styles.confirmBtn}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium" }}
/>
</View>
</Dialog>
);
};
// Empty stylesheet for future styles
const styles = StyleSheet.create({
confirmBtn: {
backgroundColor: "#ea156d",
},
cancelBtn: {
backgroundColor: "white",
},
dialog: {
backgroundColor: "white",
paddingHorizontal: 25,
paddingTop: 35,
paddingBottom: 17,
borderRadius: 20,
},
title: {
fontFamily: "Manrope_600SemiBold",
fontSize: 22,
marginBottom: 20,
},
text: {
fontFamily: "PlusJakartaSans_400Regular",
fontSize: 16,
marginBottom: 25,
},
});
export default BrainDumpDialog;

View File

@ -18,6 +18,7 @@ import NavCalendarIcon from "@/assets/svgs/NavCalendarIcon";
import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
import RemindersIcon from "@/assets/svgs/RemindersIcon";
import MenuIcon from "@/assets/svgs/MenuIcon";
import BrainDumpDialog from "./BrainDumpDialog";
const MoveBrainDump = (props: {
item: IBrainDump;
@ -28,12 +29,26 @@ const MoveBrainDump = (props: {
const [description, setDescription] = useState<string>(
props.item.description
);
const [modalVisible, setModalVisible] = useState<boolean>(false);
const { width } = Dimensions.get("screen");
useEffect(() => {
updateBrainDumpItem(props.item.id, { description: description });
}, [description]);
const showConfirmationDialog = () => {
setModalVisible(true);
};
const handleDeleteNote = () =>{
deleteBrainDump(props.item.id);
}
const hideConfirmationDialog = () => {
setModalVisible(false);
}
return (
<Dialog
bottom={true}
@ -81,8 +96,7 @@ const MoveBrainDump = (props: {
marginL-5
iconSource={() => <BinIcon />}
onPress={() => {
deleteBrainDump(props.item.id);
props.setIsVisible(false);
showConfirmationDialog();
}}
/>
</View>
@ -145,6 +159,7 @@ const MoveBrainDump = (props: {
</View>
</TouchableOpacity>
</View>
<BrainDumpDialog visible={modalVisible} title={props.item.title} onDismiss={hideConfirmationDialog} onConfirm={handleDeleteNote} />
</Dialog>
);
};
@ -191,10 +206,10 @@ const styles = StyleSheet.create({
fontSize: 22,
fontFamily: "Manrope_500Medium",
},
description:{
description: {
fontFamily: "Manrope_400Regular",
fontSize: 14,
}
},
});
export default MoveBrainDump;

View File

@ -0,0 +1,81 @@
import React from "react";
import { Dialog, Button, Text, View } from "react-native-ui-lib";
import { StyleSheet } from "react-native";
interface DeleteEventDialogProps {
visible: boolean;
title: string;
onDismiss: () => void;
onConfirm: () => void;
}
const DeleteEventDialog: React.FC<DeleteEventDialogProps> = ({
visible,
title,
onDismiss,
onConfirm,
}) => {
return (
<Dialog
visible={visible}
onDismiss={onDismiss}
containerStyle={styles.dialog}
>
<Text center style={styles.title}>
Delete Event
</Text>
<View center>
<Text style={styles.text} center>
Are you sure you want to delete the event:{" "}
<Text style={{ fontSize: 16, fontFamily: "PlusJakartaSans_700Bold" }}>
{title}
</Text>{" "}
</Text>
</View>
<View row right gap-8>
<Button
label="Cancel"
onPress={onDismiss}
style={styles.cancelBtn}
color="#999999"
labelStyle={{ fontFamily: "Poppins_500Medium", fontSize: 13.53 }}
/>
<Button
label="Yes"
onPress={onConfirm}
style={styles.confirmBtn}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium" }}
/>
</View>
</Dialog>
);
};
// Empty stylesheet for future styles
const styles = StyleSheet.create({
confirmBtn: {
backgroundColor: "#ea156d",
},
cancelBtn: {
backgroundColor: "white",
},
dialog: {
backgroundColor: "white",
paddingHorizontal: 25,
paddingTop: 35,
paddingBottom: 17,
borderRadius: 20,
},
title: {
fontFamily: "Manrope_600SemiBold",
fontSize: 22,
marginBottom: 20,
},
text: {
fontFamily: "PlusJakartaSans_400Regular",
fontSize: 16,
marginBottom: 25,
},
});
export default DeleteEventDialog;

View File

@ -207,7 +207,7 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
scrollOffsetMinutes={offsetMinutes}
theme={{
palette: {
nowIndicator: "#fd1575",
nowIndicator: profileData?.eventColor || "#fd1575",
gray: {
"100": "#e8eaed",
"200": "#e8eaed",
@ -223,13 +223,15 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
fontSize: 16,
},
moreLabel: {},
xs:{fontSize: 10}
xs: { fontSize: 10 },
},
}}
dayHeaderStyle={dateStyle}
dayHeaderHighlightColor={"white"}
renderCustomDateForMonth={renderCustomDateForMonth}
showAdjacentMonths
hourStyle={styles.hourStyle}
ampm
/>
);
}
@ -273,4 +275,9 @@ const styles = StyleSheet.create({
alignItems: "center",
justifyContent: "center",
},
hourStyle: {
color: "#5f6368",
fontSize: 12,
fontFamily: "Manrope_500Medium",
},
});

File diff suppressed because it is too large Load Diff

View File

@ -9,3 +9,4 @@ export const selectedDateAtom = atom<Date>(new Date());
export const selectedNewEventDateAtom = atom<Date | undefined>(undefined);
export const settingsPageIndex = atom<number>(0);
export const userSettingsView = atom<boolean>(true);
export const toDosPageIndex = atom<number>(0);

View File

@ -14,7 +14,7 @@ const AddGroceryItem = () => {
paddingH-25
style={{
position: "absolute",
bottom: 20,
bottom: 65,
width: "100%",
height: 60,
}}

View File

@ -1,38 +1,42 @@
import {ScrollView} from "react-native";
import {View} from "react-native-ui-lib";
import React, {useEffect, useRef} from "react";
import { Dimensions, ScrollView } from "react-native";
import { View } from "react-native-ui-lib";
import React, { useEffect, useRef } from "react";
import AddGroceryItem from "./AddGroceryItem";
import GroceryList from "./GroceryList";
import {useGroceryContext} from "@/contexts/GroceryContext";
import { useGroceryContext } from "@/contexts/GroceryContext";
const GroceryWrapper = () => {
const {isAddingGrocery} = useGroceryContext();
const scrollViewRef = useRef<ScrollView>(null); // Reference to the ScrollView
const { isAddingGrocery } = useGroceryContext();
const scrollViewRef = useRef<ScrollView>(null); // Reference to the ScrollView
useEffect(() => {
if (isAddingGrocery && scrollViewRef.current) {
scrollViewRef.current.scrollTo({
y: 400, // Adjust this value to scroll a bit down (100 is an example)
animated: true,
});
}
}, [isAddingGrocery]);
useEffect(() => {
if (isAddingGrocery && scrollViewRef.current) {
scrollViewRef.current.scrollTo({
y: 400, // Adjust this value to scroll a bit down (100 is an example)
animated: true,
});
}
}, [isAddingGrocery]);
return (
<View height={"100%"} paddingT-15 paddingH-15>
<View height={"100%"}>
<ScrollView
ref={scrollViewRef}
automaticallyAdjustKeyboardInsets={true}
>
<View marginB-70>
<GroceryList/>
</View>
</ScrollView>
{!isAddingGrocery && <AddGroceryItem/>}
return (
<View height={Dimensions.get("window").height}>
<View>
<ScrollView
ref={scrollViewRef}
automaticallyAdjustKeyboardInsets={true}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
>
<View height={"100%"}>
<View marginB-115>
<GroceryList />
</View>
</View>
);
</View>
</ScrollView>
</View>
{!isAddingGrocery && <AddGroceryItem />}
</View>
);
};
export default GroceryWrapper;

View File

@ -1,7 +1,7 @@
import { AntDesign, Ionicons } from "@expo/vector-icons";
import React, { useCallback, useEffect, useState } from "react";
import { Button, Checkbox, Text, View } from "react-native-ui-lib";
import { ActivityIndicator, ScrollView, StyleSheet } from "react-native";
import { ActivityIndicator, Alert, ScrollView, StyleSheet } from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
import { useAuthContext } from "@/contexts/AuthContext";
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
@ -21,6 +21,7 @@ import ExpoLocalization from "expo-localization/src/ExpoLocalization";
import { colorMap } from "@/constants/colorMap";
import { useAtom } from "jotai";
import { settingsPageIndex } from "../calendar/atoms";
import CalendarSettingsDialog from "./calendar_components/CalendarSettingsDialog";
const googleConfig = {
androidClientId:
@ -61,6 +62,29 @@ const CalendarSettingsPage = () => {
? "Mondays"
: "Sundays"
);
const [isModalVisible, setModalVisible] = useState<boolean>(false);
const [selectedService, setSelectedService] = useState<
"google" | "outlook" | "apple"
>("google");
const [selectedEmail, setSelectedEmail] = useState<string>("");
const showConfirmationDialog = (
serviceName: "google" | "outlook" | "apple",
email: string
) => {
setSelectedService(serviceName);
setSelectedEmail(email);
setModalVisible(true);
};
const handleConfirm = () => {
clearToken(selectedService, selectedEmail);
setModalVisible(false);
};
const handleCancel = () => {
setModalVisible(false);
};
const [selectedColor, setSelectedColor] = useState<string>(
profileData?.eventColor ?? colorMap.pink
@ -477,7 +501,9 @@ const CalendarSettingsPage = () => {
googleToken && (
<Button
key={googleMail}
onPress={() => clearToken("google", googleMail)}
onPress={() => {
showConfirmationDialog("google", googleMail);
}}
label={`Disconnect ${googleMail}`}
labelStyle={styles.addCalLbl}
labelProps={{
@ -520,7 +546,7 @@ const CalendarSettingsPage = () => {
appleToken && (
<Button
key={appleEmail}
onPress={() => clearToken("apple", appleEmail)}
onPress={() => showConfirmationDialog("apple", appleEmail)}
label={`Disconnect ${appleEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{
@ -565,7 +591,9 @@ const CalendarSettingsPage = () => {
microsoftToken && (
<Button
key={microsoftEmail}
onPress={() => clearToken("outlook", microsoftEmail)}
onPress={() => {
showConfirmationDialog("outlook", microsoftEmail);
}}
label={`Disconnect ${microsoftEmail}`}
labelStyle={styles.addCalLbl}
labelProps={{
@ -754,6 +782,13 @@ const CalendarSettingsPage = () => {
</>
)}
</View>
<CalendarSettingsDialog
visible={isModalVisible}
serviceName={selectedService}
email={selectedEmail}
onDismiss={handleCancel}
onConfirm={handleConfirm}
/>
</ScrollView>
);
};

View File

@ -0,0 +1,86 @@
import React from "react";
import { Dialog, Button, Text, View } from "react-native-ui-lib";
import { StyleSheet } from "react-native";
interface ConfirmationDialogProps {
visible: boolean;
serviceName: "google" | "outlook" | "apple";
email: string;
onDismiss: () => void;
onConfirm: () => void;
}
const CalendarSettingsDialog: React.FC<ConfirmationDialogProps> = ({
visible,
serviceName,
email,
onDismiss,
onConfirm,
}) => {
return (
<Dialog
visible={visible}
onDismiss={onDismiss}
containerStyle={styles.dialog}
>
<Text center style={styles.title}>
Disconnect {serviceName}
</Text>
<View center>
<Text style={styles.text} center>
Are you sure you want to disconnect this {"\n"}
<Text style={{ fontSize: 16, fontFamily: "PlusJakartaSans_700Bold" }}>
{serviceName}
</Text>{" "}
calendar
{"\n"}
for {email}?
</Text>
</View>
<View row right gap-8>
<Button
label="Cancel"
onPress={onDismiss}
style={styles.cancelBtn}
color="#999999"
labelStyle={{ fontFamily: "Poppins_500Medium", fontSize: 13.53 }}
/>
<Button
label="Yes"
onPress={onConfirm}
style={styles.confirmBtn}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium" }}
/>
</View>
</Dialog>
);
};
// Empty stylesheet for future styles
const styles = StyleSheet.create({
confirmBtn: {
backgroundColor: "#ea156d",
},
cancelBtn: {
backgroundColor: "white",
},
dialog: {
backgroundColor: "white",
paddingHorizontal: 25,
paddingTop: 35,
paddingBottom: 17,
borderRadius: 20,
},
title: {
fontFamily: "Manrope_600SemiBold",
fontSize: 22,
marginBottom: 20,
},
text: {
fontFamily: "PlusJakartaSans_400Regular",
fontSize: 16,
marginBottom: 25,
},
});
export default CalendarSettingsDialog;

View File

@ -12,11 +12,11 @@ import { useToDosContext } from "@/contexts/ToDosContext";
import { Ionicons } from "@expo/vector-icons";
import PointsSlider from "@/components/shared/PointsSlider";
import { IToDo } from "@/hooks/firebase/types/todoData";
import { ImageBackground } from "react-native";
import { ImageBackground, StyleSheet } from "react-native";
import AddChoreDialog from "@/components/pages/todos/AddChoreDialog";
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import RepeatIcon from "@/assets/svgs/RepeatIcon";
import {ProfileType, useAuthContext} from "@/contexts/AuthContext";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
const ToDoItem = (props: { item: IToDo; isSettings?: boolean }) => {
const { updateToDo } = useToDosContext();
@ -48,9 +48,9 @@ const ToDoItem = (props: { item: IToDo; isSettings?: boolean }) => {
let isTodoEditable;
if (isParent) {
isTodoEditable = true
isTodoEditable = true;
} else {
isTodoEditable = props.item.creatorId === profileData?.uid;
isTodoEditable = props.item.creatorId === profileData?.uid;
}
return (
@ -81,20 +81,16 @@ const ToDoItem = (props: { item: IToDo; isSettings?: boolean }) => {
fontSize: 15,
}}
onPress={() => {
isTodoEditable ? setVisible(true) : null
isTodoEditable ? setVisible(true) : null;
}}
>
{props.item.title}
</Text>
<Checkbox
value={props.item.done}
containerStyle={{
borderWidth: 0.7,
borderRadius: 50,
borderColor: "gray",
height: 24.64,
width: 24.64,
}}
containerStyle={[styles.checkbox, { borderRadius: 50 }]}
style={styles.checked}
borderRadius={50}
color="#fd1575"
onValueChange={(value) => {
updateToDo({ id: props.item.id, done: !props.item.done });
@ -258,3 +254,17 @@ const ToDoItem = (props: { item: IToDo; isSettings?: boolean }) => {
};
export default ToDoItem;
const styles = StyleSheet.create({
checkbox: {
borderRadius: 50,
borderWidth: 0.7,
color: "#bfbfbf",
borderColor: "#bfbfbf",
width: 24.64,
aspectRatio: 1,
},
checked: {
borderRadius: 50,
},
});

View File

@ -1,81 +1,90 @@
import {Button, Text, View} from "react-native-ui-lib";
import React, {useState} from "react";
import { Button, Text, View } from "react-native-ui-lib";
import React, { useState } from "react";
import HeaderTemplate from "@/components/shared/HeaderTemplate";
import AddChore from "./AddChore";
import ProgressCard from "./ProgressCard";
import ToDosList from "./ToDosList";
import {Dimensions, ScrollView, StyleSheet} from "react-native";
import {TouchableOpacity} from "react-native-gesture-handler";
import {ProfileType, useAuthContext} from "@/contexts/AuthContext";
import { Dimensions, ScrollView, StyleSheet } from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import FamilyChoresProgress from "./family-chores/FamilyChoresProgress";
import UserChoresProgress from "./user-chores/UserChoresProgress";
import { useAtom } from "jotai";
import { toDosPageIndex } from "../calendar/atoms";
const ToDosPage = () => {
const [pageIndex, setPageIndex] = useState<number>(0);
const {profileData} = useAuthContext();
const {width, height} = Dimensions.get("screen");
const pageLink = (
<TouchableOpacity onPress={() => setPageIndex(1)}>
<Text color="#ea156d" style={{fontSize: 14}}>
View family progress
</Text>
</TouchableOpacity>
);
return (
<>
<View paddingH-25 backgroundColor="#f9f8f7" height={"100%"} width={width}>
{pageIndex == 0 && (
<View>
<ScrollView
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
const { profileData } = useAuthContext();
const [pageIndex, setPageIndex] = useAtom(toDosPageIndex);
const { width, height } = Dimensions.get("screen");
const pageLink = (
<TouchableOpacity onPress={() => setPageIndex(1)}>
<Text color="#ea156d" style={{ fontSize: 14 }}>
View family progress
</Text>
</TouchableOpacity>
);
return (
<>
<ScrollView
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
>
<View
paddingH-25
backgroundColor="#f9f8f7"
height={"100%"}
width={width}
>
{pageIndex == 0 && (
<View>
<View>
<HeaderTemplate
message="Here are your To Do's"
isWelcome={true}
link={profileData?.userType == ProfileType.PARENT && pageLink}
/>
{profileData?.userType == ProfileType.CHILD && (
<View marginB-25>
<ProgressCard
children={
<Button
backgroundColor="transparent"
onPress={() => setPageIndex(2)}
>
<View>
<HeaderTemplate
message="Here are your To Do's"
isWelcome={true}
link={profileData?.userType == ProfileType.PARENT && pageLink}
/>
{profileData?.userType == ProfileType.CHILD && (
<View marginB-25>
<ProgressCard
children={
<Button
backgroundColor="transparent"
onPress={() => setPageIndex(2)}
>
<Text
style={{
textDecorationLine: "underline",
color: "#05a8b6",
}}
>
View your full progress report here
</Text>
</Button>
}
/>
</View>
)}
<ToDosList/>
</View>
</ScrollView>
</View>
<Text
style={{
textDecorationLine: "underline",
color: "#05a8b6",
}}
>
View your full progress report here
</Text>
</Button>
}
/>
</View>
)}
{pageIndex == 1 && <FamilyChoresProgress setPageIndex={setPageIndex}/>}
{pageIndex == 2 && <UserChoresProgress setPageIndex={setPageIndex}/>}
<ToDosList />
</View>
</View>
<AddChore/>
</>
)
;
)}
{pageIndex == 1 && (
<FamilyChoresProgress setPageIndex={setPageIndex} />
)}
{pageIndex == 2 && <UserChoresProgress setPageIndex={setPageIndex} />}
</View>
</ScrollView>
<AddChore />
</>
);
};
const styles = StyleSheet.create({
linkBtn: {
backgroundColor: "transparent",
padding: 0,
},
linkBtn: {
backgroundColor: "transparent",
padding: 0,
},
});
export default ToDosPage;