From 43e6973f881662605307002774ed048dd6edf411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Sat, 20 Dec 2025 22:23:35 -0300 Subject: [PATCH] add rybbit --- .../app/routes/orgs/enrollments/submission.py | 10 +- api.saladeaula.digital/template.yaml | 2 +- api.saladeaula.digital/uv.lock | 2 +- .../app/@types/rybbit.d.ts | 53 +++++ .../routes/_.$orgid.billing._index/route.tsx | 186 +++++++++--------- .../routes/_.$orgid.enrollments.add/route.tsx | 83 +++++++- .../app/routes/_.$orgid.scheduled/route.tsx | 4 +- .../app/routes/_.$orgid/route.tsx | 16 +- courses-events/template.yaml | 2 +- enrollments-events/template.yaml | 2 +- id.saladeaula.digital/template.yaml | 2 +- konviva-events/template.yaml | 2 +- layercake/layercake/dynamodb.py | 6 + layercake/pyproject.toml | 2 +- orders-events/template.yaml | 2 +- streams-events/template.yaml | 8 +- users-events/template.yaml | 2 +- 17 files changed, 269 insertions(+), 115 deletions(-) create mode 100644 apps/admin.saladeaula.digital/app/@types/rybbit.d.ts diff --git a/api.saladeaula.digital/app/routes/orgs/enrollments/submission.py b/api.saladeaula.digital/app/routes/orgs/enrollments/submission.py index cd74239..c436a64 100644 --- a/api.saladeaula.digital/app/routes/orgs/enrollments/submission.py +++ b/api.saladeaula.digital/app/routes/orgs/enrollments/submission.py @@ -1,7 +1,7 @@ from aws_lambda_powertools import Logger from aws_lambda_powertools.event_handler.api_gateway import Router from aws_lambda_powertools.event_handler.exceptions import NotFoundError -from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair +from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair, PartitionKey from boto3clients import dynamodb_client from config import ENROLLMENT_TABLE @@ -11,6 +11,14 @@ router = Router() dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client) +@router.get('//enrollments/submissions') +def submissions(org_id: str): + return dyn.collection.query( + PartitionKey(f'SUBMISSION#ORG#{org_id}'), + projection_expr='id, sk, created_by', + ) + + @router.get('//enrollments//submitted') def submitted(org_id: str, submission_id: str): return dyn.collection.get_item( diff --git a/api.saladeaula.digital/template.yaml b/api.saladeaula.digital/template.yaml index 9ca5639..959b181 100644 --- a/api.saladeaula.digital/template.yaml +++ b/api.saladeaula.digital/template.yaml @@ -26,7 +26,7 @@ Globals: Architectures: - x86_64 Layers: - - !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:100 + - !Sub arn:aws:lambda:sa-east-1:336641857101:layer:layercake:103 Environment: Variables: TZ: America/Sao_Paulo diff --git a/api.saladeaula.digital/uv.lock b/api.saladeaula.digital/uv.lock index e5dc835..7c08be1 100644 --- a/api.saladeaula.digital/uv.lock +++ b/api.saladeaula.digital/uv.lock @@ -667,7 +667,7 @@ wheels = [ [[package]] name = "layercake" -version = "0.11.3" +version = "0.11.4" source = { directory = "../layercake" } dependencies = [ { name = "arnparse" }, diff --git a/apps/admin.saladeaula.digital/app/@types/rybbit.d.ts b/apps/admin.saladeaula.digital/app/@types/rybbit.d.ts new file mode 100644 index 0000000..a782050 --- /dev/null +++ b/apps/admin.saladeaula.digital/app/@types/rybbit.d.ts @@ -0,0 +1,53 @@ +interface Rybbit { + /** + * Tracks a page view + */ + pageview: () => void + + /** + * Tracks a custom event + * @param name Name of the event + * @param properties Optional properties for the event + */ + event: (name: string, properties?: Record) => void + + /** + * Sets a custom user ID for tracking logged-in users + * @param userId The user ID to set (will be stored in localStorage) + * @param traits Optional user metadata (email, name, custom fields) + */ + identify: (userId: string, traits?: Record) => void + + /** + * Updates traits for the currently identified user + * @param traits User metadata to merge with existing traits + */ + setTraits: (traits: Record) => void + + /** + * Clears the stored user ID + */ + clearUserId: () => void + + /** + * Gets the currently set user ID + * @returns The current user ID or null if not set + */ + getUserId: () => string | null + + /** + * Manually tracks outbound link clicks + * @param url The URL of the outbound link + * @param text Optional text content of the link + * @param target Optional target attribute of the link + */ + trackOutbound: (url: string, text?: string, target?: string) => void +} + +declare global { + interface Window { + rybbit: Rybbit + } +} + +export {} diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx index e28d52c..d60ae10 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx @@ -208,102 +208,100 @@ function List({ items, search }) { } return ( -
- - {charges.length ? ( - <> - - - Colaborador - Curso - Matriculado por - Matriculado em - Valor unit. - - - - {charges?.map( - ( - { user, course, author: created_by, unit_price, enrolled_at }, - index - ) => ( - - - {user.name} - - - {course.name} - - - {created_by ? created_by.name : 'N/A'} - - - {enrolled_at} - - - {unit_price} - - - ) - )} - - - ) : null} +
+ {charges.length ? ( + <> + + + Colaborador + Curso + Matriculado por + Matriculado em + Valor unit. + + + + {charges?.map( + ( + { user, course, author: created_by, unit_price, enrolled_at }, + index + ) => ( + + + {user.name} + + + {course.name} + + + {created_by ? created_by.name : 'N/A'} + + + {enrolled_at} + + + {unit_price} + + + ) + )} + + + ) : null} - {credits.length ? ( - <> - - - - Cancelado por - Cancelado em - - - - {credits?.map( - ( - { user, course, author: canceled_by, unit_price, created_at }, - index - ) => ( - - - {user.name} - - - {course.name} - - - {canceled_by ? canceled_by.name : 'N/A'} - - - {created_at} - - - {unit_price} - - - ) - )} - - - ) : null} + {credits.length ? ( + <> + + + + Cancelado por + Cancelado em + + + + {credits?.map( + ( + { user, course, author: canceled_by, unit_price, created_at }, + index + ) => ( + + + {user.name} + + + {course.name} + + + {canceled_by ? canceled_by.name : 'N/A'} + + + {created_at} + + + {unit_price} + + + ) + )} + + + ) : null} - - - - Total - - - - {filtered - ?.filter((x) => 'course' in x) - ?.reduce((acc, { unit_price }) => acc + unit_price, 0)} - - - - -
-
+ + + + Total + + + + {filtered + ?.filter((x) => 'course' in x) + ?.reduce((acc, { unit_price }) => acc + unit_price, 0)} + + + + + ) } diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx index 218c69e..1d431e4 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx @@ -1,6 +1,7 @@ import type { Route } from './+types/route' -import { useToggle } from 'ahooks' +import Fuse from 'fuse.js' +import { useRequest, useToggle } from 'ahooks' import { ErrorMessage } from '@hookform/error-message' import { CalendarIcon, @@ -15,7 +16,8 @@ import { ArrowDownAZIcon, ArrowUpAZIcon, AlertTriangleIcon, - UserIcon + UserIcon, + EllipsisIcon } from 'lucide-react' import { redirect, Link, useParams, useFetcher } from 'react-router' import { Controller, useFieldArray, useForm } from 'react-hook-form' @@ -23,9 +25,10 @@ import { Fragment, use, useEffect, useMemo, useState } from 'react' import { format } from 'date-fns' import { ptBR } from 'react-day-picker/locale' import { zodResolver } from '@hookform/resolvers/zod' -import Fuse from 'fuse.js' import { formatCPF } from '@brazilian-utils/brazilian-utils' +import { pick } from 'ramda' +import { DateTime } from '@repo/ui/components/datetime' import { Avatar, AvatarFallback } from '@repo/ui/components/ui/avatar' import { Abbr } from '@repo/ui/components/abbr' import { @@ -51,6 +54,7 @@ import { } from '@repo/ui/components/ui/input-group' import { Card, + CardAction, CardContent, CardDescription, CardHeader, @@ -75,7 +79,6 @@ import { cloudflareContext } from '@repo/auth/context' import { SearchFilter } from '@repo/ui/components/search-filter' import { formSchema, type Schema, MAX_ITEMS } from './data' -import { pick } from 'ramda' export function meta({}: Route.MetaArgs) { return [{ title: 'Adicionar matrĂ­cula' }] @@ -215,6 +218,9 @@ export default function Route({ Siga os passos abaixo para adicionar novas matrĂ­culas. + + + @@ -731,3 +737,72 @@ function DuplicateRowMultipleTimes({ ) } + +function ActionMenu() { + const { orgid } = useParams() + const [open, { set }] = useToggle() + const { data, runAsync, loading } = useRequest( + async () => { + const r = await fetch(`/~/api/orgs/${orgid}/enrollments/submissions`, { + method: 'GET' + }) + return await r.json() + }, + { manual: true } + ) + + return ( + { + set(open) + await runAsync() + }} + > + + + + +
+ Envios recentes +
+ + + + {loading && ( + + + + )} + + {data?.items?.map(({ sk }, index) => ( + + + + {sk} + + + + ))} + + {data?.items?.length === 0 && ( + Nenhum envio ainda + )} + + + +
+
+ ) +} diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.scheduled/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.scheduled/route.tsx index ab95f05..13b2985 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.scheduled/route.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.scheduled/route.tsx @@ -406,14 +406,16 @@ function Failed({ items = [] }) { } function ActionMenu({ sk }: { sk: string }) { + const [open, { toggle, set }] = useToggle() const { revalidate } = useRevalidator() const onSuccess = () => { revalidate() + set(false) } return ( - +