Skip to content

Commit

Permalink
Improve/profile avatar timer status (#1634)
Browse files Browse the repository at this point in the history
* added initial status icon and color

* positioned the icon better, and removed unused code

* updating icon bg color dynamically

* added larger icons
  • Loading branch information
desperado1802 authored Oct 25, 2023
1 parent b54401b commit c8ec461
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 25 deletions.
52 changes: 42 additions & 10 deletions apps/mobile/app/components/HamburgerMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ const HamburgerMenu = observer((props: any) => {
<View style={{ marginBottom: 40 }}>
<ProfileImage size={76} user={user} />
</View>
<Text style={[styles.userProfileName, { color: colors.primary, marginTop: 30 }]}>
<Text
style={[
styles.userProfileName,
{ color: colors.primary, marginTop: 30 },
]}
>
{user?.name}
</Text>
<Text
Expand All @@ -113,30 +118,45 @@ const HamburgerMenu = observer((props: any) => {
</View>
<View style={styles.navigationSection}>
{activeTeam ? (
<TouchableOpacity style={styles.item} onPress={() => navigation.navigate("Timer")}>
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate("Timer")}
>
<SvgXml xml={dark ? userNotFocusedDark2 : userNotFocusedLight} />
<Text style={[styles.screenLabel, { color: colors.primary }]}>
{translate("myWorkScreen.name")}
</Text>
</TouchableOpacity>
) : null}

<TouchableOpacity style={styles.item} onPress={() => navigation.navigate("Team")}>
<SvgXml xml={dark ? peopleCaseNotFocusedDark2 : peopleNotFocusedLight} />
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate("Team")}
>
<SvgXml
xml={dark ? peopleCaseNotFocusedDark2 : peopleNotFocusedLight}
/>
<Text style={[styles.screenLabel, { color: colors.primary }]}>
{translate("teamScreen.name")}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate("Profile", { userId: user?.id, tabIndex: 0 })}
onPress={() =>
navigation.navigate("Profile", { userId: user?.id, tabIndex: 0 })
}
>
<SvgXml xml={dark ? briefCaseNotFocusedDark2 : briefCaseNotFocusedLight} />
<SvgXml
xml={dark ? briefCaseNotFocusedDark2 : briefCaseNotFocusedLight}
/>
<Text style={[styles.screenLabel, { color: colors.primary }]}>
{translate("tasksScreen.name")}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.item} onPress={() => navigation.navigate("Setting")}>
<TouchableOpacity
style={styles.item}
onPress={() => navigation.navigate("Setting")}
>
<SvgXml xml={dark ? settingsIconDark : settingsIconLight} />
<Text style={[styles.screenLabel, { color: colors.primary }]}>
{translate("settingScreen.name")}
Expand All @@ -153,7 +173,9 @@ const HamburgerMenu = observer((props: any) => {
onPress={toggleTheme}
style={[
styles.toggle,
dark ? { backgroundColor: "#1D222A" } : { backgroundColor: "#E7E7EA" },
dark
? { backgroundColor: "#1D222A" }
: { backgroundColor: "#E7E7EA" },
]}
>
{dark ? (
Expand All @@ -163,10 +185,20 @@ const HamburgerMenu = observer((props: any) => {
</View>
) : (
<View style={styles.iconsContainer}>
<View style={[styles.iconWrapper, { backgroundColor: "white" }]}>
<View
style={[
styles.iconWrapper,
{ backgroundColor: "white" },
]}
>
<SvgXml xml={sunLightLarge} />
</View>
<View style={[styles.iconWrapper, { backgroundColor: "transparent" }]}>
<View
style={[
styles.iconWrapper,
{ backgroundColor: "transparent" },
]}
>
<SvgXml xml={moonLightLarge} />
</View>
</View>
Expand Down
101 changes: 89 additions & 12 deletions apps/mobile/app/components/ProfileImage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
/* eslint-disable react-native/no-unused-styles */
/* eslint-disable react-native/no-color-literals */
/* eslint-disable react-native/no-inline-styles */
import React, { FC, useMemo } from "react"
import { View, StyleSheet } from "react-native"
import { Avatar, Badge } from "react-native-paper"
import { Avatar } from "react-native-paper"
import { IUser } from "../services/interfaces/IUserData"
import { typography, useAppTheme } from "../theme"
import { imgTitleProfileAvatar } from "../helpers/img-title-profile-avatar"
import { useOrganizationTeam } from "../services/hooks/useOrganization"
import { useTimer } from "../services/hooks/useTimer"
import { getTimerStatusValue } from "../helpers/get-timer-status"
import {
idleStatusIconLarge,
onlineAndTrackingTimeStatusIconLarge,
pauseStatusIconLarge,
suspendedStatusIconLarge,
} from "./svgs/icons"
import { SvgXml } from "react-native-svg"

interface Props {
user: IUser
Expand All @@ -14,18 +25,57 @@ interface Props {
const ProfileImage: FC<Props> = ({ user, size }) => {
const { colors } = useAppTheme()

const { currentTeam } = useOrganizationTeam()

const currentMember = currentTeam?.members.find(
(currentMember) => currentMember.employee.userId === user.id,
)

const { timerStatus } = useTimer()

const status = getTimerStatusValue(timerStatus, currentMember, currentTeam?.public)

const imageUrl = useMemo(
() => user?.image?.thumbUrl || user?.image?.fullUrl || user?.imageUrl,
[user?.image?.thumb, user],
)

let iconSvgXml = ""

switch (status) {
case "online":
iconSvgXml = onlineAndTrackingTimeStatusIconLarge
break
case "pause":
iconSvgXml = pauseStatusIconLarge
break
case "idle":
iconSvgXml = idleStatusIconLarge
break
case "suspended":
iconSvgXml = suspendedStatusIconLarge
break
}

return (
<View style={styles.container}>
<View>
{imageUrl ? (
<Avatar.Image
size={size - 6}
style={{ ...styles.profileImage, width: size, height: size }}
style={{
...styles.profileImage,
width: size,
height: size,
borderColor:
status === "online"
? "#6EE7B7"
: status === "pause"
? "#EFCF9E"
: status === "idle"
? "#F5BEBE"
: "#DCD6D6",
}}
source={{
uri: imageUrl,
}}
Expand All @@ -34,11 +84,46 @@ const ProfileImage: FC<Props> = ({ user, size }) => {
<Avatar.Text
label={imgTitleProfileAvatar(user?.name)}
size={size - 6}
style={{ ...styles.profileImage, width: size, height: size }}
style={{
...styles.profileImage,
width: size,
height: size,
borderColor:
status === "online"
? "#6EE7B7"
: status === "pause"
? "#EFCF9E"
: status === "idle"
? "#F5BEBE"
: "#DCD6D6",
}}
labelStyle={styles.prefix}
/>
)}
<Badge size={25} style={[styles.onlineIcon, { borderColor: colors.background }]} />
<View
style={{
right: 0,
bottom: 0,
borderRadius: 100,
width: 25,
height: 25,
position: "absolute",
backgroundColor:
status === "online"
? "#6EE7B7"
: status === "pause"
? "#EFCF9E"
: status === "idle"
? "#F5BEBE"
: "#DCD6D6",
alignItems: "center",
justifyContent: "center",
borderColor: colors.background,
borderWidth: 3,
}}
>
<SvgXml xml={iconSvgXml} />
</View>
</View>
</View>
)
Expand All @@ -50,20 +135,12 @@ const styles = StyleSheet.create({
alignItems: "center",
height: "10%",
},
onlineIcon: {
backgroundColor: "#27AE60",
borderWidth: 4,
bottom: 0,
position: "absolute",
right: 0,
},
prefix: {
fontFamily: typography.fonts.PlusJakartaSans.light,
fontSize: 42,
fontWeight: "200",
},
profileImage: {
borderColor: "#86DAA9",
borderRadius: 200,
borderWidth: 3,
},
Expand Down
48 changes: 48 additions & 0 deletions apps/mobile/app/components/svgs/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -468,3 +468,51 @@ export const pauseStatusIcon = `<svg
<path d="M4.44395 7.92772V2.07242C4.44395 1.51654 4.20924 1.29419 3.6163 1.29419H2.12159C1.52865 1.29419 1.29395 1.51654 1.29395 2.07242V7.92772C1.29395 8.4836 1.52865 8.70595 2.12159 8.70595H3.6163C4.20924 8.70595 4.44395 8.4836 4.44395 7.92772Z" />
<path d="M8.70566 7.92772V2.07242C8.70566 1.51654 8.47096 1.29419 7.87802 1.29419H6.38331C5.79449 1.29419 5.55566 1.51654 5.55566 2.07242V7.92772C5.55566 8.4836 5.79037 8.70595 6.38331 8.70595H7.87802C8.47096 8.70595 8.70566 8.4836 8.70566 7.92772Z" />
</svg>`

export const suspendedStatusIconLarge = `<svg
width="10"
height="10"
viewBox="0 0 10 10"
fill="#FFFFFF"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M4.98728 0.882324C2.71433 0.882324 0.869629 2.72703 0.869629 4.99997C0.869629 7.27291 2.71433 9.11762 4.98728 9.11762C7.26022 9.11762 9.10492 7.27291 9.10492 4.99997C9.10492 2.72703 7.26434 0.882324 4.98728 0.882324ZM6.74139 5.50644C6.74139 6.18997 6.18963 6.74174 5.5061 6.74174H4.49316C3.80963 6.74174 3.25786 6.18997 3.25786 5.50644V4.4935C3.25786 3.80997 3.80963 3.25821 4.49316 3.25821H5.5061C6.18963 3.25821 6.74139 3.80997 6.74139 4.4935V5.50644Z" />
</svg>`

export const idleStatusIconLarge = `<svg
width="10"
height="10"
viewBox="0 0 10 10"
fill="#E65B5B"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M4.98728 0.882324C2.71433 0.882324 0.869629 2.72703 0.869629 4.99997C0.869629 7.27291 2.71433 9.11762 4.98728 9.11762C7.26022 9.11762 9.10492 7.27291 9.10492 4.99997C9.10492 2.72703 7.26434 0.882324 4.98728 0.882324ZM6.74139 5.50644C6.74139 6.18997 6.18963 6.74174 5.5061 6.74174H4.49316C3.80963 6.74174 3.25786 6.18997 3.25786 5.50644V4.4935C3.25786 3.80997 3.80963 3.25821 4.49316 3.25821H5.5061C6.18963 3.25821 6.74139 3.80997 6.74139 4.4935V5.50644Z" />
</svg>`

export const onlineAndTrackingTimeStatusIconLarge = `<svg
width="10"
height="10"
viewBox="0 0 10 10"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.26027 4.01184L2.36439 6.96419C2.07615 7.13713 1.70557 6.93125 1.70557 6.5936V3.29948C1.70557 1.86242 3.25792 0.964776 4.50557 1.68125L6.39557 2.76831L7.25615 3.26242C7.54027 3.43125 7.54439 3.84301 7.26027 4.01184Z"
fill="#307D50"
/>
<path
d="M7.50763 6.42462L5.83998 7.38815L4.17645 8.34756C3.57939 8.68932 2.9041 8.61932 2.4141 8.27344C2.17527 8.10874 2.2041 7.74227 2.45527 7.59403L7.6888 4.45638C7.93586 4.30815 8.26116 4.44815 8.30645 4.73227C8.40939 5.3705 8.14586 6.05815 7.50763 6.42462Z"
fill="#307D50"
/>
</svg>`

export const pauseStatusIconLarge = `<svg
width="10"
height="10"
viewBox="0 0 10 10"
xmlns="http://www.w3.org/2000/svg"
fill="#B87B1E"
>
<path d="M4.44395 7.92772V2.07242C4.44395 1.51654 4.20924 1.29419 3.6163 1.29419H2.12159C1.52865 1.29419 1.29395 1.51654 1.29395 2.07242V7.92772C1.29395 8.4836 1.52865 8.70595 2.12159 8.70595H3.6163C4.20924 8.70595 4.44395 8.4836 4.44395 7.92772Z" />
<path d="M8.70566 7.92772V2.07242C8.70566 1.51654 8.47096 1.29419 7.87802 1.29419H6.38331C5.79449 1.29419 5.55566 1.51654 5.55566 2.07242V7.92772C5.55566 8.4836 5.79037 8.70595 6.38331 8.70595H7.87802C8.47096 8.70595 8.70566 8.4836 8.70566 7.92772Z" />
</svg>`
5 changes: 2 additions & 3 deletions apps/mobile/app/services/client/api/auth/sendAuthCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ export default async function sendAuthCode(email: string) {
}
}

const codeSendRes = await sendAuthCodeRequest(email)
.then(() => void 0)
.catch(() => void 0)
// removed the the then() block as it isn't working in stage api, always returning false and causing error message to appear
const codeSendRes = await sendAuthCodeRequest(email).catch(() => void 0)

if (!codeSendRes) {
return {
Expand Down

0 comments on commit c8ec461

Please sign in to comment.