Browse Source

query route private routing and orders

asmer 1 month ago
parent
commit
066a877dcd
4 changed files with 86 additions and 8 deletions
  1. 70 2
      src/App.tsx
  2. 3 0
      src/lib/pub/query/index.ts
  3. 3 1
      src/lib/queryRoute/index.tsx
  4. 10 5
      src/lib/router/index.tsx

+ 70 - 2
src/App.tsx

@@ -197,11 +197,53 @@ const LeftMenuItem = ({category:{_id,name}})=>
 //
 //
 
+const Order = ({order: {createdAt, total}, children}) =>
+<div style={{border: '2px solid black', margin: '30px'}}>
+    {console.log(+createdAt)}
+    <h2>{(new Date(+createdAt)).toDateString()} - {total}</h2>
+    {children}
+</div>
+
+const OrderGood = ({orderGood: {good, total, count, price}}) =>
+<div style={{border: '1px dashed gray'}}>
+    {console.log(good.images)}
+    <h3>{good.name}</h3>
+    <Image src={good.images?.[0]?.url} />
+    <h4>{price} x {count} = {total}</h4>
+</div>
+
+
+const PageOrders = ({data}) => {
+    console.log('orders page', data[0])
+    return (
+        <MetaPlate data={data}>
+            <>
+                <Order prop="order" keyDataKey="_id">
+                    <Fragment sourceDataKey="orderGoods">
+                        <OrderGood prop="orderGood" />
+                    </Fragment>
+                </Order>
+            </>
+        </MetaPlate>
+    )
+}
+    /*
+        <MetaPlate data={data}>
+            <Category prop="category" keyDataKey="_id">
+                <Goods sourceDataKey="goods"> 
+                    <Good prop="good" keyDataKey="_id">
+                        <div sourceDataKey="images">
+                            <Image prop="src" sourceDataKey="url"/>
+                        </div>
+                    </Good>
+                </Goods> */
 
 const queryRouteResult = createQueryRoutes({
     query: gql,
     Pending: () => <h1>Loading...</h1>,
-    cacheTimeout: 5000,
+    //cacheTimeout: 5000,
+    getUserRoles: () => authPub.decoded?.sub.acl,
+    fallback: history => history.goBack(),
     queryRoutes: {
         index: {
             path: '/',
@@ -257,16 +299,39 @@ const queryRouteResult = createQueryRoutes({
                     }
                 }
             `, {query: JSON.stringify([{_id}])}],
+        },
+        myOrders: {
+            path: '/orders',
+            roles: ['user'],
+            args: [`query Orders{
+                      OrderFind(query: "[{}]"){
+                        _id total
+                        createdAt
+                        orderGoods{
+                            good {
+                                _id name
+                                images { url }
+                            }
+                            count
+                            total
+                            price
+                        }
+                    }
+                }
+            `],
+            component: PageOrders,
         }
     }
 })
 
+
 const { AllRoutes, 
         queryRoutes: 
             {
                 category: {CategoryLink}, 
                 login: {useLoginMutation, query: loginQuery},
-                user: {query: userQuery}
+                user: {query: userQuery},
+                myOrders: {MyOrdersLink},
             }, 
        queryPub, withQueryFunc, flushCache } = queryRouteResult
 
@@ -312,6 +377,8 @@ const thunkLogin = async ({login, password}) => {
         return;
     }
     authPub.user = myUser.payload
+
+    flushCache()
 }
 
 //authPub.subscribe(() => console.log(JSON.stringify(authPub, null, 4)))
@@ -363,6 +430,7 @@ function App() {
     //useEffect(() => console.log('effect',performance.now()), [payload])
     return (
         <Router history={history}>
+            <MyOrdersLink>Orders</MyOrdersLink>
             <LogoutButton/>
             <LoginForm />
             <AllRoutes />

+ 3 - 0
src/lib/pub/query/index.ts

@@ -232,6 +232,9 @@ export default (options:CreateQueryPubOptions) => {
     const flushCache = () => {
         for (const [promiseName,promiseBranch] of Object.entries(queryPub.queries)){
             for (const [args, promiseState]    of Object.entries(promiseBranch)){
+                if (promiseState.timeoutId){
+                    clearTimeout(promiseState.timeoutId)
+                }
                 promiseState.invalidated = true
                 delete promiseBranch[args]
                 //promiseState.invalidated = true

+ 3 - 1
src/lib/queryRoute/index.tsx

@@ -1,5 +1,5 @@
 import { ComponentType, Fragment } from 'react';
-import { GetUserRolesFunc, NamedRoute, NamedLink, createPrivateRoute } from '../router';
+import { GetUserRolesFunc, NamedRoute, NamedLink, createPrivateRoute, addRoute } from '../router';
 import { Pub } from '../pub';
 import { createQueryPub } from '../pub';
 
@@ -144,6 +144,8 @@ export const createQueryRoutes = (options:CreateQueryRoutesOptions):CreateQueryR
 
         const camelCaseName = name[0].toUpperCase() + name.slice(1)
 
+        addRoute({name, path});
+
         let queryRouteResult:QueryRouteResult = {}
 
         if (args){

+ 10 - 5
src/lib/router/index.tsx

@@ -6,6 +6,8 @@ const routes = {
 
 }
 
+export const addRoute = ({name, path, props}) => routes[name || path] = {...props, path}
+
 export const NamedRoute = ({name, routeName, query, pendingQueryComponent:P, errorQueryComponent:E, errorQueryComponentErrorProp="error", componentQueryResultProp='data', path, component, render, ...props}) => {
     name  ||= routeName
     routes[name || path] = {...props, path}
@@ -22,12 +24,11 @@ export const NamedRoute = ({name, routeName, query, pendingQueryComponent:P, err
 
         useEffect(() => {
             if (query && typeof query === 'function'){
-                if (typeof query.getQueryPubBranch === 'function'){ //if it's queryPub query function
+                if (typeof query.getQueryPubBranch === 'function'){ 
                     query(paramsRef.current)
-                    //flushCache don't affect refresh here, but it must
                     const [queryPub, key] = query.getQueryPubBranch(paramsRef.current)
                     const pubToState = () => {
-                        console.log(queryPub, key, queryPub[key], queryPub[key].invalidated)
+                        //console.log(queryPub, key, queryPub[key], queryPub[key].invalidated)
                         if (!queryPub[key]){ 
                             if (queryError || queryResult){
                                 setQueryError()
@@ -108,7 +109,8 @@ export const NamedLink = ({routeName, name, params, to,...props}) => {
         to            = generatePath(pattern, params)
     }
     else {
-        console.log('no route, hnyk', routes, to)
+        throw new Error(`Route "${name}"not registered`)
+        //console.log('no route, hnyk', routes, to, props)
     }
     return <Link to={to} {...props} />
 }
@@ -148,12 +150,14 @@ export const createPrivateRoute = (getUserRoles:GetUserRolesFunc, defaultFallbac
                 fallback               ||= defaultFallback
                 roles:Array<string>    ||= defaultRouteRoles
 
-                const userRoles:Array<string> = getUserRoles()
+                const userRoles:Array<string> = getUserRoles() || []
 
                 if (!fallback){
                     throw new ReferenceError('fallback or defaultFallback are mandatory for Private Route')
                 }
 
+                console.log('PRIVATE ROUTING', roles, userRoles)
+
                 if (!intersectArrays(roles, userRoles)){
                     if (typeof fallback === 'string')
                         props.history.push(fallback)
@@ -170,6 +174,7 @@ export const createPrivateRoute = (getUserRoles:GetUserRolesFunc, defaultFallbac
                 throw new ReferenceError('getUserRoles are mandatory for Private Routing and it should be a function')
             }
 
+
             return <RouteComponent {...props} component={ComponentWrapper}/>
         }