# Swapy # Client-side Stack - Vue 3 - Typescript - Pinia as State management - Axios for requests - Vite build tool # API & Types Work in progress.. ## User ### Standard Registration/Login, say, - `/auth/login/` .etc. - Preferrably jwt strategy. - Register -> email confirmation - Reset password email with token Initial user `status: 'inactive'`, i.e. 'being moderated' ### `/profile/` answer: `{ current: User, onModeration: Member }` **User** might be **Admin**, then send only `current` - Delete the account **DELETE** `/profile/` - which actually sets user's status to `blocked` - Change Password - request `/profile/reset-password/` with new password - then `/profile/reset-password/confirm/` with code from an email message - https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=546%3A27323 ### Request account change`/profile/request-change/` To change other fields the user has to be a **Member** payload: `{ newDate: Partial<Member> }` **Fields that can't change** - email - avatar - phone (?) *being discussed* After the first `/profile/request-change/` admin can activate user (set status to 'active') ### Delete account **DELETE** `/profile/` Change user's status to 'blocked' ### Bank Account #### To add a new account - use `/profile/request-change/` #### To delete - DELETE `/profile/bank-account/:id` - Can't delete if it's the only account in user.bankAccounts ### Types ```ts export type Role = 0 | 1 | 2 /* * 0 - admin | 'Администратор' * 1 - moderator | 'Модератор' * 2 - member | 'Пользователь' */ export type Status = 0 | 1 | 2 | 3 /* * 0 - active | Активен * 1 - inactive (being moderated) | На модерации * 2 - blocked | Заблокирован * 3 - not verified | Не подтверждён */ export type User = { id: string role: Role status: Status // i.e. dispayed text statusText?: string roleText?: string fullName: string phone: string email: string avatar?: string // url dateCreated?: string } export type MemberInfo = { rating?: number nickname?: string // in UX can be edited in the admin panel only fullNameLatin?: string birthDate?: string // iso registrationAddress?: string certifyingDocument?: { country: string number: string // e.g. series and number of passport dateOfIssue: string // iso overdueDate: string // or should it be a number? agency: string } verifiyingDocuments?: { // js 'File' object + url url: string name: string size: number lastModified: number }[] favorites: string[] // ids of favorite offers (transactions) bankAccounts: BankAccount[] } export type Member = User & MemberInfo ``` **BankAccount** ```ts type BankAccountBase = { id: string // e.g. 'russia', 'europe' (for EU), 'australia' // corresponds to countries' icons' names country: string bankName: string currency: string bic: string fullName: string } export type EuroBankAccount = BankAccountBase & { iban: string } export type RussianBankAccount = BankAccountBase & { checkingAccount: string correspondentAccount: string inn: string kpp: string } export type BankAccount = EuroBankAccount | RussianBankAccount ``` ## Transactions (Offers) ```ts export type OfferShort = { id: string type?: OfferType number?: string dateCreated?: string // iso rating?: number // of the creator offerValidDates?: { startDate: string // iso endDate: string // iso } fromCountry: { label?: string name: string price: string currency: string } toCountry: { label?: string name: string price: string currency: string } } export type Offer = OfferShort & { userId?: string // creator of the offer bankAccount?: BankAccount // of the creator } export type OfferType = 'draft' | 'rejected' | 'published' | 'overdue' | 'cancelled' | 'to-sign' | 'to-sign-for-partner' | 'to-prove-payment' | 'awaiting-transaction' | 'refund' | 'success' | 'overdue-payment' | // extra 'accept-transaction-preview' | 'preview' | 'regular' ``` ### POST `/offers/` payload: `Offer` - For Russia only `ruble` as `currency` - For Countries from European Union - `euro` ### `/offers/` Search with filters https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=11:3A208 Payload ```ts export type OffersSearchRequest = { fromCountry: string toCountry: string currency: string // in toCountry fromPrice: string toPrice: string offerValidStartDate: string offerValidEndDate: string offerNumber: string } ``` Return ```ts export type OffersSearchResponse = { page: number totalPages: number results: OfferShort[] } ``` ### `/like-offer/:id` --- ### `/offers/:id/` CRUD ![](https://i.imgur.com/uXR1vnK.png) ### `/profile/offers/` https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=53%3A6950 Filters - tag name. `Tag` is the same as `OfferType` but some `OfferType`'s are not present in the page above ### `/profile/favorite/` - `Offer`s with `starred` being `true` ## Documents https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=585%3A51291 There are 3 documents. - Between person A and B - With Escrow agent in country 2 - Payment requisites So there should be endpoints for all 3 files. Generated on some storage service, I guess. Examples on page https://transcend-swapy.netlify.app/my-transactions/8 Document between person A and B have 4 stages (4 different versions) - not signed - signed with person A - signed with person B - signed by both ## TODO: generate on client or backend? Backend - It's hard to generate this (.doc) kind of html on frontend to convert to PDF ## Notifications: TODO ![](https://i.imgur.com/FCrB8eR.png) # Admin Api ## Users ### `/admin/users/` https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=1986%3A51089 Returns users. Perhaps, a short version **UserShort** fields - username - fullName - status - transactions count - rating - registration date Filters - sort by any given field ascending/descending - pagination with custom page size ### `/admin/users/:id` CRUD on User \+ **extra** info: - user's last actions ### `/admin/staff/` & `/admin/staff/:id` Same for staff members ## Transactions (offers) ### `/admin/offers/` https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=2002%3A55406 Same as `/admin/users/` But different fields May send short version for a table with fields as in the design. **Also** -![](https://i.imgur.com/gbqKpc3.png) - quantity of offer types - search by offer type ### `/admin/offers/:id` https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=2056%3A55867 Detailed info on offer Actions - Accept offer's payment - Decline offer's payment ### `/admin/users/:id/offers/` Same as `/admin/offers/` but for a particular user Or leave only `/admin/offers/` with user id filter ### `/admin/transfers/` https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=2079%3A59854 Where users pays us Search by country ### `/admin/payments/` https://www.figma.com/file/1RVUck0awrwv59rkjtWFKa/swapy?node-id=2079%3A65333 Where we pay users # Chat One on one chat between a member and a staff member (admin or moderator)