aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorGravatar piotrruss <mail@pruss.it> 2022-05-18 23:02:58 +0100
committerGravatar piotrruss <mail@pruss.it> 2022-05-18 23:02:58 +0100
commitd77d7c440333ded46eeb8d28e22ec5517f3b15b8 (patch)
tree34bc54ef125433b722184777f33da90e1badf745 /components
parent9173d98070a0463b352625c2e50d20543f7c12fb (diff)
downloadnotes_mobile-d77d7c440333ded46eeb8d28e22ec5517f3b15b8.tar.gz
notes_mobile-d77d7c440333ded46eeb8d28e22ec5517f3b15b8.tar.bz2
notes_mobile-d77d7c440333ded46eeb8d28e22ec5517f3b15b8.zip
small fixes
Diffstat (limited to 'components')
-rw-r--r--components/Edit.jsx127
-rw-r--r--components/List.jsx72
-rw-r--r--components/Login.jsx90
-rw-r--r--components/Menu.jsx71
-rw-r--r--components/Note.jsx38
-rw-r--r--components/index.js7
6 files changed, 405 insertions, 0 deletions
diff --git a/components/Edit.jsx b/components/Edit.jsx
new file mode 100644
index 0000000..d2ec6b3
--- /dev/null
+++ b/components/Edit.jsx
@@ -0,0 +1,127 @@
+import { StyleSheet, Text, TextInput , View } from 'react-native';
+import { useState, useEffect } from 'react'
+import Menu from './Menu'
+
+const Edit = ({ edit, setEdit, session, setSession, showError }) => {
+ const [saving, setSaving] = useState()
+ const [title, setTitle] = useState(edit ? edit.title : '')
+ const [content, setContent] = useState()
+
+ const fetchNote = async () => {
+ try {
+ const response = await fetch(`https://apps.pruss.it/api/notes/${edit.noteId}`, {
+ method: 'GET', headers: { 'Cookie': session.cookies },
+ })
+ const { content } = await response.json()
+ setContent(content)
+ } catch(e) {
+ showError('Error while fetching note')
+ setEdit(null)
+ }
+ }
+
+ const saveNote = async () => {
+ try {
+ setSaving(true)
+ await fetch(`https://apps.pruss.it/api/notes/${edit._id}`, {
+ method: 'PUT',
+ headers: { 'Content-Type': 'plain/text; charset=utf-8', 'Cookie': session.cookies },
+ body: JSON.stringify({ title, noteId: edit.noteId, content })
+ })
+ setSaving(false)
+ setEdit(null)
+ } catch(e) {
+ showError('Error while saving note')
+ setSaving(false)
+ setEdit(null)
+ }
+ }
+
+ createNote = async () => {
+ try {
+ setSaving(true)
+ await fetch(`https://apps.pruss.it/api/notes`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'plain/text; charset=utf-8', 'Cookie': session.cookies },
+ body: JSON.stringify({ title, content })
+ })
+ setSaving(false)
+ setEdit(null)
+ } catch(e) {
+ showError('Error while saving note')
+ setSaving(false)
+ setEdit(null)
+ }
+ }
+
+ useEffect(() => {
+ if (edit?._id) {
+ fetchNote()
+ } else {
+ setContent('')
+ }
+ }, [])
+
+ return (
+ <>
+ <Menu
+ session={session}
+ setSession={setSession}
+ showError={showError}
+ setEdit={setEdit}
+ saveNote={edit._id ? saveNote : createNote}
+ />
+ {
+ content === undefined || saving
+ ? <Text style={styles.text}>{saving ? 'Saving...' : 'Loading...'}</Text>
+ : (
+ <View style={styles.container}>
+ <TextInput
+ placeholder="Title"
+ placeholderTextColor="#BBB"
+ style={styles.title}
+ value={title}
+ onChange={e => setTitle(e.nativeEvent.text)}
+ />
+ <TextInput
+ placeholder="Content"
+ placeholderTextColor="#BBB"
+ multiline={true}
+ textAlignVertical="top"
+ style={styles.content}
+ value={content}
+ onChange={e => setContent(e.nativeEvent.text)}
+ />
+ </View>
+ )
+ }
+ </>
+ )
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 15,
+ marginBottom: 50,
+ },
+ title: {
+ color: 'white',
+ borderBottomColor: 'white',
+ borderBottomWidth: 1,
+ paddingBottom: 15,
+ marginBottom: 10,
+ fontWeight: 'bold',
+ },
+ content: {
+ color: 'white',
+ flexGrow: 1,
+ paddingVertical: 10,
+ },
+ text: {
+ padding: 15,
+ color: 'white',
+ }
+});
+
+export default Edit
diff --git a/components/List.jsx b/components/List.jsx
new file mode 100644
index 0000000..ae578d9
--- /dev/null
+++ b/components/List.jsx
@@ -0,0 +1,72 @@
+import { StyleSheet, FlatList, Text } from 'react-native'
+import { useState, useEffect } from 'react'
+import Note from './Note'
+import Menu from './Menu'
+
+const List = ({ session, setSession, showError, setEdit }) => {
+ const [list, setList] = useState()
+ const [loading, setLoading] = useState(true)
+
+ const fetchNotes = async () => {
+ setLoading(true)
+ try {
+ const response = await fetch('https://apps.pruss.it/api/notes', { 'Cookie': session.cookies } )
+ const data = await response.json()
+ setList(data)
+ } catch(e) {
+ showError('Error while fetching notes')
+ }
+ setLoading(false)
+ }
+
+ useEffect(() => {
+ setLoading(true)
+ fetchNotes()
+ }, [])
+
+ return (
+ <>
+ <Menu
+ session={session}
+ setSession={setSession}
+ showError={showError}
+ setEdit={setEdit}
+ />
+ {
+ loading || list === undefined
+ ? <Text style={styles.text}>Loading notes...</Text>
+ : (
+ <FlatList
+ data={list.sort((a,b) => new Date(b.updated_at) - new Date(a.updated_at))}
+ renderItem={({item}) => <Note note={item} setEdit={setEdit} />}
+ ListEmptyComponent={<Text style={styles.text}>You don't have any notes</Text>}
+ onRefresh={fetchNotes}
+ refreshing={loading}
+ />
+ )
+ }
+ </>
+ )
+}
+
+const styles = StyleSheet.create({
+ text: {
+ color: 'white',
+ padding: 20,
+ },
+ menu: {
+ backgroundColor: 'lightgrey',
+ height: 55,
+ width: '100%',
+ flexDirection: 'row',
+ alignItems: 'flex-end',
+ justifyContent: 'space-between',
+ padding: 10,
+ },
+ menuText: {
+ fontWeight: 'bold',
+ paddingHorizontal: 10,
+ },
+});
+
+export default List;
diff --git a/components/Login.jsx b/components/Login.jsx
new file mode 100644
index 0000000..4c6ffb0
--- /dev/null
+++ b/components/Login.jsx
@@ -0,0 +1,90 @@
+import { StyleSheet, Text, TextInput, Pressable, View } from 'react-native';
+import { useState } from 'react';
+
+const Login = ({ login }) => {
+ const [email, setEmail] = useState('');
+ const [pass, setPass] = useState('');
+ const disabled = (e, p) => !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e) || p.length < 6;
+
+ return (
+ <View style={styles.container}>
+ <Text style={styles.title}>Login to Notes</Text>
+ <Text style={styles.text}>Account can be created through apps.pruss.it website</Text>
+ <TextInput
+ style={styles.input}
+ autoComplete="email"
+ placeholder="Email"
+ placeholderTextColor="#BBB"
+ keyboardType="email-address"
+ returnKeyType="next"
+ autoComplete="email"
+ textContentType="emailAddress"
+ value={email}
+ onChange={e => setEmail(e.nativeEvent.text.toLowerCase())}
+ />
+ <TextInput
+ style={styles.input}
+ autoComplete="password"
+ placeholder="Password"
+ placeholderTextColor="#BBB"
+ returnKeyType="next"
+ autoComplete="password-new"
+ secureTextEntry={true}
+ textContentType="newPassword"
+ value={pass}
+ onChange={e => setPass(e.nativeEvent.text)}
+ />
+ <Pressable
+ onPress={() => login(email, pass)}
+ style={{...styles.button, opacity: disabled(email, pass) ? .3 : 1}}
+ disabled={disabled(email, pass)}
+ >
+ <Text style={styles.buttonText}>Login</Text>
+ </Pressable>
+ </View>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: '100%'
+ },
+ title: {
+ color: 'white',
+ fontSize: 26,
+ marginBottom: 40,
+ },
+ text: {
+ color: 'white',
+ marginBottom: 50,
+ },
+ input: {
+ height: 50,
+ width: 280,
+ padding: 10,
+ marginBottom: 20,
+ color: 'white',
+ backgroundColor: '#444',
+ borderColor: '#aaa',
+ borderWidth: 1,
+ borderStyle: 'solid',
+ borderRadius: 10,
+ },
+ button: {
+ width: 100,
+ height: 40,
+ backgroundColor: '#666',
+ borderRadius: 5,
+ marginTop: 40,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ buttonText: {
+ color: 'white',
+ }
+});
+
+export default Login;
diff --git a/components/Menu.jsx b/components/Menu.jsx
new file mode 100644
index 0000000..bc883e4
--- /dev/null
+++ b/components/Menu.jsx
@@ -0,0 +1,71 @@
+import { StyleSheet, Text, View } from 'react-native';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+
+const Menu = ({ session, setSession, setEdit, showError, saveNote }) => {
+ const logout = async () => {
+ try {
+ await AsyncStorage.clear();
+ setSession(null)
+ } catch(e) {
+ showError('Error while logging out')
+ }
+ }
+
+ return (
+ <View style={styles.menu}>
+ {
+ saveNote
+ ? (
+ <>
+ <Text
+ style={styles.menuText}
+ onPress={() => setEdit(null)}
+ >
+ Back
+ </Text>
+ <Text
+ style={styles.menuText}
+ onPress={saveNote}
+ >
+ Save
+ </Text>
+ </>
+ ) : (
+ <>
+ <Text
+ style={styles.menuText}
+ onPress={() => setEdit({})}
+ >
+ New Note
+ </Text>
+ <Text style={styles.menuText}>{session.email}</Text>
+ <Text
+ style={styles.menuText}
+ onPress={logout}
+ >
+ Logout
+ </Text>
+ </>
+ )
+ }
+ </View>
+ )
+}
+
+const styles = StyleSheet.create({
+ menu: {
+ backgroundColor: 'lightgrey',
+ height: 55,
+ width: '100%',
+ flexDirection: 'row',
+ alignItems: 'flex-end',
+ justifyContent: 'space-between',
+ padding: 10,
+ },
+ menuText: {
+ fontWeight: 'bold',
+ paddingHorizontal: 10,
+ },
+});
+
+export default Menu
diff --git a/components/Note.jsx b/components/Note.jsx
new file mode 100644
index 0000000..d13e786
--- /dev/null
+++ b/components/Note.jsx
@@ -0,0 +1,38 @@
+import { Pressable, StyleSheet, Text } from 'react-native'
+
+const Note = ({ note, setEdit }) => {
+ const formatDate = d => d.replace('T',' ').replace(/\..*Z/, '')
+
+ return (
+ <Pressable
+ style={styles.note}
+ onPress={() => setEdit(note)}
+ >
+ <Text style={styles.title}>{note.title}</Text>
+ <Text style={styles.dates}>{`Created at: ${formatDate(note.created_at)}`}</Text>
+ <Text style={styles.dates}>{`Updated at: ${formatDate(note.updated_at)}`}</Text>
+ </Pressable>
+ )
+}
+
+const styles = StyleSheet.create({
+ note: {
+ textAlign: 'left',
+ padding: 15,
+ width: '100%',
+ borderColor: '#222',
+ borderStyle: 'solid',
+ borderTopWidth: 1,
+ borderBottomWidth: 1,
+ },
+ title: {
+ color: 'white',
+ fontSize: 18,
+ },
+ dates: {
+ color: '#bbb',
+ fontSize: 10,
+ },
+});
+
+export default Note
diff --git a/components/index.js b/components/index.js
new file mode 100644
index 0000000..0f227df
--- /dev/null
+++ b/components/index.js
@@ -0,0 +1,7 @@
+import Edit from './Edit'
+import List from './List'
+import Login from './Login'
+import Menu from './Menu'
+import Note from './Note'
+
+export { Edit, List, Login, Menu, Note }