mirror of
https://github.com/urosran/cally.git
synced 2025-07-14 17:25:46 +00:00
Colors, fix family view, updated version
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">Kali - Family Planner</string>
|
||||
<string name="app_name">Cally - Family Planner</string>
|
||||
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
||||
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
||||
<string name="expo_system_ui_user_interface_style" translatable="false">light</string>
|
||||
|
@ -1,4 +1,4 @@
|
||||
rootProject.name = 'Kali - Family Planner'
|
||||
rootProject.name = 'Cally - Family Planner'
|
||||
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
|
4
app.json
4
app.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "Kali - Family Planner",
|
||||
"name": "Cally - Family Planner",
|
||||
"slug": "cally",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
@ -16,7 +16,7 @@
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.cally.app",
|
||||
"googleServicesFile": "./ios/GoogleService-Info.plist",
|
||||
"buildNumber": "18"
|
||||
"buildNumber": "19"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
|
@ -1,21 +1,14 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { LayoutChangeEvent, StyleSheet } from "react-native";
|
||||
import { Calendar } from "react-native-big-calendar";
|
||||
import {
|
||||
Picker,
|
||||
PickerModes,
|
||||
SegmentedControl,
|
||||
View,
|
||||
Text
|
||||
} from "react-native-ui-lib";
|
||||
import { MaterialIcons } from "@expo/vector-icons";
|
||||
import { AddEventDialog } from "@/components/pages/calendar/AddEventDialog";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import React, {useRef, useState} from "react";
|
||||
import {LayoutChangeEvent, StyleSheet} from "react-native";
|
||||
import {Calendar} from "react-native-big-calendar";
|
||||
import {Picker, PickerModes, SegmentedControl, View} from "react-native-ui-lib";
|
||||
import {MaterialIcons} from "@expo/vector-icons";
|
||||
import {AddEventDialog} from "@/components/pages/calendar/AddEventDialog";
|
||||
import HeaderTemplate from "@/components/shared/HeaderTemplate";
|
||||
import CalendarViewSwitch from "@/components/pages/calendar/CalendarViewSwitch";
|
||||
import { ManuallyAddEventModal } from "@/components/pages/calendar/ManuallyAddEventModal";
|
||||
import { CalendarEvent, useCalendarContext } from "@/contexts/CalendarContext";
|
||||
import { useSettingsContext } from "@/contexts/SettingsContext";
|
||||
import {ManuallyAddEventModal} from "@/components/pages/calendar/ManuallyAddEventModal";
|
||||
import {CalendarEvent} from "@/contexts/CalendarContext";
|
||||
import {useSettingsContext} from "@/contexts/SettingsContext";
|
||||
import EditEventDialog from "./EditEventDialog";
|
||||
import {useGetEvents} from "@/hooks/firebase/useGetEvents";
|
||||
|
||||
@ -41,7 +34,7 @@ const months = [
|
||||
];
|
||||
|
||||
export default function CalendarPage() {
|
||||
const { calendarColor } = useSettingsContext();
|
||||
const {calendarColor} = useSettingsContext();
|
||||
const [editVisible, setEditVisible] = useState<boolean>(false);
|
||||
const [eventForEdit, setEventForEdit] = useState<CalendarEvent>();
|
||||
|
||||
@ -54,7 +47,6 @@ export default function CalendarPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const { profileData } = useAuthContext();
|
||||
const [isFamilyView, setIsFamilyView] = useState<boolean>(true);
|
||||
const [calendarHeight, setCalendarHeight] = useState(0);
|
||||
const [mode, setMode] = useState<"week" | "month" | "day">("week");
|
||||
@ -64,11 +56,10 @@ export default function CalendarPage() {
|
||||
>(undefined);
|
||||
|
||||
const calendarContainerRef = useRef(null);
|
||||
// const { events, familyEvents } = useCalendarContext();
|
||||
const {data: events} = useGetEvents()
|
||||
const {data: events} = useGetEvents(isFamilyView)
|
||||
|
||||
const onLayout = (event: LayoutChangeEvent) => {
|
||||
const { height } = event.nativeEvent.layout;
|
||||
const {height} = event.nativeEvent.layout;
|
||||
setCalendarHeight(height);
|
||||
};
|
||||
|
||||
@ -80,29 +71,25 @@ export default function CalendarPage() {
|
||||
};
|
||||
|
||||
const handleMonthChange = (month: string) => {
|
||||
// Get the current day and year
|
||||
const currentDay = selectedDate.getDate();
|
||||
const currentYear = selectedDate.getFullYear();
|
||||
|
||||
// Find the new month index
|
||||
const newMonthIndex = months.indexOf(month);
|
||||
|
||||
// Create a new Date object with the selected month, preserving day and year
|
||||
const updatedDate = new Date(currentYear, newMonthIndex, currentDay);
|
||||
|
||||
// Update both selectedDate and activeDate in the Calendar component
|
||||
setSelectedDate(updatedDate);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, height: "100%", padding: 10 }}>
|
||||
<View style={{flex: 1, height: "100%", padding: 10}}>
|
||||
<HeaderTemplate
|
||||
message={"Let's get your week started!"}
|
||||
isWelcome={true}
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{ flex: 1, backgroundColor: "#fff", borderRadius: 30 }}
|
||||
style={{flex: 1, backgroundColor: "#fff", borderRadius: 30}}
|
||||
ref={calendarContainerRef}
|
||||
onLayout={onLayout}
|
||||
>
|
||||
@ -125,23 +112,23 @@ export default function CalendarPage() {
|
||||
placeholder={"Select Month"}
|
||||
mode={PickerModes.SINGLE}
|
||||
onChange={(itemValue) => handleMonthChange(itemValue as string)}
|
||||
trailingAccessory={<MaterialIcons name={"keyboard-arrow-down"} />}
|
||||
trailingAccessory={<MaterialIcons name={"keyboard-arrow-down"}/>}
|
||||
>
|
||||
{months.map((month) => (
|
||||
<Picker.Item key={month} label={month} value={month} />
|
||||
<Picker.Item key={month} label={month} value={month}/>
|
||||
))}
|
||||
</Picker>
|
||||
|
||||
<View>
|
||||
<SegmentedControl
|
||||
segments={[{ label: "D" }, { label: "W" }, { label: "M" }]}
|
||||
segments={[{label: "D"}, {label: "W"}, {label: "M"}]}
|
||||
backgroundColor="#ececec"
|
||||
inactiveColor="#919191"
|
||||
activeBackgroundColor="#ea156c"
|
||||
activeColor="white"
|
||||
outlineColor="white"
|
||||
outlineWidth={3}
|
||||
style={{ backgroundColor: "green" }}
|
||||
style={{backgroundColor: "green"}}
|
||||
segmentLabelStyle={styles.segmentslblStyle}
|
||||
onChangeIndex={handleSegmentChange}
|
||||
initialIndex={mode === "day" ? 0 : mode === "week" ? 1 : 2}
|
||||
@ -154,7 +141,7 @@ export default function CalendarPage() {
|
||||
bodyContainerStyle={styles.calHeader}
|
||||
mode={mode}
|
||||
events={isFamilyView ? events ?? [] : events ?? []}
|
||||
eventCellStyle={{ backgroundColor: isFamilyView ? '#46a80a' : calendarColor }}
|
||||
eventCellStyle={(event) => ({backgroundColor: event.eventColor})}
|
||||
onPressEvent={(event) => {
|
||||
setEditVisible(true);
|
||||
setEventForEdit(event);
|
||||
@ -166,8 +153,8 @@ export default function CalendarPage() {
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<CalendarViewSwitch viewSwitch={setIsFamilyView} />
|
||||
<AddEventDialog />
|
||||
<CalendarViewSwitch viewSwitch={setIsFamilyView}/>
|
||||
<AddEventDialog/>
|
||||
{eventForEdit && (
|
||||
<EditEventDialog
|
||||
isVisible={editVisible}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {AntDesign, Ionicons} from "@expo/vector-icons";
|
||||
import React, {useState} from "react";
|
||||
import React, {useCallback, useState} from "react";
|
||||
import {Button, Checkbox, Text, View} from "react-native-ui-lib";
|
||||
import {ScrollView, StyleSheet} from "react-native";
|
||||
import {colorMap} from "@/contexts/SettingsContext";
|
||||
@ -11,6 +11,7 @@ import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import {useUpdateUserData} from "@/hooks/firebase/useUpdateUserData";
|
||||
import {GoogleSignin} from "@react-native-google-signin/google-signin";
|
||||
import * as AuthSession from "expo-auth-session";
|
||||
import debounce from "debounce";
|
||||
|
||||
GoogleSignin.configure({
|
||||
webClientId:
|
||||
@ -40,10 +41,12 @@ const microsoftConfig = {
|
||||
const CalendarSettingsPage = (props: {
|
||||
setSelectedPage: (page: number) => void;
|
||||
}) => {
|
||||
const [selectedColor, setSelectedColor] = useState<string>(colorMap.pink);
|
||||
const [startDate, setStartDate] = useState<boolean>(true);
|
||||
const {profileData} = useAuthContext();
|
||||
|
||||
const [selectedColor, setSelectedColor] = useState<string>(profileData?.eventColor ?? colorMap.pink);
|
||||
const [previousSelectedColor, setPreviousSelectedColor] = useState<string>(profileData?.eventColor ?? colorMap.pink);
|
||||
|
||||
const {mutateAsync: createEventFromProvider} = useCreateEventFromProvider();
|
||||
const {mutateAsync: updateUserData} = useUpdateUserData();
|
||||
|
||||
@ -162,6 +165,28 @@ const CalendarSettingsPage = (props: {
|
||||
}
|
||||
};
|
||||
|
||||
const debouncedUpdateUserData = useCallback(
|
||||
debounce(async (color: string) => {
|
||||
try {
|
||||
await updateUserData({
|
||||
newUserData: {
|
||||
eventColor: color
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to update color:", error);
|
||||
setSelectedColor(previousSelectedColor)
|
||||
}
|
||||
}, 500),
|
||||
[]
|
||||
);
|
||||
|
||||
const handleChangeColor = (color: string) => {
|
||||
setPreviousSelectedColor(selectedColor)
|
||||
setSelectedColor(color);
|
||||
debouncedUpdateUserData(color);
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<View marginH-30>
|
||||
@ -179,35 +204,35 @@ const CalendarSettingsPage = (props: {
|
||||
Event Color Preference
|
||||
</Text>
|
||||
<View row spread>
|
||||
<TouchableOpacity onPress={() => setSelectedColor(colorMap.pink)}>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.pink)}>
|
||||
<View style={styles.colorBox} backgroundColor={colorMap.pink}>
|
||||
{selectedColor == colorMap.pink && (
|
||||
<AntDesign name="check" size={30} color="white"/>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setSelectedColor(colorMap.orange)}>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.orange)}>
|
||||
<View style={styles.colorBox} backgroundColor={colorMap.orange}>
|
||||
{selectedColor == colorMap.orange && (
|
||||
<AntDesign name="check" size={30} color="white"/>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setSelectedColor(colorMap.green)}>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.green)}>
|
||||
<View style={styles.colorBox} backgroundColor={colorMap.green}>
|
||||
{selectedColor == colorMap.green && (
|
||||
<AntDesign name="check" size={30} color="white"/>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setSelectedColor(colorMap.teal)}>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.teal)}>
|
||||
<View style={styles.colorBox} backgroundColor={colorMap.teal}>
|
||||
{selectedColor == colorMap.teal && (
|
||||
<AntDesign name="check" size={30} color="white"/>
|
||||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setSelectedColor(colorMap.purple)}>
|
||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.purple)}>
|
||||
<View style={styles.colorBox} backgroundColor={colorMap.purple}>
|
||||
{selectedColor == colorMap.purple && (
|
||||
<AntDesign name="check" size={30} color="white"/>
|
||||
|
@ -19,6 +19,7 @@ export interface UserProfile {
|
||||
uid?: string;
|
||||
googleToken?: string;
|
||||
microsoftToken?: string;
|
||||
eventColor?: string
|
||||
}
|
||||
|
||||
export interface ParentProfile extends UserProfile {
|
||||
|
@ -1,31 +1,43 @@
|
||||
import {useQuery} from "react-query";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import {ReactElement} from "react";
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import {ICalendarEventBase} from "react-native-big-calendar";
|
||||
import {colorMap} from "@/contexts/SettingsContext";
|
||||
|
||||
export const useGetEvents = () => {
|
||||
const {user} = useAuthContext()
|
||||
export const useGetEvents = (isFamilyView: boolean) => {
|
||||
const { user, profileData } = useAuthContext();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ["events", user?.uid],
|
||||
queryKey: ["events", user?.uid, isFamilyView],
|
||||
queryFn: async () => {
|
||||
const snapshot = await firestore()
|
||||
const eventsQuery = firestore()
|
||||
.collection("Events")
|
||||
.where("creatorId", "==", user?.uid)
|
||||
.where("creatorId", "==", user?.uid);
|
||||
|
||||
if (isFamilyView) {
|
||||
eventsQuery.where("familyID", "==", profileData?.familyId);
|
||||
}
|
||||
|
||||
const snapshot = await eventsQuery.get();
|
||||
|
||||
return await Promise.all(snapshot.docs.map(async (doc) => {
|
||||
const data = doc.data();
|
||||
|
||||
const profileSnapshot = await firestore()
|
||||
.collection("Profiles")
|
||||
.doc(data.creatorId)
|
||||
.get();
|
||||
|
||||
const events: ICalendarEventBase[] = snapshot.docs.map((doc) => {
|
||||
const data = doc.data();
|
||||
const profileData = profileSnapshot.data();
|
||||
const eventColor: string = profileData?.eventColor || colorMap.pink // Default color if not found
|
||||
|
||||
return {
|
||||
title: data.title,
|
||||
start: new Date(data.startDate.seconds * 1000),
|
||||
end: new Date(data.endDate.seconds * 1000),
|
||||
hideHours: data.allDay,
|
||||
eventColor: eventColor,
|
||||
};
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
return events;
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ import {UserProfile} from "@/hooks/firebase/types/profileTypes";
|
||||
import {FirebaseAuthTypes} from "@react-native-firebase/auth";
|
||||
|
||||
export const useUpdateUserData = () => {
|
||||
const {user: currentUser, setProfileData, refreshProfileData} = useAuthContext();
|
||||
const {user: currentUser, refreshProfileData} = useAuthContext();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ["updateUserData"],
|
||||
|
@ -437,7 +437,7 @@
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cally.app;
|
||||
PRODUCT_NAME = "KaliFamilyPlanner";
|
||||
PRODUCT_NAME = "CallyFamilyPlanner";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@ -468,7 +468,7 @@
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cally.app;
|
||||
PRODUCT_NAME = "KaliFamilyPlanner";
|
||||
PRODUCT_NAME = "CallyFamilyPlanner";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
@ -7,7 +7,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Kali - Family Planner</string>
|
||||
<string>Cally - Family Planner</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@ -45,7 +45,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>18</string>
|
||||
<string>19</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
@ -81,6 +81,7 @@
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>SplashScreen</string>
|
||||
|
@ -39,6 +39,7 @@
|
||||
"@react-navigation/drawer": "^6.7.2",
|
||||
"@react-navigation/native": "^6.0.2",
|
||||
"date-fns": "^3.6.0",
|
||||
"debounce": "^2.1.1",
|
||||
"expo": "~51.0.24",
|
||||
"expo-auth-session": "^5.5.2",
|
||||
"expo-barcode-scanner": "~13.0.1",
|
||||
|
Reference in New Issue
Block a user