feat: marketplaces endpoints

This commit is contained in:
2025-10-13 12:48:06 +04:00
parent d8eba188c9
commit 35869e2ea5
16 changed files with 441 additions and 10 deletions

View File

@ -14,3 +14,4 @@ from .deal_product import (
from .deal_service import DealService as DealService
from .product import Product as Product
from .service import Service as Service, ServiceCategory as ServiceCategory
from .marketplace import BaseMarketplace as BaseMarketplace, Marketplace as Marketplace

View File

@ -0,0 +1,32 @@
from typing import TYPE_CHECKING
from sqlalchemy import ForeignKey, JSON
from sqlalchemy.orm import Mapped, mapped_column, relationship
from models.base import BaseModel
from models.mixins import IdMixin, SoftDeleteMixin
if TYPE_CHECKING:
from modules.clients.models import Client
class BaseMarketplace(BaseModel, IdMixin):
__tablename__ = "fulfillment_base_base_marketplaces"
name: Mapped[str] = mapped_column()
icon_url: Mapped[str] = mapped_column()
class Marketplace(BaseModel, IdMixin, SoftDeleteMixin):
__tablename__ = "fulfillment_base_marketplaces"
base_marketplace_id: Mapped[str] = mapped_column(
ForeignKey("fulfillment_base_base_marketplaces.id")
)
base_marketplace: Mapped["BaseMarketplace"] = relationship(lazy="joined")
client_id: Mapped[int] = mapped_column(ForeignKey("clients.id"))
client: Mapped["Client"] = relationship()
name: Mapped[str] = mapped_column()
auth_data: Mapped[dict] = mapped_column(type_=JSON)

View File

@ -1,8 +1,9 @@
from .deal_product import DealProductRepository as DealProductRepository
from .product_service import ProductServiceRepository as ProductServiceRepository
from .deal_service import DealServiceRepository as DealServiceRepository
from .product import ProductRepository as ProductRepository
from .service import ServiceRepository as ServiceRepository
from .services_kit import ServicesKitRepository as ServicesKitRepository
from .service_category import ServiceCategoryRepository as ServiceCategoryRepository
from .barcode_template import BarcodeTemplateRepository as BarcodeTemplateRepository
from .deal_product import DealProductRepository as DealProductRepository
from .deal_service import DealServiceRepository as DealServiceRepository
from .marketplace import MarketplaceRepository as MarketplaceRepository
from .product import ProductRepository as ProductRepository
from .product_service import ProductServiceRepository as ProductServiceRepository
from .service import ServiceRepository as ServiceRepository
from .service_category import ServiceCategoryRepository as ServiceCategoryRepository
from .services_kit import ServicesKitRepository as ServicesKitRepository

View File

@ -0,0 +1,62 @@
from sqlalchemy.orm import joinedload
from modules.clients.models import Client
from modules.fulfillment_base.models import (
Marketplace,
BaseMarketplace,
)
from modules.fulfillment_base.schemas.marketplace import (
CreateMarketplaceSchema,
UpdateMarketplaceSchema,
)
from repositories.mixins import *
class MarketplaceRepository(
RepCrudMixin[Marketplace, CreateMarketplaceSchema, UpdateMarketplaceSchema],
):
session: AsyncSession
entity_class = Marketplace
entity_not_found_msg = "Маркетплейс не найден"
def _process_get_all_stmt_with_args(self, stmt: Select, *args) -> Select:
client_id: int = args[0]
return (
stmt.options(
joinedload(Marketplace.base_marketplace),
joinedload(Marketplace.client),
)
.where(
Marketplace.is_deleted.is_(False), Marketplace.client_id == client_id
)
.order_by(Marketplace.id)
)
def _process_get_by_id_stmt(self, stmt: Select) -> Select:
return stmt.options(
joinedload(Marketplace.base_marketplace), joinedload(Marketplace.client)
)
async def get_base_marketplaces(self) -> list[BaseMarketplace]:
stmt = select(BaseMarketplace)
result = await self.session.execute(stmt)
return list(result.scalars().all())
async def _prepare_create(self, data: CreateMarketplaceSchema) -> dict:
dict_data = data.model_dump()
dict_data["base_marketplace_id"] = data.base_marketplace.id
del dict_data["base_marketplace"]
dict_data["client_id"] = data.client.id
del dict_data["client"]
return dict_data
async def update(
self, template: Marketplace, data: UpdateMarketplaceSchema
) -> Marketplace:
if data.base_marketplace:
data.base_marketplace = BaseMarketplace(
**data.base_marketplace.model_dump()
)
if data.client:
data.client = Client(**data.client.model_dump())
return await self._apply_update_data_to_model(template, data, True)

View File

@ -0,0 +1,66 @@
from fastapi import APIRouter, Path
from backend.dependecies import SessionDependency
from modules.fulfillment_base.schemas.marketplace import *
from modules.fulfillment_base.services import MarketplaceService
router = APIRouter(tags=["marketplace"])
@router.get(
"/base",
response_model=GetBaseMarketplacesResponse,
operation_id="get_base_marketplaces",
)
async def get_base_marketplaces(
session: SessionDependency,
):
return await MarketplaceService(session).get_base_marketplaces()
@router.get(
"/{clientId}",
response_model=GetMarketplacesResponse,
operation_id="get_marketplaces",
)
async def get_marketplaces(
session: SessionDependency, client_id: int = Path(alias="clientId")
):
return await MarketplaceService(session).get_all(client_id)
@router.post(
"/",
response_model=CreateMarketplaceResponse,
operation_id="create_marketplace",
)
async def create_product(
session: SessionDependency,
request: CreateMarketplaceRequest,
):
return await MarketplaceService(session).create(request)
@router.patch(
"/{pk}",
response_model=UpdateMarketplaceResponse,
operation_id="update_marketplace",
)
async def update_marketplace(
session: SessionDependency,
request: UpdateMarketplaceRequest,
pk: int = Path(),
):
return await MarketplaceService(session).update(pk, request)
@router.delete(
"/{pk}",
response_model=DeleteMarketplaceResponse,
operation_id="delete_marketplace",
)
async def delete_marketplace(
session: SessionDependency,
pk: int = Path(),
):
return await MarketplaceService(session).delete(pk)

View File

@ -0,0 +1,77 @@
from typing import Optional
from modules.clients.schemas.client import ClientSchema
from schemas.base import BaseSchema, BaseResponse
# region Entity
class BaseMarketplaceSchema(BaseSchema):
id: int
name: str
icon_url: str
class MarketplaceSchema(BaseSchema):
id: int
base_marketplace_id: int
base_marketplace: BaseMarketplaceSchema
client: ClientSchema
name: str
auth_data: dict
class CreateMarketplaceSchema(BaseSchema):
base_marketplace: BaseMarketplaceSchema
client: ClientSchema
name: str
auth_data: dict
class UpdateMarketplaceSchema(BaseSchema):
base_marketplace: Optional[BaseMarketplaceSchema] = None
client: Optional[ClientSchema] = None
name: Optional[str] = None
auth_data: Optional[dict] = None
# endregion
# region Request
class CreateMarketplaceRequest(BaseSchema):
entity: CreateMarketplaceSchema
class UpdateMarketplaceRequest(BaseSchema):
entity: UpdateMarketplaceSchema
# endregion
# region Response
class GetBaseMarketplacesResponse(BaseSchema):
items: list[BaseMarketplaceSchema]
class GetMarketplacesResponse(BaseSchema):
items: list[MarketplaceSchema]
class CreateMarketplaceResponse(BaseResponse):
entity: MarketplaceSchema
class UpdateMarketplaceResponse(BaseResponse):
pass
class DeleteMarketplaceResponse(BaseResponse):
pass
# endregion

View File

@ -7,3 +7,4 @@ from .services_kit import ServicesKitService as ServicesKitService
from .service_category import ServiceCategoryService as ServiceCategoryService
from .barcode_template import BarcodeTemplateService as BarcodeTemplateService
from .barcode_printer_service import BarcodePrinterService as BarcodePrinterService
from .marketplace import MarketplaceService as MarketplaceService

View File

@ -20,9 +20,6 @@ class BarcodeTemplateService(
def __init__(self, session: AsyncSession):
self.repository = BarcodeTemplateRepository(session)
async def is_soft_delete(self, template: BarcodeTemplate) -> bool:
return True
async def get_attributes(self) -> GetBarcodeAttributesResponse:
attributes = await self.repository.get_attributes()
return GetBarcodeAttributesResponse(

View File

@ -0,0 +1,27 @@
from modules.fulfillment_base.models import Marketplace
from modules.fulfillment_base.repositories import MarketplaceRepository
from modules.fulfillment_base.schemas.marketplace import *
from services.mixins import *
class MarketplaceService(
ServiceCrudMixin[
Marketplace,
MarketplaceSchema,
CreateMarketplaceRequest,
UpdateMarketplaceRequest,
]
):
schema_class = MarketplaceSchema
entity_deleted_msg = "Маркетплейс успешно удален"
entity_updated_msg = "Маркетплейс успешно обновлен"
entity_created_msg = "Маркетплейс успешно создан"
def __init__(self, session: AsyncSession):
self.repository = MarketplaceRepository(session)
async def get_base_marketplaces(self) -> GetBaseMarketplacesResponse:
mps = await self.repository.get_base_marketplaces()
return GetBaseMarketplacesResponse(
items=[BaseMarketplaceSchema.model_validate(mp) for mp in mps]
)

BIN
static/icons/denco.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

1
static/icons/denco.svg Normal file
View File

@ -0,0 +1 @@
<svg id="Слой_1" data-name="Слой 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 791.06 146.29"><path d="M153.64,36a65.78,65.78,0,0,0-27.48-24.75Q108.48,2.43,85.45,2.43H21.19v36.2H53.93V29.3h29.9q21.21,0,33.84,11.82t12.63,32q0,20.2-12.63,32T83.83,117H53.93V105.13H21.19v38.74H85.45q23,0,40.71-8.79a65.78,65.78,0,0,0,27.48-24.75q9.8-16,9.8-37.18T153.64,36Z"/><path d="M220.62,117.6V84.87h65.67V59.41H220.62V28.7H295V2.43H188.09V143.87H297.6V117.6Z"/><path d="M421.06,2.43V88.3L350.74,2.43H323.67V143.87H356V58l70.51,85.88h26.88V2.43Z"/><path d="M556.44,118.41A47.21,47.21,0,0,1,533,112.65a40.87,40.87,0,0,1-16.06-16.06,47.21,47.21,0,0,1-5.76-23.44,47.21,47.21,0,0,1,5.76-23.44A40.87,40.87,0,0,1,533,33.65a47.21,47.21,0,0,1,23.44-5.76q21.21,0,35.56,16.57l21-19.4a66.55,66.55,0,0,0-25-18.59A82.44,82.44,0,0,0,554.82,0Q533,0,515.52,9.4A70.08,70.08,0,0,0,488,35.47q-10,16.67-10,37.68t10,37.68a70.15,70.15,0,0,0,27.48,26.07q17.47,9.39,39.1,9.39A83.2,83.2,0,0,0,588,139.83,65.49,65.49,0,0,0,613,121l-21-19.4Q577.65,118.41,556.44,118.41Z"/><path d="M732.75,105.13a41.07,41.07,0,0,1-9.62,7.52,47.33,47.33,0,0,1-45.26,0A41.29,41.29,0,0,1,662,96.59a47.21,47.21,0,0,1-5.76-23.44A47.21,47.21,0,0,1,662,49.71a41.29,41.29,0,0,1,15.86-16.06,47.33,47.33,0,0,1,45.26,0,40.89,40.89,0,0,1,7,5h39.35c-.53-1-1.09-2-1.68-3A71.4,71.4,0,0,0,740.1,9.5Q722.54,0,700.5,0T660.8,9.5a70.36,70.36,0,0,0-27.68,26.17,71.42,71.42,0,0,0-10,37.48,71.42,71.42,0,0,0,10,37.48A70.43,70.43,0,0,0,660.8,136.8q17.67,9.49,39.7,9.49t39.6-9.49a71.47,71.47,0,0,0,27.69-26.17c1.09-1.8,2.08-3.63,3-5.5Z"/><rect x="715.07" y="45.63" width="75.99" height="52.5"/><rect y="45.63" width="75.98" height="52.5"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
static/icons/ozon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

114
static/icons/ozon.svg Normal file
View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1417.3 1417.3" style="enable-background:new 0 0 1417.3 1417.3;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_00000028286792660517655600000001409180945242151851_);}
.st1{fill:#005BFF;}
.st2{fill:#F91155;}
.st3{fill:none;}
.st4{clip-path:url(#SVGID_00000067924568506772475600000006273407934913832106_);}
.st5{fill:#FFFFFF;}
</style>
<g>
<defs>
<path id="SVGID_1_" d="M1133.9,1417.3H283.5C126.9,1417.3,0,1290.4,0,1133.9V283.5C0,126.9,126.9,0,283.5,0h850.4
c156.6,0,283.5,126.9,283.5,283.5v850.4C1417.3,1290.4,1290.4,1417.3,1133.9,1417.3z"/>
</defs>
<clipPath id="SVGID_00000004505243697409283410000015111137345945702290_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#SVGID_00000004505243697409283410000015111137345945702290_);">
<rect x="0" class="st1" width="1417.3" height="1417.3"/>
</g>
<g style="clip-path:url(#SVGID_00000004505243697409283410000015111137345945702290_);">
<g>
<g>
<g>
<path class="st2" d="M1267.3-251.6C1188-105.6,1135-29.9,981.2,142.6c-23.5,33.5-51.7,61.4-81.9,87.8
C758.7,353.3,618.4,477.3,477.4,599.6c-41.7,36.2-85.5,69.2-128.7,103.5c-25.7,20.4-56.5,31.6-86.6,41.9
C161.6,779.3,61.7,811.7-38.5,846.8c-45,15.8-89.3,35.2-133.5,53.5c-30.9,12.8-54.9,36.4-78.1,60.5
c-55.9,58.3-86,112.4-134.3,205.5c-0.1-3.2-13.2-290.4-13.2-290.4C-337,798-263.7,736-191,678.8c32-25.2,66.5-45.4,100.8-67
c60.6-38.1,115.2-86,166.9-136.5c49.1-47.8,89.3-103.8,128.7-160.5c62.4-89.9,125.8-179.3,193.2-265.2
c33.8-43.1,73.3-80.5,112.6-117.7c50.4-47.7,157.1-156.4,157.1-156.4c0.4,0,185.6-8.4,185.6-8.4c-5.5,6.4-11.1,16.1-13.2,19.6
C818.3-175.1,794.8-138,774-99c-13.2,24.8-21.8,53.2-33.6,78.9c-23.6,51-52,98.1-93.9,134.5c-13.8,12-30,22.6-46.1,30.6
c-33.5,16.6-62.9,38.7-90.7,63.8c-42.1,38-79.9,80.5-117.5,123.4C333,399.6,277,469.5,223.4,541.9c-5.2,7-11.1,13.6-15.7,21.1
c-2.2,3.6-3,8.3-4.6,12.4l1.4,2.6c5.4-1.9,11.6-3.2,16.4-6.2c18-11,36.8-20.9,53.6-33.6c63.6-48.1,127.5-96.8,189.6-147
c32-25.9,60.1-56.8,91.1-84.2c19.1-16.8,40.8-30.4,60.7-46.2c32.7-25.9,65.1-51.3,96.5-79C760.2,139.8,807.9,96.4,854,52
c96-92.8,77.1-195.3,169.3-292.6L1267.3-251.6z"/>
<path class="st2" d="M1574.1,1214.3c-14.8,15.2-22.3,27.1-38,41.3c-12.7,11.5-28.3,20.5-41.8,31.2
c-49.7,39.4-95.7,88.2-150.8,118.9c-41.6,23.2-84.9,39.5-131.6,44.9c-8.3,1-17.4-0.1-25.6-2.1c-10.7-2.6-14.8-12.3-13.6-23.7
c1.9-17.6,10.8-30.9,21.5-43.6c11.7-13.9,23.5-29.6,37.8-40c33.3-24,59.3-54.3,82-88.6c16.3-24.7,31.1-49.7,47.7-74.2
c20-29.7,46.2-53.3,71.4-77.8c59.9-58,117-120.6,180.3-174.3C1613.3,927.9,1575.5,1203.8,1574.1,1214.3z"/>
<path class="st2" d="M1297.7-253.5c0,0-5.2,13.2-9.9,22.5c-49.9,111.6-94.3,215-158,318.6c-54.8,89.1-111.4,176.3-176.6,257.4
c-22.8,28.4-45.9,57.5-75.2,78.8c-45.9,33.4-91.7,65.6-138,98.3c-65.6,46.3-131.8,92.2-192.4,145.8
c-23.9,21.1-46.7,43.5-65.6,70c-14.5,20.3-28.9,41-45.8,59c-68.7,73.6-144.9,138.5-221.7,202.3
c-79.2,65.7-159,130.6-238.9,195.3c-49.7,40.3-100.4,79-155,111.8c-10.9,6.5-23.1,11.4-34.8,16.1
c-1.8,0.7-114.2,45.5-123.3,53.8c0.7,9.4,10.4,145.5,10.7,147.3c1.6-0.9,33.7-26.7,40.1-31.4c46-34.8,70.1-60.6,120.9-86.2
c57.7-29.1,115.6-56,172.2-87.2c129.6-71.9,257.9-148.6,382.9-228.9c57.9-37.2,115.2-74.5,171.5-114.4
C628.3,927.8,687,870,744.3,809.9c70.1-73.6,138.9-148.7,207.2-224.3c46.6-51.6,92.1-105.2,137.5-158.1
c30.4-35.4,60.8-70.5,89.9-107.1c48.7-61.5,89.8-128.1,132.3-194.4c26.2-40.9,53-81.9,82.5-120.1
c75.3-97.6,143.4-191.8,236.3-283.5L1297.7-253.5z"/>
<path class="st2" d="M259.3,75c-63.3,67-125.1,134.1-187,202.5c-33.7,37.4-64.1,77.7-97.4,115.7
c-59.5,67.9-121.1,135-191.4,190.5c-71.3,56.2-148,113-220.7,167.4c-0.2-4.1-8.8-194.7-9-199c30.8-52.2,61.8-111.3,84.7-168
c13.5-33.5,25.4-68.7,39-102.2c26-64.5,60.1-123.5,110.3-170.5c28-26.3,60.2-44.9,93.3-62.6c99.3-53.2,198.5-107.3,298-160
c59.3-31.5,104.2-86.4,157.1-127.9l209.9-9.5C450.8-140.1,358.6-30.1,259.3,75z"/>
<path class="st2" d="M700.3,1624.9c16.3-15.9,31.6-30.3,46.6-45.6c70.1-71.6,149.5-130.4,227.6-191.3
c16.8-13.1,33.3-27.1,49.2-41.5c5.6-5.3,9.8-11.7,13-18.8c2.1-4.5,3.8-11.8,1.4-14.9c-3.1-4-10.6-8-15.3-6.9
c-11.4,2.4-23.6,5.5-33.4,11.8c-56.4,36.3-112,73.5-167.8,110.6c-19,12.7-37.9,27.3-56.8,40c-34.6,23-65,52.1-90.6,85.7
c-16.3,21.5-31.8,37.3-49.3,57.7c-2.1,2.5-7.8,8-11.7,12.1c-13-0.1-206.9-2.3-210.1-2.3c22.6-14.7,48.2-33.1,57.5-40
c101.1-75.7,183-121.7,291-185.1c95.8-56.3,190.3-115,285.1-173c33-20.2,66.7-40.5,91.8-72.2c16.4-20.7,33.5-40.6,49.4-61.8
c51.3-68.4,102-138.7,153.5-207c32.8-43.5,65.6-86.5,105.2-123.5c28.6-26.8,59.2-51.1,88-77.6c57-52.4,42.1-121.8,147.4-283.3
c58.6-89.9,97.4-119.8,129.1-154.1c20.3-22,79.5-55.6,103.3-73.4c-0.2,14.5-0.7,64.3-0.8,74.5c-43.5,37.3-114,140.9-122,199.1
c-28.7,207.7-218,333.3-314.5,457.5c-45.2,58.4-96.7,109.1-151.7,156.9c-36.1,31.4-71,64-99.8,103.2
c-11.6,15.8-19.4,34.5-30,51.2c-34.8,54.4-70.2,108.8-105.6,162.8c-26.4,40-52.7,80.8-82,118.4
c-34.9,44.8-61.6,75.3-98.7,118.2c-1.8,2.1-8.2,10-13,14.8L700.3,1624.9z"/>
<path class="st2" d="M-388.1,1703.1c107.2-75.9,230.4-139.5,343.3-207.1c51.9-31.1,105.2-60,158.5-88.4
c58.6-31.2,117.3-63.4,177.7-90.1c98.4-43.5,187.1-101.6,269.7-171.9c27.4-23.3,51.9-50.8,76.7-77.4
c52.1-55.9,104.8-112.6,155.7-169.7c50.2-56.3,98.4-114,148-170.9c25.7-29.5,53.7-57,85.6-78.9c7-4.6,15.1-7.2,22.9-9.9
c8.1-2.9,13.6,0.6,11.7,9.3c-3.2,14.7-7.6,30.7-14.5,43.7c-23.5,43.4-47.5,85.4-73.2,127.5c-32,52.5-67.9,103.4-107.4,149.8
c-35.6,41.9-74.4,78.7-118.3,110.7c-30,21.6-58.9,46.3-85.8,72.1c-42,40.8-90.2,72.3-137.7,105.6
c-100.9,70.8-205.9,135.9-310.1,201.1c-108.7,68-193.4,139.2-303,238.9L-388.1,1703.1z"/>
<path class="st2" d="M1630,182.2c73.2-33.4,191.6-134.6,243.3-186.1l-20.6-307c-22.5,18.5-58.2,44-78.7,61.6
c-21.6,18.3-49.1,43.4-68.9,63.7c-81.1,83.3-106.1,123-181.6,211.8c-68.9,81-142.9,163.9-190.5,261.3
c-16.1,33.1-29.8,66.5-46,99.5c-43.4,88.9-93.1,175-141.7,260.8c-35.9,63.3-73.9,124.1-118.9,180.5
c-39.6,49.6-79.1,99.3-119.8,147.9c-27.4,32.8-54.9,65.2-84.8,95.3c-42.3,42.7-90.9,77-140.3,109.9
c-51.2,34.3-102.9,67.4-155.1,100c-63.4,39.6-117.1,92.7-170,145.9c-22.1,22.3-43.9,45.3-67.5,65.6
c-58.6,50.4-111.6,81.2-164,138.7c-4.8,5.2-16.7,17.6-19.2,20.3l253.1-17c10.3-7,26.7-27.9,34.7-37.6
c20.7-31.4,34.1-45.4,52.5-78.2c20.4-36.4,48-65.5,82.9-85.7c27.5-15.9,54-31.9,81.6-47.6c37.8-21.5,78-40.1,113.8-64.7
c72.6-49.9,144.1-102.2,214.3-155.6c65.8-50.2,129.3-103.5,193.7-155.6c22.8-18.4,42.2-38.7,57.3-65
c36.1-63,64.5-130.4,89.4-198.9c19.9-54.7,37.7-110.4,57-165.5c35.6-101.5,84.5-196.1,140-286.5
C1519.2,224.1,1556.9,215.6,1630,182.2z"/>
</g>
</g>
</g>
</g>
<g style="clip-path:url(#SVGID_00000004505243697409283410000015111137345945702290_);">
<rect x="0" class="st3" width="1417.3" height="1417.3"/>
</g>
<g style="clip-path:url(#SVGID_00000004505243697409283410000015111137345945702290_);">
<g>
<defs>
<rect id="SVGID_00000032616369356456210220000012159966553573026438_" width="1417.3" height="1417.3"/>
</defs>
<clipPath id="SVGID_00000108279254641195066740000005803902842077635263_">
<use xlink:href="#SVGID_00000032616369356456210220000012159966553573026438_" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#SVGID_00000108279254641195066740000005803902842077635263_);">
<path class="st5" d="M150.7,947.5c-53.3,22-112.8-13.5-121.1-72.3C24,835.2,46,795.7,82.4,780.7c53.3-22,112.8,13.5,121.1,72.3
C209,893,187,932.5,150.7,947.5z M89.2,697.3C-13.8,714-74.3,822.4-36.7,923c27.8,74.4,104.4,120.2,180.6,107.8
c103-16.6,163.5-125.1,125.9-225.7C242,730.7,165.4,685,89.2,697.3z"/>
<path class="st5" d="M319.4,638.7c-23.2,6.2-35.7,32.5-24.3,55.6c8.3,16.9,28.1,24.7,46.1,19.9l104.3-27.9l-104,260.9
c-3.4,8.6,4.3,17.5,13.2,15.1l254.5-68.2c18-4.8,31.2-21.5,29.9-40.3c-1.7-25.7-25.7-42.2-48.8-36l-127,34l103.9-260.7
c3.4-8.6-4.4-17.6-13.3-15.2L319.4,638.7z"/>
<path class="st5" d="M1335.8,364.8c-16.4,8.4-24,28-19.2,46l33.9,126.3l-247.1-108.4c-8.6-3.8-17.7,4.1-15.2,13.3l69.9,260.8
c4.8,18,21.2,31.2,39.6,30.2c25.7-1.4,42.2-25.7,35.8-49.3l-34.1-127.4l247.1,108.4c8.6,3.8,17.7-4.1,15.2-13.3l-70.1-261.8
C1385.2,365.9,1358.8,353.1,1335.8,364.8z"/>
<path class="st5" d="M805.3,500.1C681.5,533.2,600.8,633.2,625,723.4c24.2,90.2,144.1,136.4,267.8,103.2
c123.7-33.2,204.5-133.1,180.3-223.3C1048.9,513.1,929,466.9,805.3,500.1z M825.7,576.3c85.5-22.9,161.7,5.9,172.7,47
c11,41.1-40.5,104.2-126,127.1c-85.5,22.9-161.7-5.9-172.7-47C688.6,662.2,740.2,599.2,825.7,576.3z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

16
static/icons/wb.svg Normal file
View File

@ -0,0 +1,16 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 12C0 5.37258 5.37258 0 12 0H36C42.6274 0 48 5.37258 48 12V36C48 42.6274 42.6274 48 36 48H12C5.37258 48 0 42.6274 0 36V12Z" fill="url(#paint0_linear_11_61)"/>
<path d="M13.85 32.5H10.6958L6 16H8.86965L12.3559 28.8936L16.1268 16H18.6407L22.3878 28.8936L25.8741 16H28.7437L24.0479 32.5H20.8937L17.3837 20.455L13.85 32.5ZM39.6758 23.9436C41.1225 24.6979 42 26.065 42 27.7857C42 29.1293 41.5257 30.2607 40.5533 31.1564C39.581 32.0521 38.4189 32.5 37.0196 32.5H29.9048V16H36.4979C37.8497 16 39.0118 16.4479 39.9367 17.32C40.8853 18.1921 41.3597 19.2764 41.3597 20.5729C41.3597 22.0107 40.7905 23.1186 39.6758 23.9436ZM36.4979 18.5457H32.6321V22.8829H36.4979C37.7074 22.8829 38.6323 21.94 38.6323 20.7143C38.6323 19.4886 37.7074 18.5457 36.4979 18.5457ZM32.6321 29.9543H37.0196C38.2766 29.9543 39.2727 28.9407 39.2727 27.6443C39.2727 26.3479 38.2766 25.3343 37.0196 25.3343H32.6321V29.9543Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_11_61" x1="-0.101122" y1="2.88128" x2="52.4352" y2="9.57311" gradientUnits="userSpaceOnUse">
<stop stop-color="#ED3CCA"/>
<stop offset="0.145833" stop-color="#DF34D2"/>
<stop offset="0.291667" stop-color="#D02BD9"/>
<stop offset="0.432292" stop-color="#BF22E1"/>
<stop offset="0.572917" stop-color="#AE1AE8"/>
<stop offset="0.713542" stop-color="#9A10F0"/>
<stop offset="0.854167" stop-color="#8306F7"/>
<stop offset="1" stop-color="#7C1AF8"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
static/icons/ym.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

36
static/icons/ym.svg Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 30 29.9" style="enable-background:new 0 0 30 29.9;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{fill:#FED42B;}
.st2{display:none;fill:#FC3F1D;}
.st3{display:none;fill:#FFFFFF;}
.st4{clip-path:url(#SVGID_00000010272773654270891200000013716528645843490994_);}
</style>
<path class="st0" d="M46,26h3.3l4.6-17.1V26h3.7V3.4h-5.1L47.9,20L43.3,3.4h-5.2V26h3.2V8.9L46,26z M73.1,14.8c0-4-2-5.5-6.1-5.5
c-2.6,0-4.6,0.8-5.8,1.5V14c1-0.8,3.3-1.6,5.3-1.6c1.9,0,2.7,0.7,2.7,2.4v0.9h-0.6c-5.9,0-8.6,2-8.6,5.3s2,5.2,5,5.2
c2.3,0,3.3-0.7,4-1.5h0.2c0,0.4,0.2,1,0.3,1.3h3.8c-0.1-1.3-0.2-2.7-0.2-4C73.1,22,73.1,14.8,73.1,14.8z M69.2,22.1
c-0.5,0.7-1.4,1.3-2.8,1.3c-1.6,0-2.4-1-2.4-2.4c0-1.9,1.3-2.6,4.7-2.6h0.6L69.2,22.1L69.2,22.1z M79.8,9.6h-3.6v21.1h3.9v-6.6
c1,1.5,2.4,2.2,4.1,2.2c3.8,0,6.4-3,6.4-8.5s-2.5-8.5-6.2-8.5c-1.8,0-3.3,0.8-4.4,2.4C80,11.7,79.8,9.6,79.8,9.6z M83.1,23.3
c-2,0-3.1-1.7-3.1-5.4c0-3.8,1.1-5.5,3.3-5.5c2.1,0,3.2,1.7,3.2,5.4C86.5,21.6,85.4,23.3,83.1,23.3z M102.7,26h4.4l-6.2-8.8l5.5-7.6
h-3.9L97,17.2V9.6h-3.9V26H97v-8L102.7,26z M120.1,24.9v-3.2c-1.2,0.8-3.2,1.5-5.1,1.5c-2.8,0-3.9-1.3-4.1-4.1h9.3V17
c0-5.7-2.5-7.8-6.4-7.8c-4.7,0-7,3.6-7,8.6c0,5.7,2.8,8.5,7.7,8.5C117.2,26.3,119,25.7,120.1,24.9z M113.8,12.4
c1.9,0,2.5,1.6,2.5,3.6v0.3h-5.4C111,13.7,112,12.4,113.8,12.4z M134.1,12.7V9.6h-13v3.1h4.6V26h3.9V12.7H134.1z"/>
<path class="st1" d="M15,30c8.3,0,15-6.7,15-15S23.3,0,15,0S0,6.7,0,15C-0.1,23.3,6.7,30,15,30z"/>
<circle class="st2" cx="-17.1" cy="15" r="15"/>
<path class="st3" d="M-14.9,8.4h-1.5c-2.6,0-3.9,1.3-3.9,3.3c0,2.2,0.9,3.3,2.8,4.6l1.5,1.1l-4.3,6.7h-3.5l4.1-6.1
c-2.4-1.7-3.7-3.3-3.7-6.1c0-3.5,2.4-5.9,7-5.9h4.6v18h-3L-14.9,8.4L-14.9,8.4z"/>
<g>
<defs>
<path id="SVGID_1_" d="M15,30c8.3,0,15-6.7,15-15S23.3,0,15,0S0,6.7,0,15C-0.1,23.3,6.7,30,15,30z"/>
</defs>
<clipPath id="SVGID_00000002364318101313429230000004077879184956543148_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<path style="clip-path:url(#SVGID_00000002364318101313429230000004077879184956543148_);" d="M7.6,8.2L-5.6,25.5l3.5,4l9.8-13
l-1,7.1l5.5,1.9l6.7-10.7c-0.3,2-0.8,6.6,3.6,8c6.9,2.1,12.9-10.3,15.7-16.6l-4-2.1c-3.1,6.5-7.9,13.7-9.8,13.2
c-1.9-0.5-0.2-6.6,0.9-10.5V6.7l-6.1-2.1l-7.3,11.9l1-6.5L7.6,8.2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB