Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(native-app): add app widgets to home screen #15902

Merged
merged 35 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3797894
feat: first version of vehicle module for home screen
thoreyjona Aug 27, 2024
ae26af8
feat: add base for air discount module on home screen
thoreyjona Aug 27, 2024
78955ea
feat: first version of license widget
thoreyjona Aug 27, 2024
08553ba
feat: fix routing to vehicles and air discount
thoreyjona Aug 27, 2024
be89d69
feat: allow override styling for walletItems
thoreyjona Aug 27, 2024
4deb403
fix: correct size for all modules based on screensize
thoreyjona Aug 27, 2024
6a8ed4b
feat: first version of home-options
thoreyjona Aug 28, 2024
de24137
fix: better coordination for sizes of licenses
thoreyjona Aug 28, 2024
f129f1b
feat: UI for home options screen ready
thoreyjona Aug 28, 2024
b872ebc
feat: add empty states for home screen widgets
thoreyjona Aug 28, 2024
0d9585e
feat: add loading states for cards
thoreyjona Aug 29, 2024
9fa76a4
chore: remove unused illustration
thoreyjona Aug 29, 2024
09f54f1
feat: temp adding another illustration for card until better solution
thoreyjona Aug 29, 2024
d6eb714
fix: finalize empty states for home screen widgets
thoreyjona Aug 29, 2024
0f751c3
feat: show mileage vehicles first in vehicles module
thoreyjona Aug 29, 2024
6f34713
feat: disable pressable heading if no data, move inbox query into widget
thoreyjona Aug 29, 2024
776836d
chore: rename singular to plural to match applications name
thoreyjona Aug 29, 2024
cbe75b5
feat: add minHeight for vehicle cards in vehicle module
thoreyjona Aug 30, 2024
b04df02
fix: add seconds to appLock label in settings
thoreyjona Aug 30, 2024
c608f78
feat: move all data fetching and validation to home screen
thoreyjona Sep 3, 2024
032557f
fix: should be plural for licenses and vehicles everywhere
thoreyjona Sep 3, 2024
49e5f39
feat: skip fetching data on home screen if widgets are disabled
thoreyjona Sep 3, 2024
33065a2
fix: remove duplicate translations
thoreyjona Sep 3, 2024
fc45be0
fix: update feature flags to be plural in all places
thoreyjona Sep 5, 2024
f0554be
fix: don't set initializedWidget until queries have loaded
thoreyjona Sep 5, 2024
58ae302
fix: inbox check
thoreyjona Sep 5, 2024
7d23103
fix: spelling of initialised
thoreyjona Sep 5, 2024
7ee9cd1
feat: resetting homescreen preferences on logout
thoreyjona Sep 5, 2024
1ca414f
fix: final touches
thoreyjona Sep 5, 2024
126a9b6
fix: rename preferences flags to be shorter
thoreyjona Sep 6, 2024
83bec0d
fix: import preferences separately
thoreyjona Sep 6, 2024
d783e0c
fix: renaming children to items
thoreyjona Sep 6, 2024
e84813d
feat: remove reset call even later
thoreyjona Sep 6, 2024
ecdfedc
fix: see all in widgets should be variant heading5
thoreyjona Sep 6, 2024
d650f86
Merge branch 'main' into feat/app-widgets-home-screen
kodiakhq[bot] Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added apps/native/app/src/assets/icons/options.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/native/app/src/assets/icons/options@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/native/app/src/assets/icons/options@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
14 changes: 13 additions & 1 deletion apps/native/app/src/messages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const en: TranslatedMessages = {
'settings.security.appLockTimeoutLabel': 'App lock timeout',
'settings.security.appLockTimeoutDescription':
'Time until app lock will appear',
'settings.security.appLockTimeoutSeconds': 'sec.',
'settings.about.groupTitle': 'About',
'settings.about.versionLabel': 'Version',
'settings.about.logoutLabel': 'Logout',
Expand Down Expand Up @@ -168,7 +169,6 @@ export const en: TranslatedMessages = {
'home.screenTitle': 'Overview',
'home.applicationsStatus': 'Applications',
'home.allApplications': 'Digital applications',
'home.inbox': 'Latest in inbox',
'home.welcomeText': 'Hi',
'home.goodDay': 'Good day,',
'home.onboardingModule.card1':
Expand All @@ -184,6 +184,18 @@ export const en: TranslatedMessages = {
'home.vehicleModule.button': 'My vehicles',
'button.seeAll': 'See all',

// home options
'homeOptions.screenTitle': 'Home screen',
'homeOptions.heading.title': 'Configure home screen',
'homeOptions.heading.subtitle':
'Here you can configure what is displayed on the home screen.',
'homeOptions.graphic': 'Display graphic',
'homeOptions.inbox': 'Latest in inbox',
'homeOptions.licenses': 'Licenses',
'homeOptions.applications': 'Applications',
'homeOptions.vehicles': 'Vehicles',
'homeOptions.airDiscount': 'Air discount scheme',

// inbox
'inbox.screenTitle': 'Inbox',
'inbox.bottomTabText': 'Inbox',
Expand Down
14 changes: 13 additions & 1 deletion apps/native/app/src/messages/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const is = {
'settings.security.appLockTimeoutLabel': 'Biðtími skjálæsingar',
'settings.security.appLockTimeoutDescription':
'Tíminn þar til skjálæsing fer í gang',
'settings.security.appLockTimeoutSeconds': 'sek.',
'settings.about.groupTitle': 'Um appið',
'settings.about.versionLabel': 'Útgáfa',
'settings.about.logoutLabel': 'Útskrá',
Expand Down Expand Up @@ -169,7 +170,6 @@ export const is = {
'home.applicationsStatus': 'Staða umsókna',
'home.allApplications': 'Stafrænar umsóknir',
'home.welcomeText': 'Hæ',
'home.inbox': 'Nýjast í pósthólfinu',
'home.goodDay': 'Góðan dag,',
'home.onboardingModule.card1':
'Nú sérð þú upplýsingar um ökutæki, fasteignir og fjölskyldu þína í appinu til viðbótar við skjöl og skírteini.',
Expand All @@ -184,6 +184,18 @@ export const is = {
'home.vehicleModule.button': 'Mín ökutæki',
'button.seeAll': 'Sjá allt',

// home options
'homeOptions.screenTitle': 'Heimaskjár',
'homeOptions.heading.title': 'Stilla heimaskjá',
'homeOptions.heading.subtitle':
'Hér er hægt að stilla hvað birtist á heimaskjá.',
'homeOptions.graphic': 'Birta myndskreytingu',
'homeOptions.inbox': 'Nýjast í pósthólfinu',
'homeOptions.licenses': 'Skírteini',
'homeOptions.applications': 'Umsóknir',
'homeOptions.vehicles': 'Ökutæki',
'homeOptions.airDiscount': 'Loftbrú',

// inbox
'inbox.screenTitle': 'Pósthólf',
'inbox.bottomTabText': 'Pósthólf',
Expand Down
6 changes: 1 addition & 5 deletions apps/native/app/src/screens/applications/applications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,7 @@ export const ApplicationsScreen: NavigationFunctionComponent = ({
ListHeaderComponent={
<View style={{ flex: 1 }}>
<ApplicationsModule
applications={
(applicationsRes.data?.applicationApplications ??
[]) as Application[]
}
loading={applicationsRes.loading}
{...applicationsRes}
componentId={componentId}
hideAction={true}
hideSeeAllButton={true}
Expand Down
167 changes: 167 additions & 0 deletions apps/native/app/src/screens/home/air-discount-module.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import {
Typography,
Heading,
ChevronRight,
ViewPager,
EmptyCard,
GeneralCardSkeleton,
} from '@ui'

import React from 'react'
import { FormattedMessage, useIntl } from 'react-intl'
import { Image, SafeAreaView, TouchableOpacity } from 'react-native'
import styled, { useTheme } from 'styled-components/native'
import { ApolloError } from '@apollo/client'

import illustrationSrc from '../../assets/illustrations/le-jobs-s2.png'
import { navigateTo } from '../../lib/deep-linking'
import {
GetAirDiscountQuery,
useGetAirDiscountQuery,
} from '../../graphql/types/schema'
import { AirDiscountCard } from '@ui/lib/card/air-discount-card'
import { screenWidth } from '../../utils/dimensions'

const Host = styled.View`
margin-bottom: ${({ theme }) => theme.spacing[2]}px;
`

interface AirDiscountModuleProps {
data: GetAirDiscountQuery | undefined
loading: boolean
error?: ApolloError | undefined
}

const validateAirDiscountInitialData = ({
data,
loading,
}: {
data: GetAirDiscountQuery | undefined
loading: boolean
}) => {
if (loading) {
return true
}

const noRights =
data?.airDiscountSchemeDiscounts?.filter(
(item) => item.user.fund?.credit === 0 && item.user.fund.used === 0,
).length === data?.airDiscountSchemeDiscounts?.length

// Only show widget initially if the user has air discount rights
if (!noRights) {
return true
}

return false
}
thoreyjona marked this conversation as resolved.
Show resolved Hide resolved

const AirDiscountModule = React.memo(
({ data, loading, error }: AirDiscountModuleProps) => {
const theme = useTheme()
const intl = useIntl()

if (error && !data) {
return null
}
thoreyjona marked this conversation as resolved.
Show resolved Hide resolved

const noRights =
data?.airDiscountSchemeDiscounts?.filter(
(item) => item.user.fund?.credit === 0 && item.user.fund.used === 0,
).length === data?.airDiscountSchemeDiscounts?.length

const discounts = data?.airDiscountSchemeDiscounts?.filter(
({ user }) => !(user.fund?.used === 0 && user.fund.credit === 0),
)

const count = discounts?.length ?? 0

const items = discounts?.slice(0, 3).map(({ discountCode, user }) => (
<AirDiscountCard
key={`loftbru-item-${discountCode}`}
name={user.name}
code={discountCode}
credit={user.fund?.credit}
text={intl.formatMessage(
{ id: 'airDiscount.remainingFares' },
{
remaining: user.fund?.credit,
total: user.fund?.total,
},
)}
style={
count > 1
? {
thoreyjona marked this conversation as resolved.
Show resolved Hide resolved
width: screenWidth - theme.spacing[2] * 4,
marginLeft: theme.spacing[2],
}
: {
width: '100%',
}
}
/>
))

return (
<SafeAreaView
style={{
marginHorizontal: theme.spacing[2],
marginBottom: theme.spacing[2],
}}
>
<Host>
<TouchableOpacity
disabled={count === 0}
onPress={() => navigateTo(`/air-discount`)}
>
<Heading
button={
count === 0 ? null : (
<TouchableOpacity
onPress={() => navigateTo('/air-discount')}
style={{
flexDirection: 'row',
alignItems: 'center',
}}
>
<Typography variant="heading5" color={theme.color.blue400}>
<FormattedMessage id="button.seeAll" />
</Typography>
<ChevronRight />
</TouchableOpacity>
)
}
>
<FormattedMessage id="homeOptions.airDiscount" />
</Heading>
</TouchableOpacity>
{loading && !data ? (
<GeneralCardSkeleton height={146} />
) : (
<>
{noRights && (
<EmptyCard
text={intl.formatMessage({
id: 'airDiscount.emptyListDescription',
})}
image={
<Image source={illustrationSrc} resizeMode="contain" />
}
link={null}
/>
)}
{count === 1 && items}
{count >= 2 && <ViewPager>{items}</ViewPager>}
</>
)}
</Host>
</SafeAreaView>
)
},
)

export {
AirDiscountModule,
useGetAirDiscountQuery,
validateAirDiscountInitialData,
}
64 changes: 51 additions & 13 deletions apps/native/app/src/screens/home/applications-module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,65 @@ import {
import React from 'react'
import { useIntl } from 'react-intl'
import { Image, SafeAreaView, TouchableOpacity } from 'react-native'
import { useTheme } from 'styled-components'
import { ApolloError } from '@apollo/client'

import leJobss3 from '../../assets/illustrations/le-jobs-s3.png'
import { Application } from '../../graphql/types/schema'
import {
ListApplicationsQuery,
useListApplicationsQuery,
} from '../../graphql/types/schema'
import { navigateTo } from '../../lib/deep-linking'
import { useBrowser } from '../../lib/use-browser'
import { getApplicationUrl } from '../../utils/applications-utils'
import { useTheme } from 'styled-components'
import { screenWidth } from '../../utils/dimensions'

interface ApplicationsModuleProps {
applications: Application[]
data: ListApplicationsQuery | undefined
loading: boolean
error?: ApolloError | undefined
componentId: string
hideAction?: boolean
hideSeeAllButton?: boolean
}

export const ApplicationsModule = React.memo(
const validateApplicationsInitialData = ({
data,
loading,
}: {
data: ListApplicationsQuery | undefined
loading: boolean
}) => {
if (loading) {
return true
}
// Only show widget initially if there are applications
if (data?.applicationApplications?.length !== 0) {
return true
}
return false
}
thoreyjona marked this conversation as resolved.
Show resolved Hide resolved

const ApplicationsModule = React.memo(
({
applications,
data,
loading,
error,
componentId,
hideAction,
hideSeeAllButton = false,
}: ApplicationsModuleProps) => {
const intl = useIntl()
const theme = useTheme()
const applications = data?.applicationApplications ?? []
const count = applications.length
const { openBrowser } = useBrowser()

const children = applications.slice(0, 5).map((application) => (
if (error && !data) {
return null
}

const items = applications.slice(0, 3).map((application) => (
<StatusCard
key={application.id}
title={application.name ?? ''}
Expand All @@ -68,7 +98,7 @@ export const ApplicationsModule = React.memo(
style={
count > 1
? {
width: 283,
width: screenWidth - theme.spacing[2] * 4,
marginLeft: 16,
}
: {}
Expand All @@ -80,10 +110,12 @@ export const ApplicationsModule = React.memo(
<SafeAreaView
style={{
marginHorizontal: theme.spacing[2],
marginBottom: theme.spacing[2],
}}
>
<TouchableOpacity onPress={() => navigateTo(`/applications`)}>
<TouchableOpacity
disabled={count === 0}
onPress={() => navigateTo(`/applications`)}
>
<Heading
button={
count === 0 || hideSeeAllButton ? null : (
Expand All @@ -94,7 +126,7 @@ export const ApplicationsModule = React.memo(
alignItems: 'center',
}}
>
<Typography weight="400" color={blue400}>
<Typography variant="heading5" color={blue400}>
{intl.formatMessage({ id: 'button.seeAll' })}
</Typography>
<ChevronRight />
Expand All @@ -105,7 +137,7 @@ export const ApplicationsModule = React.memo(
{intl.formatMessage({ id: 'home.applicationsStatus' })}
</Heading>
</TouchableOpacity>
{loading ? (
{loading && !data ? (
<StatusCardSkeleton />
) : (
<>
Expand Down Expand Up @@ -136,11 +168,17 @@ export const ApplicationsModule = React.memo(
}
/>
)}
{count === 1 && children.slice(0, 1)}
{count >= 2 && <ViewPager>{children}</ViewPager>}
{count === 1 && items}
{count >= 2 && <ViewPager>{items}</ViewPager>}
</>
)}
</SafeAreaView>
)
},
)

export {
ApplicationsModule,
useListApplicationsQuery,
validateApplicationsInitialData,
}
Loading