# 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

### `/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

# 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**
-
- 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)