Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
181 commits
Select commit Hold shift + click to select a range
a7a4174
🐛 fix conditional query type errors
andrew-bierman Aug 12, 2025
552ceb0
🐛 missing import
andrew-bierman Aug 12, 2025
3893fde
🏷️ fix type error in db connection
andrew-bierman Aug 12, 2025
19e2401
📝 update api docs on auth routes
andrew-bierman Aug 12, 2025
baa426c
🎨 lint
andrew-bierman Aug 12, 2025
461985c
🎨 lint
andrew-bierman Aug 12, 2025
e0996fe
➕ add drizzle zod
andrew-bierman Aug 12, 2025
ebd5d4a
➕ add missing deps
andrew-bierman Aug 12, 2025
fad9dce
⚡️ add drizzle zod schemas
andrew-bierman Aug 12, 2025
74a011c
⚡️ add and register openapi configuration
andrew-bierman Aug 12, 2025
44482e2
⚡️ add schemas for openapi
andrew-bierman Aug 12, 2025
e58c677
feat(api): Add comprehensive OpenAPI documentation to all routes
andrew-bierman Aug 12, 2025
9b5fcea
fix: resolve TypeScript type errors in API routes
andrew-bierman Aug 12, 2025
82472ec
fix: resolve OpenAPI type errors and standardize response patterns
andrew-bierman Aug 12, 2025
693a930
🗑️ remove old auth logic, refactor
andrew-bierman Aug 12, 2025
51a9124
🏷️ fix type errors
andrew-bierman Aug 12, 2025
1f0a93b
🗑️ clean up api docs
andrew-bierman Aug 12, 2025
cc09252
fix(CatalogItemDetailScreen): add fallback image
mikib0 Aug 18, 2025
6743556
fix(expo/ai-chat): show ActivityIndicator instead of dots while gener…
mikib0 Aug 18, 2025
c76b2cd
feat(expo/ai-chat): parse markdown in AI messages
mikib0 Aug 18, 2025
e50ab62
fix(expo/CatalogItemDetailScreen): ensure consitent material chip rad…
mikib0 Aug 18, 2025
d32d4d0
fix(ChatBubble): tweak AI message layout to look more standard
mikib0 Aug 18, 2025
e7debad
fix(ai-chat): patch sending of suggested messages
mikib0 Aug 18, 2025
7f9d120
♻️ refactor to remove authenticate request func in favor of middleware
andrew-bierman Aug 20, 2025
03bb8f9
🗑️ remove unnecessary auth check
andrew-bierman Aug 20, 2025
783fe71
🎨 lint
andrew-bierman Aug 20, 2025
475b147
🎨 lint
andrew-bierman Aug 20, 2025
7f10851
🏷️ update response types
andrew-bierman Aug 20, 2025
31cae77
🏷️ resolve type errors with ai sdk
andrew-bierman Aug 20, 2025
51d4c7f
🏷️ resolve more type errors
andrew-bierman Aug 20, 2025
241c17f
🎨 clarify var name
andrew-bierman Aug 20, 2025
66ae20d
⬆️ bump ai sdk
andrew-bierman Aug 20, 2025
64bf2fa
Initial plan
Copilot Aug 20, 2025
8b4682d
Fix major type mismatches in schemas and types
Copilot Aug 20, 2025
b9cc882
Fix catalog sort fields and guide route key field
Copilot Aug 20, 2025
200396e
Fix database column access errors in pack suggestions route
Copilot Aug 20, 2025
164c605
Merge branch 'development' into feat/revamp-ai
mikib0 Aug 20, 2025
ec3d2e3
refactor(ChatBubble): clean up
mikib0 Aug 20, 2025
07805bb
feat(ai-chat): add loading state and cleanup some code
mikib0 Aug 20, 2025
03dc5c2
feat(ai-chat): add ErrorState component and handle error display in chat
mikib0 Aug 20, 2025
e602b34
Merge remote-tracking branch 'origin/development' into fix/conditiona…
andrew-bierman Aug 22, 2025
b1d460d
🎨 lint
andrew-bierman Aug 22, 2025
6df1072
🎨 lint
andrew-bierman Aug 22, 2025
a61cfd7
🎨 lint
andrew-bierman Aug 22, 2025
7794522
Restructure Env type architecture: centralize through types package
Copilot Aug 22, 2025
f4812fe
Merge remote-tracking branch 'origin/fix/conditional-query-type-error…
andrew-bierman Aug 22, 2025
3852ba5
🎨 lint
andrew-bierman Aug 22, 2025
87b7df5
🎨 lint
andrew-bierman Aug 22, 2025
43eda1a
🎨 lint
andrew-bierman Aug 22, 2025
a9c5395
Merge branch 'development' into fix/conditional-query-type-errors
andrew-bierman Aug 22, 2025
022db5b
Merge branch 'fix/conditional-query-type-errors' into copilot/fix-22c…
andrew-bierman Aug 22, 2025
f039d22
🏷️ fix type error
andrew-bierman Aug 22, 2025
6e2e165
🏷️ type error resolutions
andrew-bierman Aug 22, 2025
207739a
Merge remote-tracking branch 'origin/copilot/fix-22cee349-f38f-4f36-9…
andrew-bierman Aug 22, 2025
67216e1
🏷️ fix type errors
andrew-bierman Aug 22, 2025
c994589
🎨 lint
andrew-bierman Aug 22, 2025
15e8674
🎨 lint
andrew-bierman Aug 22, 2025
186494d
🏷️ fix type errors
andrew-bierman Aug 22, 2025
a1bc3ff
➕ add radash
andrew-bierman Aug 22, 2025
3814fef
🎨 lint
andrew-bierman Aug 22, 2025
c50ae55
🎨 lint
andrew-bierman Aug 22, 2025
792d73f
🏷️ fix type errors
andrew-bierman Aug 22, 2025
b382fc3
🏷️ fix type errors
andrew-bierman Aug 22, 2025
9159ae5
🏷️ type errors
andrew-bierman Aug 22, 2025
bd917ea
🏷️ fix type errors
andrew-bierman Aug 22, 2025
040f5ea
🏷️ type errors
andrew-bierman Aug 22, 2025
6b49a15
🏷️ fix types
andrew-bierman Aug 22, 2025
fd62613
🏷️ type errors
andrew-bierman Aug 22, 2025
b205757
🏷️ fix types
andrew-bierman Aug 22, 2025
caca7bd
🏷️ fix types
andrew-bierman Aug 22, 2025
04c57fa
🏷️ fix types
andrew-bierman Aug 22, 2025
1430723
🐛 import issue
andrew-bierman Aug 22, 2025
e31c7c7
🏷️ fix type errors
andrew-bierman Aug 22, 2025
38d768a
⬆️ align deps
andrew-bierman Aug 22, 2025
9abced4
Merge pull request #1584 from PackRat-AI/copilot/fix-22cee349-f38f-4f…
andrew-bierman Aug 22, 2025
308e816
Merge remote-tracking branch 'origin/development' into fix/conditiona…
andrew-bierman Aug 22, 2025
e522d05
🏷️ fix type error
andrew-bierman Aug 22, 2025
d3e37da
switch token and session atoms to use expo-sqlite/kv-store
Isthisanmol Aug 22, 2025
5df5057
make atomWithKvStorage.ts
Isthisanmol Aug 22, 2025
61342fd
Update apps/expo/features/auth/atoms/authAtoms.ts
Isthisanmol Aug 22, 2025
99d89fe
Update apps/expo/features/auth/atoms/authAtoms.ts
Isthisanmol Aug 22, 2025
36fcdcc
⬆️ update deps
andrew-bierman Aug 23, 2025
949888a
Merge pull request #1614 from PackRat-AI/development
andrew-bierman Aug 23, 2025
c785e45
Merge main into development
github-actions[bot] Aug 23, 2025
09ec6bb
Merge branch 'development' into chore/migrate-auth-storage-to-kv
Isthisanmol Aug 23, 2025
3d2ef14
Merge pull request #1612 from PackRat-AI/chore/migrate-auth-storage-t…
Isthisanmol Aug 23, 2025
19f0010
handle remote URLs properly in image upload process
Isthisanmol Aug 23, 2025
2cd6251
Update apps/expo/lib/utils/ImageCacheManager.ts
Isthisanmol Aug 23, 2025
4f46408
fix(expo/catalog): patch image caching when adding catalog item to pack
mikib0 Aug 23, 2025
ecfe8d3
Merge pull request #1619 from PackRat-AI/fix/patch-image-saving-catalog
mikib0 Aug 23, 2025
9cde347
fix(catalog): cleanup item specifications display
mikib0 Aug 23, 2025
31947d6
Merge branch 'development' into feat/revamp-ai
mikib0 Aug 23, 2025
3e6ffd3
refactor: lint
mikib0 Aug 23, 2025
10569fc
Merge pull request #1620 from PackRat-AI/fix/cleanup-catalog-ui
mikib0 Aug 23, 2025
e5a8d42
merge development
Isthisanmol Aug 23, 2025
75f072b
add catch
Isthisanmol Aug 23, 2025
43b182b
use imageFileName
Isthisanmol Aug 23, 2025
bb94927
Merge pull request #1618 from PackRat-AI/fix/image-upload-on-catalogI…
Isthisanmol Aug 23, 2025
d6e2a7d
refactor(etl): organise csv utils to a seperate module and clean up p…
mikib0 Aug 23, 2025
d1d4722
Initial plan
Copilot Aug 23, 2025
6e7fc68
Analyze database connection issue: fix test environment setup
Copilot Aug 23, 2025
5e52653
Fix database connection: use PostgreSQL for tests, Neon for production
Copilot Aug 23, 2025
ae0170a
RESOLVED: API tests database connectivity - PostgreSQL for tests, Neo…
Copilot Aug 23, 2025
c25bf05
Potential fix for code scanning alert no. 530: Incomplete URL substri…
andrew-bierman Aug 23, 2025
b1e3d37
Potential fix for code scanning alert no. 531: Incomplete URL substri…
andrew-bierman Aug 23, 2025
ab8cebd
Update packages/api/migrate.ts
andrew-bierman Aug 23, 2025
9b78883
Update packages/api/migrate.ts
andrew-bierman Aug 23, 2025
ec20ef1
fix(etl): add object streaming support
mikib0 Aug 23, 2025
3df0ac7
Initial plan
Copilot Aug 23, 2025
d2488ba
Initial plan
Copilot Aug 23, 2025
6375a9d
Initial assessment - identify API test migration script import and va…
Copilot Aug 23, 2025
7b4da09
Fix API tests migration script import and variable errors
Copilot Aug 23, 2025
fa115f1
Fix catalog item specifications text formatting with improved spacing…
Copilot Aug 23, 2025
c0d67c5
Merge pull request #1626 from PackRat-AI/copilot/fix-8fd6cd73-c2e8-43…
andrew-bierman Aug 23, 2025
be3ff6d
Merge pull request #1624 from PackRat-AI/copilot/fix-4e480913-c611-4f…
andrew-bierman Aug 23, 2025
bfb5732
Merge main into development
github-actions[bot] Aug 23, 2025
433086c
Merge branch 'main' into copilot/fix-1616
andrew-bierman Aug 23, 2025
40d3b3f
Merge pull request #1628 from PackRat-AI/copilot/fix-1616
andrew-bierman Aug 23, 2025
5950b60
Merge branch 'development' into fix/conditional-query-type-errors
andrew-bierman Aug 23, 2025
193a8af
Merge pull request #1577 from PackRat-AI/fix/conditional-query-type-e…
andrew-bierman Aug 23, 2025
1c2e8f6
Initial plan
Copilot Aug 23, 2025
1d3ca6c
Initial analysis - plan to fix lint and type checking issues
Copilot Aug 23, 2025
9de0555
Fix lint issues and simple type errors - unused variables, fetch mock…
Copilot Aug 23, 2025
5a9b835
Fix orphaned mockFetch reference in weather tests
Copilot Aug 23, 2025
efc21d0
Fix Drizzle .returning() API calls - remove field selection arguments
Copilot Aug 23, 2025
cdc535f
Merge pull request #1629 from PackRat-AI/copilot/fix-390c9988-e939-43…
andrew-bierman Aug 23, 2025
9761694
use locationid returned from search instead of lat&lng to get forcast
Isthisanmol Aug 23, 2025
38cf94d
Merge branch 'development' into fix/weather-api-adding-different-loca…
Isthisanmol Aug 23, 2025
524d05c
Initial plan
Copilot Aug 23, 2025
ee75363
Remove 5 unused images from landing/public directory
Copilot Aug 23, 2025
4fe681e
feat/added guides link on landing page
rivamaryvillanueva Aug 23, 2025
fe5c9a1
fix refresh forcastData
Isthisanmol Aug 23, 2025
9f5886c
fix refresh forcastData
Isthisanmol Aug 23, 2025
5e7dd87
Merge branch 'development' into feat/revamp-ai
mikib0 Aug 23, 2025
f7a1add
fix(api): temporarily losen chat route validation for AI chat to func…
mikib0 Aug 23, 2025
fe13424
fix(expo/ai-chat): properly handle retry flow
mikib0 Aug 23, 2025
63e3cb7
refactor(api/chat): fix typo
mikib0 Aug 23, 2025
6e1c478
Merge pull request #1621 from PackRat-AI/feat/revamp-ai
mikib0 Aug 23, 2025
c29e8f9
fix(api/catalog): patch category search condition to cast categories …
mikib0 Aug 23, 2025
c8d2424
Merge pull request #1635 from PackRat-AI/fix/catalog-search
mikib0 Aug 23, 2025
637c5be
fix(api/getCatalogItemsCategoriesRoute): adjust response to match exp…
mikib0 Aug 23, 2025
c5ceea8
Merge pull request #1634 from PackRat-AI/feat/landing-page-add-guides…
andrew-bierman Aug 23, 2025
87799a7
Merge pull request #1636 from PackRat-AI/fix/catalog-categories
mikib0 Aug 23, 2025
06e4ffa
Merge branch 'development' into fix/weather-api-adding-different-loca…
Isthisanmol Aug 24, 2025
bf8276c
validate numeric id and avoid mutating API response
Isthisanmol Aug 24, 2025
fb44b98
fix(packs): handle image display for non user owned pack items
mikib0 Aug 24, 2025
b7aa2ba
refactor(CachedImage): add component documentation for clarity
mikib0 Aug 24, 2025
762cd2a
Merge pull request #1638 from PackRat-AI/fix/patch-non-user-item-imag…
mikib0 Aug 24, 2025
165e3ee
fix(etl): enhance workflow to handle multiline CSV parsing
mikib0 Aug 24, 2025
f5a27e7
fix(ChatBubble): remove AI message dark mode bg as well
mikib0 Aug 24, 2025
f4cfe6b
Merge branch 'development' into fix/ai-message-bubble
Isthisanmol Aug 24, 2025
90be203
chore: temporarily disable env validation postinstall
mikib0 Aug 24, 2025
5d8c9e3
Merge pull request #1639 from PackRat-AI/fix/ai-message-bubble
Isthisanmol Aug 24, 2025
f7eae01
Merge pull request #1640 from PackRat-AI/chore/disable-env-validation…
mikib0 Aug 24, 2025
22c1122
Merge branch 'development' into fix/weather-api-adding-different-loca…
Isthisanmol Aug 24, 2025
be7271f
Merge pull request #1631 from PackRat-AI/fix/weather-api-adding-diffe…
andrew-bierman Aug 24, 2025
d79c363
Merge pull request #1632 from PackRat-AI/copilot/fix-1600
andrew-bierman Aug 24, 2025
d6d7740
chore: revert "temporarily disable env validation postinstall"
mikib0 Aug 24, 2025
893c6fd
chore: temporarily disable env validation on deployment
mikib0 Aug 24, 2025
b71d760
Merge pull request #1642 from PackRat-AI/chore/disable-env-validation…
mikib0 Aug 24, 2025
81c974d
Initial plan
Copilot Aug 24, 2025
d6c8b5a
Initial assessment of lint and type errors
Copilot Aug 24, 2025
ffd597f
Fix form validation and image component errors in expo app
Copilot Aug 24, 2025
ffa805d
Fix weather component type errors and continue API fixes
Copilot Aug 24, 2025
56c65fb
Complete major type error fixes - reduced from 61 to 27 errors
Copilot Aug 24, 2025
67f9dd9
Merge pull request #1643 from PackRat-AI/copilot/fix-dce3cc4e-5fea-4c…
andrew-bierman Aug 24, 2025
2bd12e4
hide placeholder on ios
Isthisanmol Aug 24, 2025
04aceac
Merge pull request #1644 from PackRat-AI/fix/catalog-search-screen
Isthisanmol Aug 24, 2025
7f8c0d4
fix(etl): update ETL job progress tracking logic
mikib0 Aug 24, 2025
ada363d
fix(etl): enhance etl to process larger batch for higher efficiency
mikib0 Aug 24, 2025
b87a6e0
fix(api): crank up CPU limit to 10 minutes to ensure we have abundant…
mikib0 Aug 24, 2025
51bacd2
Merge branch 'development' into fix/etl-memory-limit
mikib0 Aug 24, 2025
b2b2508
Merge pull request #1625 from PackRat-AI/fix/etl-memory-limit
mikib0 Aug 25, 2025
b657964
Merge branch 'main' into development
mikib0 Aug 25, 2025
842bb86
chore: bump version to v2.0.5
mikib0 Aug 25, 2025
2c6594f
Merge pull request #1645 from PackRat-AI/chore/v2.0.5
mikib0 Aug 25, 2025
6d0f481
chore: lower cpu limit to 300 sec max limit to resolve deployment fai…
mikib0 Aug 25, 2025
1962375
Merge pull request #1647 from PackRat-AI/chore/cpu-time-limit
mikib0 Aug 25, 2025
ef1eb07
fix(etl): drastically lower batch size and implement aggressive event…
mikib0 Aug 25, 2025
ecb3539
Merge pull request #1648 from PackRat-AI/fix/etl-memory-limit-2
mikib0 Aug 25, 2025
42605d8
Merge pull request #1646 from PackRat-AI/development
andrew-bierman Aug 25, 2025
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
45 changes: 45 additions & 0 deletions .github/workflows/api-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ permissions:
jobs:
api-tests:
runs-on: ubuntu-latest

services:
postgres:
image: pgvector/pgvector:pg15
env:
POSTGRES_DB: packrat_test
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_password
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5433:5432
options: >-
--health-cmd "pg_isready -U test_user -d packrat_test"
--health-interval 5s
--health-timeout 5s
--health-retries 5

steps:
- uses: actions/checkout@v4

Expand All @@ -28,5 +45,33 @@ jobs:
PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN: ${{ secrets.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN }}
run: bun install

- name: Run database migrations
env:
NEON_DATABASE_URL: postgres://test_user:test_password@localhost:5433/packrat_test
run: |
cd packages/api
bun run migrate

- name: Run API tests
env:
# Test database configuration
NEON_DATABASE_URL: postgres://test_user:test_password@localhost:5433/packrat_test
NEON_DATABASE_URL_READONLY: postgres://test_user:test_password@localhost:5433/packrat_test
# Other test environment variables (from test setup)
ENVIRONMENT: development
SENTRY_DSN: https://test@test.ingest.sentry.io/test
JWT_SECRET: secret
PASSWORD_RESET_SECRET: secret
GOOGLE_CLIENT_ID: test-client-id
ADMIN_USERNAME: admin
ADMIN_PASSWORD: admin-password
PACKRAT_API_KEY: test-api-key
EMAIL_PROVIDER: resend
RESEND_API_KEY: key
EMAIL_FROM: test@example.com
OPENAI_API_KEY: sk-test-key
AI_PROVIDER: openai
PERPLEXITY_API_KEY: pplx-test-key
OPENWEATHER_KEY: test-weather-key
WEATHER_API_KEY: test-weather-key
run: bun test --cwd packages/api
2 changes: 1 addition & 1 deletion apps/expo/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default (): ExpoConfig =>
{
name: 'PackRat',
slug: 'packrat',
version: '2.0.4',
version: '2.0.5',
scheme: 'packrat',
web: {
bundler: 'metro',
Expand Down
58 changes: 27 additions & 31 deletions apps/expo/app/(app)/ai-chat.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { type UIMessage, useChat } from '@ai-sdk/react';
import { Button, Text } from '@packrat/ui/nativewindui';
import { ActivityIndicator, Button, Text } from '@packrat/ui/nativewindui';
import { Icon } from '@roninoss/icons';
import { FlashList } from '@shopify/flash-list';
import { DefaultChatTransport, type TextUIPart } from 'ai';
import { fetch as expoFetch } from 'expo/fetch';
import { clientEnvs } from 'expo-app/env/clientEnvs';
import { ChatBubble } from 'expo-app/features/ai/components/ChatBubble';
import { ErrorState } from 'expo-app/features/ai/components/ErrorState';
import { tokenAtom } from 'expo-app/features/auth/atoms/authAtoms';
import { LocationSelector } from 'expo-app/features/weather/components/LocationSelector';
import { useActiveLocation } from 'expo-app/features/weather/hooks';
Expand All @@ -17,7 +18,6 @@ import { useAtomValue } from 'jotai';
import * as React from 'react';
import { useEffect } from 'react';
import {
Alert,
Dimensions,
Keyboard,
type NativeSyntheticEvent,
Expand Down Expand Up @@ -72,9 +72,7 @@ export default function AIChat() {
const insets = useSafeAreaInsets();
const { progress } = useReanimatedKeyboardAnimation();
const textInputHeight = useSharedValue(17);
const translateX = useSharedValue(0);
const params = useLocalSearchParams();
const [showSuggestions, setShowSuggestions] = React.useState(true);
const { activeLocation } = useActiveLocation();
const listRef = React.useRef<FlashList<UIMessage>>(null);

Expand All @@ -92,7 +90,9 @@ export default function AIChat() {

const token = useAtomValue(tokenAtom);
const [input, setInput] = React.useState('');
const { messages, error, sendMessage, status } = useChat({
const [lastUserMessage, setLastUserMessage] = React.useState('');
const [previousMessages, setPreviousMessages] = React.useState<UIMessage[]>([]);
const { messages, setMessages, error, sendMessage, status } = useChat({
transport: new DefaultChatTransport({
fetch: expoFetch as unknown as typeof globalThis.fetch,
api: `${clientEnvs.EXPO_PUBLIC_API_URL}/api/chat`,
Expand All @@ -114,29 +114,21 @@ export default function AIChat() {
parts: [{ type: 'text', text: getContextualGreeting(context) }],
} as UIMessage,
],
onFinish: () => {
// Hide suggestions after user sends a message
setShowSuggestions(false);
},
});

const isLoading = status === 'streaming';
const isLoading = status === 'submitted' || status === 'streaming';

const handleSubmit = () => {
sendMessage({ text: input });
const handleSubmit = (text?: string) => {
const messageText = text || input;
setLastUserMessage(messageText);
setPreviousMessages(messages);
sendMessage({ text: messageText });
setInput('');
};

React.useEffect(() => {
if (error) {
Alert.alert(error.message);
}
}, [error]);

const handleSuggestionPress = (suggestion: string) => {
sendMessage({ text: suggestion });
setInput('');
setShowSuggestions(false);
const handleRetry = () => {
setMessages(previousMessages);
sendMessage({ text: lastUserMessage });
};

const toolbarHeightStyle = useAnimatedStyle(() => ({
Expand Down Expand Up @@ -174,7 +166,6 @@ export default function AIChat() {
behavior="padding"
>
<FlashList
// inverted
ref={listRef}
estimatedItemSize={70}
ListHeaderComponent={
Expand All @@ -193,14 +184,14 @@ export default function AIChat() {
}
ListFooterComponent={
<>
{showSuggestions && messages.length <= 2 && (
{messages.length < 2 && (
<View className="px-4 py-4">
<Text className="mb-2 text-xs text-muted-foreground">SUGGESTIONS</Text>
<View className="flex-row flex-wrap gap-2">
{getContextualSuggestions(context).map((suggestion) => (
<TouchableOpacity
key={suggestion}
onPress={() => handleSuggestionPress(suggestion)}
onPress={() => handleSubmit(suggestion)}
className="mb-2 rounded-full border border-border bg-card px-3 py-2"
>
<Text className="text-sm text-foreground">{suggestion}</Text>
Expand All @@ -209,6 +200,14 @@ export default function AIChat() {
</View>
</View>
)}
{status === 'submitted' && (
<ActivityIndicator
size="small"
color={colors.primary}
className="self-start ml-4 mb-8"
/>
)}
{status === 'error' && <ErrorState error={error} onRetry={() => handleRetry()} />}
<Animated.View style={toolbarHeightStyle} />
</>
}
Expand All @@ -224,10 +223,10 @@ export default function AIChat() {
let userQuery: TextUIPart['text'] | undefined;
if (item.role === 'assistant' && index > 1) {
const userMessage = messages[index - 1];
userQuery = userMessage.parts.find((p) => p.type === 'text')?.text;
userQuery = userMessage?.parts.find((p) => p.type === 'text')?.text;
}

return <ChatBubble item={item} translateX={translateX} userQuery={userQuery} />;
return <ChatBubble item={item} userQuery={userQuery} />;
}}
/>
</KeyboardAvoidingView>
Expand All @@ -238,7 +237,6 @@ export default function AIChat() {
handleInputChange={setInput} // Pass the setter directly.
handleSubmit={() => {
handleSubmit();
setShowSuggestions(false);
}}
isLoading={isLoading}
placeholder={
Expand Down Expand Up @@ -332,9 +330,7 @@ function Composer({
/>
<View className="absolute bottom-3 right-5">
{isLoading ? (
<View className="h-7 w-7 items-center justify-center">
<Text className="text-xs text-primary">...</Text>
</View>
<ActivityIndicator size="small" color={colors.primary} />
) : input.length > 0 ? (
<Button
onPress={handleSubmit}
Expand Down
26 changes: 26 additions & 0 deletions apps/expo/atoms/atomWithKvStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Storage from 'expo-sqlite/kv-store';
import { atom } from 'jotai';

export const atomWithKvStorage = <T>(key: string, initialValue: T) => {
const baseAtom = atom(initialValue);

baseAtom.onMount = (setValue) => {
(async () => {
const item = await Storage.getItem(key);
setValue(item ? JSON.parse(item) : initialValue);
})();
};

const derivedAtom = atom(
(get) => get(baseAtom),
(get, set, update) => {
const nextValue = typeof update === 'function' ? update(get(baseAtom)) : update;

set(baseAtom, nextValue);

Storage.setItem(key, JSON.stringify(nextValue));
},
);

return derivedAtom;
};
53 changes: 53 additions & 0 deletions apps/expo/components/Markdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useColorScheme } from '@packrat-ai/nativewindui';
import RNMarkdown from '@ronradtke/react-native-markdown-display';

export function Markdown({ children }: { children: string }) {
const { colors } = useColorScheme();

const markdownStyles = {
body: {
color: colors.foreground,
fontSize: 16,
},
heading1: {
color: colors.foreground,
fontSize: 28,
fontWeight: '700',
marginTop: 24,
marginBottom: 16,
},
heading2: {
color: colors.foreground,
fontSize: 24,
fontWeight: '600',
marginTop: 20,
marginBottom: 12,
},
heading3: {
color: colors.foreground,
fontSize: 20,
fontWeight: '600',
marginTop: 16,
marginBottom: 8,
},
paragraph: {
marginTop: 0,
marginBottom: 16,
},
strong: {
fontWeight: '600' as const,
},
link: {
color: colors.primary,
textDecorationLine: 'underline' as const,
},
blockquote: {
backgroundColor: colors.grey6,
borderLeftColor: colors.primary,
borderLeftWidth: 4,
paddingLeft: 16,
},
};

return <RNMarkdown style={markdownStyles}>{children}</RNMarkdown>;
}
26 changes: 21 additions & 5 deletions apps/expo/components/initial/ItemCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type ItemCardProps = {

export function ItemCard({ item, onPress }: ItemCardProps) {
// Get weight unit
const weightUnit = (item as PackItem).weightUnit || (item as CatalogItem).defaultWeightUnit;
const weightUnit = (item as PackItem).weightUnit || (item as CatalogItem).weightUnit;

// Use the utility functions
const totalWeight = calculateTotalWeight(item);
Expand All @@ -36,12 +36,22 @@ export function ItemCard({ item, onPress }: ItemCardProps) {
onPress={() => onPress(item)}
>
<View className="flex-row">
{item.image ? (
<Image source={{ uri: item.image }} className="h-24 w-24" resizeMode="cover" />
{(item as PackItem).image || (item as CatalogItem).images?.[0] ? (
<Image
source={{ uri: (item as PackItem).image || (item as CatalogItem).images?.[0] }}
className="h-24 w-24"
resizeMode="cover"
/>
) : (
<View className="h-24 w-24 items-center justify-center bg-muted">
<Icon
name={getCategoryIcon(item.category) as MaterialIconName}
name={
getCategoryIcon(
(item as PackItem).category ||
(item as CatalogItem).categories?.[0] ||
'miscellaneous',
) as MaterialIconName
}
size={32}
color="text-muted-foreground"
/>
Expand All @@ -64,7 +74,13 @@ export function ItemCard({ item, onPress }: ItemCardProps) {
</View>

<View className="mb-2 flex-row items-center">
<CategoryBadge category={item.category} />
<CategoryBadge
category={
(item as PackItem).category ||
(item as CatalogItem).categories?.[0] ||
'miscellaneous'
}
/>
{isItemConsumable && (
<View className="ml-2 rounded-full bg-amber-100 px-2 py-0.5">
<Text className="text-xs text-amber-800">Consumable</Text>
Expand Down
Loading
Loading