Skip to content

Commit

Permalink
Merge branch 'develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
hrit2773 authored Feb 17, 2025
2 parents 99da31d + 3fd6849 commit bd24034
Show file tree
Hide file tree
Showing 33 changed files with 101 additions and 2,351 deletions.
10 changes: 0 additions & 10 deletions .example.env
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ REACT_CUSTOM_DESCRIPTION=
# Google Maps API key
REACT_GMAPS_API_KEY=

# Government data API key
REACT_GOV_DATA_API_KEY=

# reCAPTCHA site key
REACT_RECAPTCHA_SITE_KEY=

Expand All @@ -47,16 +44,9 @@ REACT_SENTRY_DSN=
# Sentry environment (default: staging)
REACT_SENTRY_ENVIRONMENT=

# Camera feed, still watching idle timeout (in seconds; default: 180)
REACT_STILL_WATCHING_IDLE_TIMEOUT=

# Camera feed, still watching prompt duration (in seconds; default: 30)
REACT_STILL_WATCHING_PROMPT_DURATION=

# Feature flags
REACT_ENABLE_HCX=true
REACT_ENABLE_ABDM=true
REACT_WARTIME_SHIFTING=true

# JWT token refresh interval (in milliseconds) (default: 5 minutes)
REACT_JWT_TOKEN_REFRESH_INTERVAL=
Expand Down
14 changes: 0 additions & 14 deletions care.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,8 @@ const careConfig = {
gmapsApiKey:
env.REACT_GMAPS_API_KEY || "AIzaSyDsBAc3y7deI5ZO3NtK5GuzKwtUzQNJNUk",

govDataApiKey:
env.REACT_GOV_DATA_API_KEY ||
"579b464db66ec23bdd000001cdd3946e44ce4aad7209ff7b23ac571b",
reCaptchaSiteKey: env.REACT_RECAPTCHA_SITE_KEY,

wartimeShifting: boolean("REACT_WARTIME_SHIFTING"),

stillWatching: {
idleTimeout: env.REACT_STILL_WATCHING_IDLE_TIMEOUT
? parseInt(env.REACT_STILL_WATCHING_IDLE_TIMEOUT)
: 3 * 60,
promptDuration: env.REACT_STILL_WATCHING_PROMPT_DURATION
? parseInt(env.REACT_STILL_WATCHING_PROMPT_DURATION)
: 30,
},

auth: {
tokenRefreshInterval: env.REACT_JWT_TOKEN_REFRESH_INTERVAL
? parseInt(env.REACT_JWT_TOKEN_REFRESH_INTERVAL)
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions public/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"DOMESTIC_HEALTHCARE_SUPPORT__NO_SUPPORT": "No support",
"DOMESTIC_HEALTHCARE_SUPPORT__PAID_CAREGIVER": "Paid caregiver",
"ENCOUNTER_TAB__abdm": "ABDM Records",
"ENCOUNTER_TAB__claims": "Insurance Claims",
"ENCOUNTER_TAB__feed": "Feed",
"ENCOUNTER_TAB__files": "Files",
"ENCOUNTER_TAB__medicines": "Medicines",
Expand Down
264 changes: 1 addition & 263 deletions src/Utils/request/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CARE's data fetching utilities

CARE now uses TanStack Query (formerly React Query) as its data fetching solution. For backward compatibility, we maintain a wrapper `useTanStackQueryInstead` that provides the same API as our previous `useQuery` hook.
CARE now uses TanStack Query (formerly React Query) as its data fetching solution.

## Using TanStack Query (Recommended for new code)

Expand Down Expand Up @@ -178,265 +178,3 @@ function UpdatePatient({ patientId }: { patientId: string }) {
return <PatientForm onSubmit={handleSubmit} />;
}
```

### mutate

`mutate` is our wrapper around the API call functionality that works with TanStack Query's `useMutation`. It:

- Handles request body serialization
- Sets appropriate headers
- Integrates with our global error handling
- Provides TypeScript type safety for your mutation payload

```typescript
interface APICallOptions {
pathParams?: Record<string, string>; // URL parameters
queryParams?: QueryParams; // Query string parameters
body?: TBody; // Request body
silent?: boolean; // Suppress error notifications
headers?: HeadersInit; // Additional headers
}
// Basic usage
useMutation({
mutationFn: mutate(routes.users.create),
});
// With parameters
useMutation({
mutationFn: mutate(routes.users.update, {
pathParams: { id },
silent: true, // Optional: suppress error notifications
}),
});
```

## Migration Guide & Reference

### Understanding the Transition

Our codebase contains two patterns for data fetching:

1. Legacy pattern using `useTanStackQueryInstead` (wrapper around TanStack Query)
2. Modern pattern using TanStack Query directly

### Pattern Comparison

Here's the same API call implemented both ways:

```tsx
// Legacy Pattern (existing code)
function LegacyComponent({ id }) {
const { data, loading, error, refetch } = useTanStackQueryInstead(
UserRoutes.getUser,
{
pathParams: { id },
prefetch: true,
refetchOnWindowFocus: false,
},
);
}
// Modern Pattern (new code)
function ModernComponent({ id }) {
const { data, isLoading, error, refetch } = useQuery({
queryKey: [UserRoutes.getUser.path, id],
queryFn: query(UserRoutes.getUser, {
pathParams: { id },
}),
enabled: true,
refetchOnWindowFocus: false,
});
}
```

### Migration Mapping

When migrating from `useTanStackQueryInstead` to direct TanStack Query usage:

```typescript
// Legacy options -> TanStack Query options
{
prefetch: true -> enabled: true
loading -> isLoading
refetchOnWindowFocus: false -> refetchOnWindowFocus: false
// Response structure
data -> data (direct access, no .data property)
res.status -> Use error handling or onError callback
error -> error
}
```

### Common Patterns

1. **Conditional Fetching**:

```tsx
// Legacy
useTanStackQueryInstead(route, { prefetch: shouldFetch });
// Modern
useQuery({
queryKey: [route.path],
queryFn: query(route),
enabled: shouldFetch,
});
```

2. **With Parameters**:

```tsx
// Legacy
useTanStackQueryInstead(route, {
pathParams: { id },
query: { filter },
});
// Modern
useQuery({
queryKey: [route.path, id, filter],
queryFn: query(route, {
pathParams: { id },
queryParams: { filter },
}),
});
```

3. **Error Handling**:

```tsx
// Legacy
const { error, res } = useTanStackQueryInstead(route);
if (res?.status === 403) handleForbidden();
// Modern
useQuery({
queryKey: [route.path],
queryFn: query(route, {
silent: true, // Optional: suppress error notifications
}),
// Error handling is now done globally
});
```

## Legacy Support: `useTanStackQueryInstead`

For existing code or maintaining consistency with older patterns, use our wrapper around TanStack Query:

```jsx
import { useTanStackQueryInstead } from "@care/request";
import FooRoutes from "@foo/routes";
export default function FooDetails({ children, id }) {
const { res, data, loading, error } = useTanStackQueryInstead(
FooRoutes.getFoo,
{
pathParams: { id },
},
);
if (loading) return <Loading />;
if (res.status === 403) {
navigate("/forbidden");
return null;
}
if (error) {
return <Error error={error} />;
}
return (
<div>
<span>{data.id}</span>
<span>{data.name}</span>
</div>
);
}
```

### API

```ts
useTanStackQueryInstead(route: Route, options?: QueryOptions): ReturnType<useTanStackQueryInstead>;
```

#### `route`

A route object that specifies the endpoint to fetch data from.

```ts
const FooRoutes = {
getFoo: {
path: "/api/v1/foo/{id}/", // 👈 The path to the endpoint. Slug parameters can be specified using curly braces.
method: "GET", // 👈 The HTTP method to use. Optional; defaults to "GET".
TRes: Type<Foo>(), // 👈 The type of the response body (for type inference).
TBody: Type<Foo>(), // 👈 The type of the request body (for type inference).
noAuth: true, // 👈 Whether to skip adding the Authorization header to the request.
},
} as const; // 👈 This is important for type inference to work properly.
```

#### `options`

An object that specifies options for the request.

```ts
const options = {
prefetch: true, // 👈 Whether to prefetch the data when the component mounts.
refetchOnWindowFocus: true, // 👈 Whether to refetch the data when the window regains focus.
// The following options are passed directly to the underlying `request` function.
pathParams: { id: "123" }, // 👈 The slug parameters to use in the path.
query: { limit: 10 }, // 👈 The query parameters to be added to the request URL.
body: { name: "foo" }, // 👈 The body to be sent with the request.
headers: { "X-Foo": "bar" }, // 👈 Additional headers to be sent with the request.
silent: true, // 👈 Whether to suppress notifications for this request.
onResponse: (res) => {
if (res.status === 403) {
navigate("/forbidden");
}
},
};
```

#### Return Type

The hook returns an object with the following properties:

```ts
{
res: Type<TRes> | undefined; // 👈 The response object. `undefined` if the request has not been made yet.
data: TRes | null; // 👈 The response body. `null` if the request has not been made yet.
error: any; // 👈 The error that occurred while making the request if any.
loading: boolean; // 👈 Whether the request is currently in progress.
refetch: () => void; // 👈 A function that can be called to refetch the data.
}
```

## `request`

`request` is a function that allows you to fetch data. It is a wrapper around `fetch` that adds some useful features. It can be used in both React components and non-React code. For fetching data in React components, prefer using TanStack Query or `useTanStackQueryInstead`. For mutations, use `request`.

### `request` usage

```ts
import { request } from "@care/request";
import FooRoutes from "@foo/routes";
export default async function updateFoo(id: string, object: Foo) {
const { res, data } = await request(FooRoutes.updateFoo, {
pathParams: { id },
body: object, // 👈 The body is automatically serialized to JSON.
});
if (res.status === 403) {
navigate("/forbidden");
return null;
}
return data;
}
```
Loading

0 comments on commit bd24034

Please sign in to comment.