|
@@ -1,8 +1,9 @@
|
|
|
---
|
|
---
|
|
|
-description:
|
|
|
|
|
|
|
+description: Dashboard package
|
|
|
globs: packages/dashboard/**/*
|
|
globs: packages/dashboard/**/*
|
|
|
alwaysApply: false
|
|
alwaysApply: false
|
|
|
---
|
|
---
|
|
|
|
|
+
|
|
|
The project in the /packages/dashboard dir uses the following stack. Please make sure to use these in any solutions:
|
|
The project in the /packages/dashboard dir uses the following stack. Please make sure to use these in any solutions:
|
|
|
|
|
|
|
|
- React
|
|
- React
|
|
@@ -10,6 +11,8 @@ The project in the /packages/dashboard dir uses the following stack. Please make
|
|
|
- TanStack Query for data fetching, i.e. useQuery or useMutation. Not Apollo Client.
|
|
- TanStack Query for data fetching, i.e. useQuery or useMutation. Not Apollo Client.
|
|
|
- TanStack router for any routing & navigation
|
|
- TanStack router for any routing & navigation
|
|
|
|
|
|
|
|
|
|
+## API Interaction
|
|
|
|
|
+
|
|
|
When creating useQuery or useMutation calls, use the following pattern as a guide:
|
|
When creating useQuery or useMutation calls, use the following pattern as a guide:
|
|
|
|
|
|
|
|
```
|
|
```
|
|
@@ -43,6 +46,61 @@ export function MyComponent() {
|
|
|
}
|
|
}
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
+When performing mutations, use this example as a guide:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { graphql } from '@/graphql/graphql.js';
|
|
|
|
|
+import { api } from '@/graphql/api.js';
|
|
|
|
|
+import { useMutation } from '@tanstack/react-query';
|
|
|
|
|
+
|
|
|
|
|
+const createProductOptionsMutation = graphql(`
|
|
|
|
|
+ mutation CreateOptionGroups($input: CreateProductOptionGroupInput!) {
|
|
|
|
|
+ createProductOptionGroup(input: $input) {
|
|
|
|
|
+ id
|
|
|
|
|
+ name
|
|
|
|
|
+ options {
|
|
|
|
|
+ id
|
|
|
|
|
+ code
|
|
|
|
|
+ name
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+`);
|
|
|
|
|
+
|
|
|
|
|
+export function MyComponent() {
|
|
|
|
|
+ // Note that explicit typings or generic params should _not_ be needed since the
|
|
|
|
|
+ // type info will flow from the use of the `graphql` function, which uses gql.tada.
|
|
|
|
|
+ const createOptionGroupMutation = useMutation({
|
|
|
|
|
+ // note that variables are not passed at this point of declaration
|
|
|
|
|
+ mutationFn: api.mutate(createProductOptionsMutation),
|
|
|
|
|
+ onSuccess: () => {
|
|
|
|
|
+ // whatever makes sense, e.g. show toast
|
|
|
|
|
+ },
|
|
|
|
|
+ onError: () => {
|
|
|
|
|
+ // whatever makes sense
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // ...
|
|
|
|
|
+
|
|
|
|
|
+ function handleClick() {
|
|
|
|
|
+ // variables are passed here
|
|
|
|
|
+ createOptionGroupMutation.mutate({
|
|
|
|
|
+ input: {
|
|
|
|
|
+ // etc
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //...
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Package Layout
|
|
|
|
|
+
|
|
|
The architecture of the dashboard is as follows:
|
|
The architecture of the dashboard is as follows:
|
|
|
|
|
|
|
|
- /src/lib contains shared code that is used across the dashboard.
|
|
- /src/lib contains shared code that is used across the dashboard.
|
|
@@ -57,4 +115,44 @@ are CRUD list/detail pages.
|
|
|
These examples show the common components, hooks and patterns that should be used across the app.
|
|
These examples show the common components, hooks and patterns that should be used across the app.
|
|
|
|
|
|
|
|
In the "lib" context, we try to re-use components from the /src/lib/components dir, including preferring the Shadcn components
|
|
In the "lib" context, we try to re-use components from the /src/lib/components dir, including preferring the Shadcn components
|
|
|
-as much as possible from the /src/lib/components/ui dir.
|
|
|
|
|
|
|
+as much as possible from the /src/lib/components/ui dir.
|
|
|
|
|
+
|
|
|
|
|
+## Forms
|
|
|
|
|
+
|
|
|
|
|
+We have a special wrapper around the Shadcn react-hook-form components to make typical form controls
|
|
|
|
|
+more concise:
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+ <FormFieldWrapper
|
|
|
|
|
+ control={form.control}
|
|
|
|
|
+ name="facetValueIds"
|
|
|
|
|
+ label={<Trans>Facet values</Trans>}
|
|
|
|
|
+ render={({ field }) => (
|
|
|
|
|
+ <AssignedFacetValues facetValues={entity?.facetValues ?? []} {...field} />
|
|
|
|
|
+ )}
|
|
|
|
|
+/>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Please prefer this form over the raw Shadcn components where possible.
|
|
|
|
|
+
|
|
|
|
|
+## Localization
|
|
|
|
|
+
|
|
|
|
|
+Any labels or user-facing messages should use localization following this example:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Trans, useLingui } from '@/lib/trans.js';
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+export function MyComponent() {
|
|
|
|
|
+
|
|
|
|
|
+ const { i18n } = useLingui();
|
|
|
|
|
+
|
|
|
|
|
+ const message = i18n.t('This is a localized string')
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <Trans>This is a localized string in the markup</Trans>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|