feat: add business brand assets and health checks
This commit is contained in:
@@ -1,12 +1,6 @@
|
||||
import { router } from "expo-router";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Alert,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { Alert, ScrollView, StyleSheet, Text, View } from "react-native";
|
||||
|
||||
import { AppBackground } from "@/components/AppBackground";
|
||||
import { FilterChip } from "@/components/FilterChip";
|
||||
@@ -24,6 +18,10 @@ import { formatCurrency } from "@/lib/format";
|
||||
import type { ThemeColors } from "@/lib/theme-palette";
|
||||
import { useThemedStyles } from "@/lib/use-themed-styles";
|
||||
import { api } from "@/lib/trpc";
|
||||
import {
|
||||
BusinessBrandImage,
|
||||
hasMobileBusinessBrandAsset,
|
||||
} from "@/components/businesses/BusinessBrandImage";
|
||||
|
||||
type EntityTab = "clients" | "businesses";
|
||||
|
||||
@@ -48,7 +46,8 @@ export default function EntitiesScreen() {
|
||||
|
||||
const activeQuery = tab === "clients" ? clientsQuery : businessesQuery;
|
||||
const isLoading =
|
||||
clientsQuery.isLoading || (tab === "businesses" && businessesQuery.isLoading);
|
||||
clientsQuery.isLoading ||
|
||||
(tab === "businesses" && businessesQuery.isLoading);
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingScreen message="Loading…" />;
|
||||
@@ -71,21 +70,27 @@ export default function EntitiesScreen() {
|
||||
const businesses = businessesQuery.data ?? [];
|
||||
|
||||
function refresh() {
|
||||
return tab === "clients" ? clientsQuery.refetch() : businessesQuery.refetch();
|
||||
return tab === "clients"
|
||||
? clientsQuery.refetch()
|
||||
: businessesQuery.refetch();
|
||||
}
|
||||
|
||||
function confirmDelete(id: string, name: string) {
|
||||
Alert.alert(`Delete ${tab === "clients" ? "client" : "business"}?`, `Remove ${name}?`, [
|
||||
{ text: "Cancel", style: "cancel" },
|
||||
{
|
||||
text: "Delete",
|
||||
style: "destructive",
|
||||
onPress: () => {
|
||||
if (tab === "clients") deleteClient.mutate({ id });
|
||||
else deleteBusiness.mutate({ id });
|
||||
Alert.alert(
|
||||
`Delete ${tab === "clients" ? "client" : "business"}?`,
|
||||
`Remove ${name}?`,
|
||||
[
|
||||
{ text: "Cancel", style: "cancel" },
|
||||
{
|
||||
text: "Delete",
|
||||
style: "destructive",
|
||||
onPress: () => {
|
||||
if (tab === "clients") deleteClient.mutate({ id });
|
||||
else deleteBusiness.mutate({ id });
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -99,10 +104,7 @@ export default function EntitiesScreen() {
|
||||
/>
|
||||
}
|
||||
refreshControl={
|
||||
<PullToRefresh
|
||||
onRefresh={refresh}
|
||||
tintColor={colors.primary}
|
||||
/>
|
||||
<PullToRefresh onRefresh={refresh} tintColor={colors.primary} />
|
||||
}
|
||||
>
|
||||
<ScrollView
|
||||
@@ -141,7 +143,10 @@ export default function EntitiesScreen() {
|
||||
icon: "create-outline",
|
||||
color: "#fff",
|
||||
backgroundColor: colors.primary,
|
||||
onPress: () => router.push(`/(app)/entities/clients/edit/${client.id}`),
|
||||
onPress: () =>
|
||||
router.push(
|
||||
`/(app)/entities/clients/edit/${client.id}`,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
@@ -152,7 +157,9 @@ export default function EntitiesScreen() {
|
||||
onPress: () => confirmDelete(client.id, client.name),
|
||||
},
|
||||
]}
|
||||
onPress={() => router.push(`/(app)/entities/clients/${client.id}`)}
|
||||
onPress={() =>
|
||||
router.push(`/(app)/entities/clients/${client.id}`)
|
||||
}
|
||||
>
|
||||
<GlassSurface style={styles.card}>
|
||||
<View style={styles.cardInner}>
|
||||
@@ -162,7 +169,10 @@ export default function EntitiesScreen() {
|
||||
) : null}
|
||||
{client.defaultHourlyRate != null ? (
|
||||
<Text style={styles.meta}>
|
||||
{formatCurrency(client.defaultHourlyRate, client.currency ?? "USD")}
|
||||
{formatCurrency(
|
||||
client.defaultHourlyRate,
|
||||
client.currency ?? "USD",
|
||||
)}
|
||||
/hr
|
||||
</Text>
|
||||
) : null}
|
||||
@@ -190,7 +200,10 @@ export default function EntitiesScreen() {
|
||||
icon: "create-outline",
|
||||
color: "#fff",
|
||||
backgroundColor: colors.primary,
|
||||
onPress: () => router.push(`/(app)/entities/businesses/edit/${business.id}`),
|
||||
onPress: () =>
|
||||
router.push(
|
||||
`/(app)/entities/businesses/edit/${business.id}`,
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
@@ -201,20 +214,35 @@ export default function EntitiesScreen() {
|
||||
onPress: () => confirmDelete(business.id, business.name),
|
||||
},
|
||||
]}
|
||||
onPress={() => router.push(`/(app)/entities/businesses/${business.id}`)}
|
||||
onPress={() =>
|
||||
router.push(`/(app)/entities/businesses/${business.id}`)
|
||||
}
|
||||
>
|
||||
<GlassSurface style={styles.card}>
|
||||
<View style={styles.cardInner}>
|
||||
<View style={styles.nameRow}>
|
||||
<Text style={styles.name}>{business.name}</Text>
|
||||
{business.isDefault ? (
|
||||
<Text style={styles.badge}>Default</Text>
|
||||
<View style={styles.businessRow}>
|
||||
{hasMobileBusinessBrandAsset(business) ? (
|
||||
<BusinessBrandImage
|
||||
business={business}
|
||||
kind="icon"
|
||||
style={styles.businessIcon}
|
||||
/>
|
||||
) : null}
|
||||
<View style={styles.businessCopy}>
|
||||
<View style={styles.nameRow}>
|
||||
<Text style={styles.name}>{business.name}</Text>
|
||||
{business.isDefault ? (
|
||||
<Text style={styles.badge}>Default</Text>
|
||||
) : null}
|
||||
</View>
|
||||
{business.nickname ? (
|
||||
<Text style={styles.meta}>{business.nickname}</Text>
|
||||
) : null}
|
||||
{business.email ? (
|
||||
<Text style={styles.meta}>{business.email}</Text>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
{business.nickname ? (
|
||||
<Text style={styles.meta}>{business.nickname}</Text>
|
||||
) : null}
|
||||
{business.email ? <Text style={styles.meta}>{business.email}</Text> : null}
|
||||
</View>
|
||||
</GlassSurface>
|
||||
</SwipeableRow>
|
||||
@@ -257,6 +285,21 @@ const createEntitiesStyles = (colors: ThemeColors, isDark: boolean) =>
|
||||
gap: spacing.sm,
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
businessRow: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: spacing.md,
|
||||
},
|
||||
businessCopy: {
|
||||
flex: 1,
|
||||
minWidth: 0,
|
||||
gap: 4,
|
||||
},
|
||||
businessIcon: {
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: 10,
|
||||
},
|
||||
name: {
|
||||
fontSize: 16,
|
||||
fontFamily: fonts.bodySemiBold,
|
||||
|
||||
Reference in New Issue
Block a user