Skip to content

Commit

Permalink
fix(modal): ✨ upd. EditContact
Browse files Browse the repository at this point in the history
  • Loading branch information
zheleznov163 committed Aug 31, 2022
1 parent 65752c0 commit 83990a0
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 120 deletions.
192 changes: 98 additions & 94 deletions modals/profile/components/organisms/EditContact.tsx
Original file line number Diff line number Diff line change
@@ -1,111 +1,113 @@
import { useCallback, useMemo, useState } from "react"
import { useMemo } from "react"
import { StyleSheet, Text, View } from "react-native"
import { observer } from "mobx-react-lite"
import { RectButton } from "react-native-gesture-handler"
import { COLOR, InputHandler } from "utils"
import { makeAutoObservable } from "mobx"
import { Steps } from "classes"
import { Button, ButtonBack, Icon2 } from "components/atoms"
import { Search, Title } from "../atoms"
import { RectButton } from "react-native-gesture-handler"
import { Steps } from "classes"
import { ButtonAvatar } from "../moleculs"
import { Contact } from "stores/ContactsStore"
import { useStore } from "hooks"

export class Controller {
steps = new Steps(["Data", "Photo"])
inputAddress = new InputHandler()
inputNickname = new InputHandler()
image: string | null = null

constructor() {
makeAutoObservable(this, {}, { autoBind: true })
}

setImage(image: string | null) {
this.image = image
}
}

type Props = {
contact: Contact | null
steps: Steps<"Data" | "Photo">
close(): void
controller: Controller
onPressScan(): void
inputAddress: InputHandler
inputNickname: InputHandler
}

export default observer<Props>(
({ close, contact, steps, onPressScan, inputAddress, inputNickname }) => {
const { contacts } = useStore()

// ------- Image ----------

const [image, setImage] = useState<string | null>(null)

const source = useMemo(
() => (contact?.avatar || image ? { uri: image || contact?.avatar } : null),
[image],
)

// -------------------------

const save = useCallback(() => {
if (contact) {
contacts.editAddress(contact, inputAddress.value)
contacts.editName(contact, inputNickname.value)
if (image) {
contacts.editAvatar(contact, image)
}
}
close()
}, [image])

return (
<View style={styles.container}>
{steps.title === "Data" && (
<>
<Title style={styles.title}>Edit Contact</Title>

<View style={{ marginBottom: 24 }}>
<Text style={styles.label}>Edit address</Text>
<Search
value={inputAddress.value}
onChangeText={inputAddress.set}
loupe={false}
Right={
<RectButton style={styles.button_qr} onPress={onPressScan}>
<Icon2 name="qr_code" stroke={COLOR.RoyalBlue} size={22} />
</RectButton>
}
/>
</View>

<View>
<Text style={styles.label}>Edit name</Text>
<Search value={inputNickname.value} onChangeText={inputNickname.set} loupe={false} />
</View>
</>
)}

{steps.title === "Photo" && (
<>
<Title style={styles.title}>Edit Profile Photo</Title>
<View style={styles.avatar}>
<ButtonAvatar source={source} onChange={setImage} />
</View>
</>
)}

<View style={styles.footer}>
<View style={styles.buttons}>
{/* <ButtonBack onPress={goBack} /> */}

{steps.title === "Data" ? (
<Button
text="Continue"
onPress={steps.next}
textStyle={styles.buttonText}
contentContainerStyle={styles.buttonContent}
/>
) : (
<Button
onPress={save}
text="Save"
textStyle={styles.buttonText}
contentContainerStyle={styles.buttonContent}
/>
)}
export default observer<Props>(({ contact, onPressScan, controller }) => {
const { steps, inputAddress, inputNickname, image } = controller

const source = useMemo(
() => (contact?.avatar || image ? { uri: image || contact?.avatar } : null),
[image],
)

return (
<View style={styles.container}>
{steps.title === "Data" && (
<>
<Title style={styles.title}>Edit Contact</Title>

<View style={{ marginBottom: 24 }}>
<Text style={styles.label}>Edit address</Text>
<Search
value={inputAddress.value}
onChangeText={inputAddress.set}
loupe={false}
Right={
<RectButton style={styles.button_qr} onPress={onPressScan}>
<Icon2 name="qr_code" stroke={COLOR.RoyalBlue} size={22} />
</RectButton>
}
/>
</View>
</View>
</View>
)
},
)

<View>
<Text style={styles.label}>Edit name</Text>
<Search value={inputNickname.value} onChangeText={inputNickname.set} loupe={false} />
</View>
</>
)}

{steps.title === "Photo" && (
<>
<Title style={styles.title}>Edit Profile Photo</Title>
<View style={styles.avatar}>
<ButtonAvatar source={source} onChange={controller.setImage} />
</View>
</>
)}
</View>
)
})

type FooterProps = {
steps: Steps
onPressBack(): void
onPressNext(): void
onPressDone(): void
}

export const Footer = observer(({ steps, onPressBack, onPressDone, onPressNext }: FooterProps) => (
<View style={styles.footer}>
<View style={styles.buttons}>
<ButtonBack onPress={onPressBack} />

{steps.title === "Data" ? (
<Button
text="Continue"
onPress={onPressNext}
textStyle={styles.buttonText}
contentContainerStyle={styles.buttonContent}
/>
) : (
<Button
onPress={onPressDone}
text="Save"
textStyle={styles.buttonText}
contentContainerStyle={styles.buttonContent}
/>
)}
</View>
</View>
))

const styles = StyleSheet.create({
container: {
Expand Down Expand Up @@ -139,6 +141,8 @@ const styles = StyleSheet.create({
footer: {
flexGrow: 1,
justifyContent: "flex-end",
marginHorizontal: 26,
marginBottom: 8,
},

button_qr: {
Expand Down
6 changes: 5 additions & 1 deletion modals/profile/components/organisms/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ export { default as AddWatchAccount } from "./AddWatchAccount"
export { default as ChangeAvatar } from "./ChangeAvatar"
export { default as AddContact } from "./AddContact"
export { default as RemoveContact } from "./RemoveContact"
export { default as EditContact } from "./EditContact"
export {
default as EditContact,
Footer as FooterEditContact,
Controller as ControllerEditContact,
} from "./EditContact"
61 changes: 36 additions & 25 deletions modals/profile/openEditContact.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
import { Keyboard } from "react-native"
import { BottomSheetProps } from "@gorhom/bottom-sheet"
import { gbs } from "modals"
import { Steps } from "classes"
import { reaction } from "mobx"
import { Contact } from "stores/ContactsStore"
import { EditContact } from "./components/organisms"
import { InputHandler } from "utils"
import { store } from "stores/Store"
import { navigationRef } from "navigation/utils"
import { EditContact, FooterEditContact, ControllerEditContact } from "./components/organisms"

type Options = {
contact: Contact
props?: Omit<Partial<BottomSheetProps>, "onClose" | " children">
onClose?(): void
}

const snapPoints = {
Data: [460],
Photo: [410],
}

export default async function openChangeAvatar({ props, onClose, contact }: Options) {
const { contacts } = store

const close = () => {
Keyboard.dismiss()
gbs.close()
}

const steps = new Steps(["Data", "Photo"])
const controller = new ControllerEditContact()

const goBack = () => (steps.active > 0 ? steps.goBack() : close())
const { steps, inputAddress, inputNickname, image } = controller

const inputAddress = new InputHandler(contact?.address)
const inputNickname = new InputHandler(contact?.name)
const goBack = () => (steps.active > 0 ? steps.goBack() : close())

const scan = () => {
close()
Expand All @@ -35,26 +40,26 @@ export default async function openChangeAvatar({ props, onClose, contact }: Opti
})
}

const save = () => {
if (contact) {
contacts.editAddress(contact, inputAddress.value)
contacts.editName(contact, inputNickname.value)
if (image) {
contacts.editAvatar(contact, image)
}
}
close()
}

const disposer = reaction(
() => steps.title,
(title) => {
switch (title) {
case "Data":
gbs.updProps({ snapPoints: [460] })
break
case "Photo":
default:
gbs.updProps({ snapPoints: [410] })
break
}
},
(title) => gbs.updProps({ snapPoints: snapPoints[title] }),
)

gbs.backHandler = () => goBack()

const open = () => {
gbs.backHandler = () => goBack()
gbs.setProps({
snapPoints: [410],
snapPoints: snapPoints[steps.title],
...props,
onChange(index) {
if (index === -1) {
Expand All @@ -63,14 +68,20 @@ export default async function openChangeAvatar({ props, onClose, contact }: Opti
onClose && onClose()
}
},
footerComponent: () => (
<FooterEditContact
steps={steps}
onPressBack={goBack}
onPressDone={save}
onPressNext={steps.next}
/>
),
children: () => (
<EditContact
inputAddress={inputAddress}
inputNickname={inputNickname}
controller={controller}
onPressScan={scan}
close={close}
contact={contact}
steps={steps}
//
/>
),
})
Expand Down

0 comments on commit 83990a0

Please sign in to comment.