diff --git a/app.config.js b/app.config.js index 360efd9..cb13efd 100644 --- a/app.config.js +++ b/app.config.js @@ -6,6 +6,7 @@ export default { "orientation": "portrait", "icon": "./assets/images/icon.png", "scheme": "cosmos", + "deepLinking": true, "userInterfaceStyle": "automatic", "newArchEnabled": true, "ios": { diff --git a/app/(tabs)/agenda/agendaView.tsx b/app/(tabs)/agenda/agendaView.tsx index ed347ca..3bda7bd 100644 --- a/app/(tabs)/agenda/agendaView.tsx +++ b/app/(tabs)/agenda/agendaView.tsx @@ -1,10 +1,11 @@ -import { Ionicons } from '@expo/vector-icons'; -import { useState } from 'react'; -import { Modal, Pressable, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; -import { SafeAreaView } from 'react-native-safe-area-context'; import { AddTaskToAgenda } from '@/components/addTaskToAgenda'; import { ConfigAgenda } from '@/components/configAgenda'; +import { PublicTaskItem } from '@/components/publicAgendaItem'; +import { Ionicons } from '@expo/vector-icons'; +import { useEffect, useState } from 'react'; +import { FlatList, Modal, Pressable, StyleSheet, Text, View } from 'react-native'; import { FAB } from 'react-native-paper'; +import { SafeAreaView } from 'react-native-safe-area-context'; type Props = { data: { @@ -17,10 +18,43 @@ type Props = { handleClose: () => void }; +type Task = { + name_task: string +} + export default function ViewAgenda({ data, handleClose }: Props) { const [configVisible, setConfigVisible] = useState(false); const [addTaskVisible, setAddTaskVisible] = useState(false); + const [arrayAgendaTasks, setArrayAgendaTasks] = useState([]) + + const chave = encodeURIComponent(process.env.EXPO_PUBLIC_API_KEY ?? ''); + + const loadTasks = async (): Promise => { + const url = `${process.env.EXPO_PUBLIC_API_URL}/docs/getAllTarefasFromOneAgenda?uid_da_agenda=${data.uid_da_agenda}&api_key=${chave}` + + try { + const response = await fetch(url); + if (!response.ok) { + const text = response.text(); + console.log(`${response.status} - ${text}`); + return []; + } + const data: Task[] = await response.json() + return data; + } catch (err) { + console.log('erro ao puxar os dados', err); + return []; + } + } + + useEffect(() => { + async function useLoad() { + const array: Task[] = await loadTasks(); + setArrayAgendaTasks(array); + } + useLoad(); + },[]); return ( @@ -32,19 +66,31 @@ export default function ViewAgenda({ data, handleClose }: Props) { setConfigVisible(true)} style={styles.agendaConfig}> {data.nome_agenda} - setConfigVisible(false)} data={data} /> + item.name_task.toString()} + renderItem={({ item }) => { + return + }} + /> - + setAddTaskVisible(false)}> - setAddTaskVisible(false)} /> + { + setAddTaskVisible(false); + }} + /> + setAddTaskVisible(true)} + onPress={() => setAddTaskVisible(true)} style={styles.button} /> diff --git a/app/(tabs)/agenda/index.tsx b/app/(tabs)/agenda/index.tsx index 539a794..74cff55 100644 --- a/app/(tabs)/agenda/index.tsx +++ b/app/(tabs)/agenda/index.tsx @@ -8,6 +8,8 @@ import { FlatList, Modal, RefreshControl, StyleSheet, Text, View } from "react-n import { ActivityIndicator, FAB } from 'react-native-paper'; import { SafeAreaView } from 'react-native-safe-area-context'; import CreateAgenda from "./createGroup"; +import { FAB, ActivityIndicator } from 'react-native-paper'; +import { ComeToGroup } from "@/components/comeToGroup"; type Agendas = { uid_da_agenda: string @@ -17,9 +19,11 @@ type Agendas = { }; export default function Agenda() { + const [userUid, setUserUid] = useState(null); const [agendas, setAgendas] = useState>({}); const [refreshing, setRefreshing] = useState(true); + const [visibleComeInToGroup, setVisibleComeInToGroup] = useState(false); const [visibleCreateGroup, setVisibleCreate] = useState(false); const [loading, setLoading] = useState(false); const focused = useIsFocused(); @@ -116,12 +120,23 @@ export default function Agenda() { setVisibleCreate(false)} onCreated={onAgendaCreated} /> + + setVisibleComeInToGroup(false)}/> + + setVisibleCreate(true)} style={styles.btnCreate} /> + + setVisibleComeInToGroup(true)} + style={styles.btnAdd} + /> ); @@ -152,6 +167,13 @@ const styles = StyleSheet.create({ right: 16, bottom: 16, }, + + btnAdd:{ + position: 'absolute', + left: 16, + bottom: 16 + }, + btnCreateTxt: { color: "#FFF", fontWeight: "bold", diff --git a/components/comeToGroup.tsx b/components/comeToGroup.tsx new file mode 100644 index 0000000..ca318fb --- /dev/null +++ b/components/comeToGroup.tsx @@ -0,0 +1,185 @@ +import { Ionicons } from "@expo/vector-icons"; +import { getApp } from '@react-native-firebase/app'; +import { getAuth } from '@react-native-firebase/auth'; +import { useEffect, useState } from "react"; +import { StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native"; +import { FAB } from 'react-native-paper'; + +type Props = { + handleClose: () => void; + +} + +type Agenda = { + id: string + uid_da_agenda: string + nome_agenda: string + chave_de_convite: string + firstCreated: string +}; + +export function ComeToGroup({ handleClose }: Props) { + + const [userUid, setUserUid] = useState(''); + + useEffect(() => { + const auth = getAuth(getApp()); + setUserUid(auth.currentUser?.uid ?? ''); + }, []); + + const [objectAgenda, setObjectAgenda] = useState() + const [inviteCode, setInviteCode] = useState(''); + const chave = encodeURIComponent(process.env.EXPO_PUBLIC_API_KEY ?? ''); + + const urlGetAgendaCode = `${process.env.EXPO_PUBLIC_API_URL}/invite/${inviteCode}` + + + const getAgendaByCode = async (): Promise => { + try { + const response = await fetch(urlGetAgendaCode) + if (!response.ok) { + const text = response.text(); + console.log(`${response.status} - ${text}`); + return undefined; + } + const data: Agenda = await response.json(); + console.log('data: ', data); + return data; + } catch (err) { + console.log('erro ao armazenar a agenda: ', err); + return undefined; + } + } + + useEffect(() => { + if (objectAgenda) { + console.log('Agenda atualizada:', objectAgenda.uid_da_agenda); + } + }, [objectAgenda]); + + + + const enterInAgenda = async () => { + const data = await getAgendaByCode(); + if (data) { + console.log(data.uid_da_agenda) + setObjectAgenda(data) + + } + + const urlAddAgenda = `${process.env.EXPO_PUBLIC_API_URL}/add/agenda/membro?uid_da_agenda=${data?.uid_da_agenda}&uid_do_membro=${userUid}&api_key=${chave}` + + const response = await fetch(urlAddAgenda, { + method: 'POST' + }); + try { + const json = await response.json(); + console.log('API response: ', json); + handleClose(); + alert('Você entrou na agenda!') + } catch (err) { + console.log('erro ao entrar na agenda: ', err); + throw err + } + + } + + return ( + + + + + + + Digite o código de convite: + + + + { + if (inviteCode === "") { + alert('Insira um código de convite!') + } + else { + enterInAgenda() + } + }} + /> + + + ) +} + +const styles = StyleSheet.create({ + container: { + padding: "3%", + backgroundColor: "rgba(93, 93, 93, 0.5)", + flex: 1, + justifyContent: "center", + alignItems: "center" + }, + + text: { + width: "100%", + alignItems: "center", + }, + nameAgenda: { + fontSize: 23, + marginVertical: 15, + fontWeight: 'bold' + }, + + close: { + position: "absolute", + top: -20, + left: -5 + }, + + content: { + justifyContent: "center", + alignItems: "center", + width: "90%", + padding: 15, + backgroundColor: "#FFF", + borderRadius: 8, + paddingBottom: 30, + paddingTop: 30, + }, + textInput: { + borderWidth: 1, + borderColor: "purple", + marginTop: 15, + borderRadius: 8, + width: "100%", + padding: 10 + }, + button: { + color: '#FFF', + backgroundColor: "#b686f4", + height: 50, + width: 150, + borderRadius: 6, + justifyContent: "center", + alignItems: "center" + }, + + btnText: { + color: "#FFF", + fontSize: 17, + fontWeight: "bold" + }, + label: { + fontSize: 17 + } +}) \ No newline at end of file diff --git a/components/configAgenda.tsx b/components/configAgenda.tsx index b466096..99da8b9 100644 --- a/components/configAgenda.tsx +++ b/components/configAgenda.tsx @@ -2,6 +2,8 @@ import { Ionicons } from '@expo/vector-icons'; import { Pressable, StyleSheet, Text, TouchableOpacity, View, Modal } from 'react-native'; import { useState } from 'react'; import { ConfirmDel } from './confirmDelete'; +import { format } from 'date-fns'; +import * as Clipboard from 'expo-clipboard'; type Props = { data: { @@ -17,6 +19,15 @@ type Props = { export function ConfigAgenda({ closeAll, data, handleClose }: Props) { const [viewDel, setViewDel] = useState(false) + const date = data.firstCreated + const dateObj = new Date(date); + const formatedDate = format(dateObj, 'dd/MM/yyyy HH:mm'); + const link = `${data.chave_de_convite}` + const copyLink = async() =>{ + await Clipboard.setStringAsync(link); + alert('Link de convite copiado!'); + } + const deletarAgenda = async () => { const uid = encodeURIComponent(data.id); // ou data.uid_da_agenda, conforme a API espera const chave = encodeURIComponent(process.env.EXPO_PUBLIC_API_KEY ?? ''); @@ -61,10 +72,13 @@ export function ConfigAgenda({ closeAll, data, handleClose }: Props) { - {data.chave_de_convite} + Copiar código de convite + + + - {data.firstCreated} + Agenda criada em: {formatedDate} setViewDel(true)} style={styles.delete}> @@ -83,7 +97,7 @@ export function ConfigAgenda({ closeAll, data, handleClose }: Props) { const styles = StyleSheet.create({ container: { flex: 1, - padding: 0, + padding: 10, margin: 0 }, header: { @@ -103,10 +117,12 @@ const styles = StyleSheet.create({ }, content: { + flexDirection:"row", + justifyContent:'space-between', + alignItems:'center', paddingHorizontal: 10, paddingVertical: 20, borderWidth: 1, - marginHorizontal: 10, borderTopColor: "gray", borderRightWidth: 0, borderLeftWidth: 0, @@ -116,7 +132,6 @@ const styles = StyleSheet.create({ paddingHorizontal: 10, paddingVertical: 20, borderWidth: 1, - marginHorizontal: 10, borderTopColor: "gray", borderTopWidth: 0, borderRightWidth: 0, @@ -128,8 +143,7 @@ const styles = StyleSheet.create({ justifyContent: "space-between", paddingHorizontal: 10, paddingVertical: 20, - borderWidth: 1, - marginHorizontal: 10, + borderWidth: 1, borderTopColor: "gray", borderBottomWidth: 0, borderRightWidth: 0, diff --git a/components/publicAgendaItem.tsx b/components/publicAgendaItem.tsx new file mode 100644 index 0000000..8a14a30 --- /dev/null +++ b/components/publicAgendaItem.tsx @@ -0,0 +1,92 @@ +import { Ionicons } from "@expo/vector-icons"; +import { useState } from "react"; +import { Modal, StyleSheet, Text, TouchableOpacity, View } from "react-native"; +import { useTheme } from "react-native-paper"; +import TaskInfo from './cardInfo'; +import TaskDel from "./cardDel"; + +type Task = { + name_task:string +}; + +type Props = { + data: Task; +}; + +export function PublicTaskItem({data}:Props) { + const [infoView, setInfoView] = useState(false); + const [delView, setDelView] = useState(false); + + const { colors } = useTheme(); + + return ( + + setInfoView(true)} + activeOpacity={0.85} + style={[ + styles.card, + { + backgroundColor: colors.primary, + borderColor: colors.primary, + shadowColor: colors.primary + "aa", + }, + ]} + > + + + {data.name_task} + + + setDelView(true)} + style={styles.iconWrapper} + hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }} + > + + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + width: "97%", + alignSelf: "center", + }, + card: { + borderWidth: 1, + borderRadius: 16, + paddingHorizontal: 20, + paddingVertical: 16, + marginVertical: 6, + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.25, + shadowRadius: 4, + elevation: 4, + }, + row: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + }, + title: { + fontSize: 18, + fontWeight: "600", + flexShrink: 1, + paddingRight: 10, + }, + iconWrapper: { + padding: 6, + borderRadius: 20, + justifyContent: "center", + alignItems: "center", + }, +}); diff --git a/package-lock.json b/package-lock.json index 0ab84d9..d06921e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "expo-auth-session": "~6.2.1", "expo-blur": "~14.1.5", "expo-build-properties": "~0.14.8", + "expo-clipboard": "~7.1.5", "expo-constants": "~17.1.6", "expo-crypto": "~14.1.5", "expo-dev-client": "~5.2.4", @@ -7451,6 +7452,17 @@ "node": ">=10" } }, + "node_modules/expo-clipboard": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/expo-clipboard/-/expo-clipboard-7.1.5.tgz", + "integrity": "sha512-TCANUGOxouoJXxKBW5ASJl2WlmQLGpuZGemDCL2fO5ZMl57DGTypUmagb0CVUFxDl0yAtFIcESd78UsF9o64aw==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, "node_modules/expo-constants": { "version": "17.1.7", "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.1.7.tgz", diff --git a/package.json b/package.json index c5a4f67..ac30cc1 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,8 @@ "react-native-safe-area-context": "5.4.0", "react-native-screens": "~4.11.1", "react-native-web": "~0.20.0", - "react-native-webview": "13.13.5" + "react-native-webview": "13.13.5", + "expo-clipboard": "~7.1.5" }, "devDependencies": { "@babel/core": "^7.25.2",