feat(pagadores): adicionar widget no dashboard e atualizar avatares
- Novo widget de pagadores no dashboard com resumo de transações - Substituir avatares SVG por PNG com melhor qualidade - Melhorar seção de pagador no diálogo de lançamentos - Adicionar ação para buscar pagadores por nome - Atualizar componentes de seleção (cartões, categorias, contas) - Melhorias no layout de ajustes e relatórios Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@@ -1,4 +1,4 @@
|
||||
import { RiSettingsLine } from "@remixicon/react";
|
||||
import { RiSettings2Line } from "@remixicon/react";
|
||||
import PageDescription from "@/components/page-description";
|
||||
|
||||
export const metadata = {
|
||||
@@ -13,7 +13,7 @@ export default function RootLayout({
|
||||
return (
|
||||
<section className="space-y-6 px-6">
|
||||
<PageDescription
|
||||
icon={<RiSettingsLine />}
|
||||
icon={<RiSettings2Line />}
|
||||
title="Ajustes"
|
||||
subtitle="Gerencie informações da conta, segurança e outras opções para otimizar sua experiência."
|
||||
/>
|
||||
|
||||
@@ -143,6 +143,8 @@ const baseFields = z.object({
|
||||
pagadorId: uuidSchema("Pagador").nullable().optional(),
|
||||
secondaryPagadorId: uuidSchema("Pagador secundário").optional(),
|
||||
isSplit: z.boolean().optional().default(false),
|
||||
primarySplitAmount: z.coerce.number().min(0).optional(),
|
||||
secondarySplitAmount: z.coerce.number().min(0).optional(),
|
||||
contaId: uuidSchema("Conta").nullable().optional(),
|
||||
cartaoId: uuidSchema("Cartão").nullable().optional(),
|
||||
categoriaId: uuidSchema("Categoria").nullable().optional(),
|
||||
@@ -234,6 +236,23 @@ const refineLancamento = (
|
||||
message: "Escolha um pagador diferente para dividir o lançamento.",
|
||||
});
|
||||
}
|
||||
|
||||
// Validate custom split amounts sum to total
|
||||
if (
|
||||
data.primarySplitAmount !== undefined &&
|
||||
data.secondarySplitAmount !== undefined
|
||||
) {
|
||||
const sum = data.primarySplitAmount + data.secondarySplitAmount;
|
||||
const total = Math.abs(data.amount);
|
||||
// Allow 1 cent tolerance for rounding differences
|
||||
if (Math.abs(sum - total) > 0.01) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["primarySplitAmount"],
|
||||
message: "A soma das divisões deve ser igual ao valor total.",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -354,17 +373,33 @@ const buildShares = ({
|
||||
pagadorId,
|
||||
isSplit,
|
||||
secondaryPagadorId,
|
||||
primarySplitAmountCents,
|
||||
secondarySplitAmountCents,
|
||||
}: {
|
||||
totalCents: number;
|
||||
pagadorId: string | null;
|
||||
isSplit: boolean;
|
||||
secondaryPagadorId?: string;
|
||||
primarySplitAmountCents?: number;
|
||||
secondarySplitAmountCents?: number;
|
||||
}): Share[] => {
|
||||
if (isSplit) {
|
||||
if (!pagadorId || !secondaryPagadorId) {
|
||||
throw new Error("Configuração de divisão inválida para o lançamento.");
|
||||
}
|
||||
|
||||
// Use custom split amounts if provided
|
||||
if (
|
||||
primarySplitAmountCents !== undefined &&
|
||||
secondarySplitAmountCents !== undefined
|
||||
) {
|
||||
return [
|
||||
{ pagadorId, amountCents: primarySplitAmountCents },
|
||||
{ pagadorId: secondaryPagadorId, amountCents: secondarySplitAmountCents },
|
||||
];
|
||||
}
|
||||
|
||||
// Fallback to equal split
|
||||
const [primaryAmount, secondaryAmount] = splitAmount(totalCents, 2);
|
||||
return [
|
||||
{ pagadorId, amountCents: primaryAmount },
|
||||
@@ -598,6 +633,12 @@ export async function createLancamentoAction(
|
||||
pagadorId: data.pagadorId ?? null,
|
||||
isSplit: data.isSplit ?? false,
|
||||
secondaryPagadorId: data.secondaryPagadorId,
|
||||
primarySplitAmountCents: data.primarySplitAmount
|
||||
? Math.round(data.primarySplitAmount * 100)
|
||||
: undefined,
|
||||
secondarySplitAmountCents: data.secondarySplitAmount
|
||||
? Math.round(data.secondarySplitAmount * 100)
|
||||
: undefined,
|
||||
});
|
||||
|
||||
const isSeriesLancamento =
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { readdir } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { PagadoresPage } from "@/components/pagadores/pagadores-page";
|
||||
import { user } from "@/db/schema";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { db } from "@/lib/db";
|
||||
import { fetchPagadoresWithAccess } from "@/lib/pagadores/access";
|
||||
import type { PagadorStatus } from "@/lib/pagadores/constants";
|
||||
import {
|
||||
@@ -44,11 +47,21 @@ const resolveStatus = (status: string | null): PagadorStatus => {
|
||||
export default async function Page() {
|
||||
const userId = await getUserId();
|
||||
|
||||
const [pagadorRows, avatarOptions] = await Promise.all([
|
||||
const [pagadorRows, localAvatarOptions, userData] = await Promise.all([
|
||||
fetchPagadoresWithAccess(userId),
|
||||
loadAvatarOptions(),
|
||||
db.query.user.findFirst({
|
||||
columns: { image: true },
|
||||
where: eq(user.id, userId),
|
||||
}),
|
||||
]);
|
||||
|
||||
// Incluir a imagem do Google nas opções se disponível
|
||||
const userImage = userData?.image;
|
||||
const avatarOptions = userImage
|
||||
? [userImage, ...localAvatarOptions]
|
||||
: localAvatarOptions;
|
||||
|
||||
const pagadoresData = pagadorRows
|
||||
.map((pagador) => ({
|
||||
id: pagador.id,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import {
|
||||
RiAndroidLine,
|
||||
RiDownload2Line,
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
RiQrCodeLine,
|
||||
RiShieldCheckLine,
|
||||
} from "@remixicon/react";
|
||||
import type { ReactNode } from "react";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { ApiTokensForm } from "./api-tokens-form";
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ export function StatusSelectContent({ label }: { label: string }) {
|
||||
return (
|
||||
<span className="flex items-center gap-2">
|
||||
<DotIcon
|
||||
bg_dot={
|
||||
color={
|
||||
isActive
|
||||
? "bg-emerald-600 dark:bg-emerald-300"
|
||||
: "bg-slate-400 dark:bg-slate-500"
|
||||
|
||||
@@ -2,9 +2,9 @@ import { RiArrowDownLine, RiArrowUpLine } from "@remixicon/react";
|
||||
import type { CategoryType } from "@/lib/categorias/constants";
|
||||
import { currencyFormatter } from "@/lib/lancamentos/formatting-helpers";
|
||||
import { cn } from "@/lib/utils/ui";
|
||||
import { CategoryIconBadge } from "./category-icon-badge";
|
||||
import { TypeBadge } from "../type-badge";
|
||||
import { Card } from "../ui/card";
|
||||
import { CategoryIconBadge } from "./category-icon-badge";
|
||||
|
||||
type CategorySummary = {
|
||||
id: string;
|
||||
|
||||
@@ -8,7 +8,7 @@ export function TypeSelectContent({ label }: { label: string }) {
|
||||
return (
|
||||
<span className="flex items-center gap-2">
|
||||
<DotIcon
|
||||
bg_dot={
|
||||
color={
|
||||
isReceita
|
||||
? "bg-emerald-600 dark:bg-emerald-300"
|
||||
: "bg-rose-600 dark:bg-rose-300"
|
||||
|
||||
@@ -8,7 +8,7 @@ export function StatusSelectContent({ label }: { label: string }) {
|
||||
return (
|
||||
<span className="flex items-center gap-2">
|
||||
<DotIcon
|
||||
bg_dot={
|
||||
color={
|
||||
isActive
|
||||
? "bg-emerald-600 dark:bg-emerald-300"
|
||||
: "bg-slate-400 dark:bg-slate-500"
|
||||
|
||||
@@ -115,13 +115,24 @@ export function DashboardGridEditable({
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleToggleWidget = useCallback((widgetId: string) => {
|
||||
setHiddenWidgets((prev) =>
|
||||
prev.includes(widgetId)
|
||||
? prev.filter((id) => id !== widgetId)
|
||||
: [...prev, widgetId],
|
||||
);
|
||||
}, []);
|
||||
const handleToggleWidget = useCallback(
|
||||
(widgetId: string) => {
|
||||
const newHidden = hiddenWidgets.includes(widgetId)
|
||||
? hiddenWidgets.filter((id) => id !== widgetId)
|
||||
: [...hiddenWidgets, widgetId];
|
||||
|
||||
setHiddenWidgets(newHidden);
|
||||
|
||||
// Salvar automaticamente ao toggle
|
||||
startTransition(async () => {
|
||||
await updateWidgetPreferences({
|
||||
order: widgetOrder,
|
||||
hidden: newHidden,
|
||||
});
|
||||
});
|
||||
},
|
||||
[hiddenWidgets, widgetOrder],
|
||||
);
|
||||
|
||||
const handleHideWidget = useCallback((widgetId: string) => {
|
||||
setHiddenWidgets((prev) => [...prev, widgetId]);
|
||||
|
||||
96
components/dashboard/pagadores-widget.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
RiExternalLinkLine,
|
||||
RiGroupLine,
|
||||
RiVerifiedBadgeFill,
|
||||
} from "@remixicon/react";
|
||||
import Link from "next/link";
|
||||
import MoneyValues from "@/components/money-values";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { CardContent } from "@/components/ui/card";
|
||||
import type { DashboardPagador } from "@/lib/dashboard/pagadores";
|
||||
import { getAvatarSrc } from "@/lib/pagadores/utils";
|
||||
import { WidgetEmptyState } from "../widget-empty-state";
|
||||
|
||||
type PagadoresWidgetProps = {
|
||||
pagadores: DashboardPagador[];
|
||||
};
|
||||
|
||||
const buildInitials = (value: string) => {
|
||||
const parts = value.trim().split(/\s+/).filter(Boolean);
|
||||
if (parts.length === 0) {
|
||||
return "??";
|
||||
}
|
||||
if (parts.length === 1) {
|
||||
const firstPart = parts[0];
|
||||
return firstPart ? firstPart.slice(0, 2).toUpperCase() : "??";
|
||||
}
|
||||
const firstChar = parts[0]?.[0] ?? "";
|
||||
const secondChar = parts[1]?.[0] ?? "";
|
||||
return `${firstChar}${secondChar}`.toUpperCase() || "??";
|
||||
};
|
||||
|
||||
export function PagadoresWidget({ pagadores }: PagadoresWidgetProps) {
|
||||
return (
|
||||
<CardContent className="flex flex-col gap-4 px-0">
|
||||
{pagadores.length === 0 ? (
|
||||
<WidgetEmptyState
|
||||
icon={<RiGroupLine className="size-6 text-muted-foreground" />}
|
||||
title="Nenhum pagador para o período"
|
||||
description="Quando houver despesas associadas a pagadores, eles aparecerão aqui."
|
||||
/>
|
||||
) : (
|
||||
<ul className="flex flex-col">
|
||||
{pagadores.map((pagador) => {
|
||||
const initials = buildInitials(pagador.name);
|
||||
|
||||
return (
|
||||
<li
|
||||
key={pagador.id}
|
||||
className="flex items-center justify-between border-b border-dashed last:border-b-0 last:pb-0"
|
||||
>
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2 py-2">
|
||||
<Avatar className="size-10 shrink-0">
|
||||
<AvatarImage
|
||||
src={getAvatarSrc(pagador.avatarUrl)}
|
||||
alt={`Avatar de ${pagador.name}`}
|
||||
/>
|
||||
<AvatarFallback>{initials}</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
<div className="min-w-0">
|
||||
<Link
|
||||
prefetch
|
||||
href={`/pagadores/${pagador.id}`}
|
||||
className="inline-flex max-w-full items-center gap-1 text-sm text-foreground underline-offset-2 hover:text-primary hover:underline"
|
||||
>
|
||||
<span className="truncate">{pagador.name}</span>
|
||||
{pagador.isAdmin && (
|
||||
<RiVerifiedBadgeFill
|
||||
className="size-4 shrink-0 text-blue-500"
|
||||
aria-hidden
|
||||
/>
|
||||
)}
|
||||
<RiExternalLinkLine
|
||||
className="size-3 shrink-0 text-muted-foreground"
|
||||
aria-hidden
|
||||
/>
|
||||
</Link>
|
||||
<p className="truncate text-xs text-muted-foreground">
|
||||
{pagador.email ?? "Sem email cadastrado"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex shrink-0 flex-col items-end">
|
||||
<MoneyValues amount={pagador.totalExpenses} />
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
</CardContent>
|
||||
);
|
||||
}
|
||||
@@ -73,6 +73,7 @@ export interface SplitAndSettlementSectionProps extends BaseFieldSectionProps {
|
||||
export interface PagadorSectionProps extends BaseFieldSectionProps {
|
||||
pagadorOptions: SelectOption[];
|
||||
secondaryPagadorOptions: SelectOption[];
|
||||
totalAmount: number;
|
||||
}
|
||||
|
||||
export interface PaymentMethodSectionProps extends BaseFieldSectionProps {
|
||||
|
||||
@@ -141,6 +141,11 @@ export function LancamentoDialog({
|
||||
return groupAndSortCategorias(filtered);
|
||||
}, [categoriaOptions, formState.transactionType]);
|
||||
|
||||
const totalAmount = useMemo(() => {
|
||||
const parsed = Number.parseFloat(formState.amount);
|
||||
return Number.isNaN(parsed) ? 0 : Math.abs(parsed);
|
||||
}, [formState.amount]);
|
||||
|
||||
const handleFieldChange = useCallback(
|
||||
<Key extends keyof FormState>(key: Key, value: FormState[Key]) => {
|
||||
if (key === "period") {
|
||||
@@ -223,6 +228,12 @@ export function LancamentoDialog({
|
||||
? formState.secondaryPagadorId
|
||||
: undefined,
|
||||
isSplit: formState.isSplit,
|
||||
primarySplitAmount: formState.isSplit
|
||||
? Number.parseFloat(formState.primarySplitAmount) || undefined
|
||||
: undefined,
|
||||
secondarySplitAmount: formState.isSplit
|
||||
? Number.parseFloat(formState.secondarySplitAmount) || undefined
|
||||
: undefined,
|
||||
contaId: formState.contaId,
|
||||
cartaoId: formState.cartaoId,
|
||||
categoriaId: formState.categoriaId,
|
||||
@@ -402,6 +413,7 @@ export function LancamentoDialog({
|
||||
onFieldChange={handleFieldChange}
|
||||
pagadorOptions={pagadorOptions}
|
||||
secondaryPagadorOptions={secondaryPagadorOptions}
|
||||
totalAmount={totalAmount}
|
||||
/>
|
||||
|
||||
<PaymentMethodSection
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback } from "react";
|
||||
import { CurrencyInput } from "@/components/ui/currency-input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
@@ -16,63 +18,46 @@ export function PagadorSection({
|
||||
onFieldChange,
|
||||
pagadorOptions,
|
||||
secondaryPagadorOptions,
|
||||
totalAmount,
|
||||
}: PagadorSectionProps) {
|
||||
const handlePrimaryAmountChange = useCallback(
|
||||
(value: string) => {
|
||||
onFieldChange("primarySplitAmount", value);
|
||||
const numericValue = Number.parseFloat(value) || 0;
|
||||
const remaining = Math.max(0, totalAmount - numericValue);
|
||||
onFieldChange("secondarySplitAmount", remaining.toFixed(2));
|
||||
},
|
||||
[totalAmount, onFieldChange],
|
||||
);
|
||||
|
||||
const handleSecondaryAmountChange = useCallback(
|
||||
(value: string) => {
|
||||
onFieldChange("secondarySplitAmount", value);
|
||||
const numericValue = Number.parseFloat(value) || 0;
|
||||
const remaining = Math.max(0, totalAmount - numericValue);
|
||||
onFieldChange("primarySplitAmount", remaining.toFixed(2));
|
||||
},
|
||||
[totalAmount, onFieldChange],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-col gap-2 md:flex-row">
|
||||
<div className="w-full space-y-1">
|
||||
<Label htmlFor="pagador">Pagador</Label>
|
||||
<Select
|
||||
value={formState.pagadorId}
|
||||
onValueChange={(value) => onFieldChange("pagadorId", value)}
|
||||
>
|
||||
<SelectTrigger id="pagador" className="w-full">
|
||||
<SelectValue placeholder="Selecione">
|
||||
{formState.pagadorId &&
|
||||
(() => {
|
||||
const selectedOption = pagadorOptions.find(
|
||||
(opt) => opt.value === formState.pagadorId,
|
||||
);
|
||||
return selectedOption ? (
|
||||
<PagadorSelectContent
|
||||
label={selectedOption.label}
|
||||
avatarUrl={selectedOption.avatarUrl}
|
||||
/>
|
||||
) : null;
|
||||
})()}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{pagadorOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<PagadorSelectContent
|
||||
label={option.label}
|
||||
avatarUrl={option.avatarUrl}
|
||||
/>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{formState.isSplit ? (
|
||||
<div className="w-full space-y-1">
|
||||
<Label htmlFor="secondaryPagador">Dividir com</Label>
|
||||
<div className="flex gap-2">
|
||||
<Select
|
||||
value={formState.secondaryPagadorId}
|
||||
onValueChange={(value) =>
|
||||
onFieldChange("secondaryPagadorId", value)
|
||||
}
|
||||
value={formState.pagadorId}
|
||||
onValueChange={(value) => onFieldChange("pagadorId", value)}
|
||||
>
|
||||
<SelectTrigger
|
||||
id="secondaryPagador"
|
||||
disabled={secondaryPagadorOptions.length === 0}
|
||||
className={"w-full"}
|
||||
id="pagador"
|
||||
className={formState.isSplit ? "w-[55%]" : "w-full"}
|
||||
>
|
||||
<SelectValue placeholder="Selecione">
|
||||
{formState.secondaryPagadorId &&
|
||||
{formState.pagadorId &&
|
||||
(() => {
|
||||
const selectedOption = secondaryPagadorOptions.find(
|
||||
(opt) => opt.value === formState.secondaryPagadorId,
|
||||
const selectedOption = pagadorOptions.find(
|
||||
(opt) => opt.value === formState.pagadorId,
|
||||
);
|
||||
return selectedOption ? (
|
||||
<PagadorSelectContent
|
||||
@@ -84,7 +69,7 @@ export function PagadorSection({
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{secondaryPagadorOptions.map((option) => (
|
||||
{pagadorOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<PagadorSelectContent
|
||||
label={option.label}
|
||||
@@ -94,6 +79,65 @@ export function PagadorSection({
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{formState.isSplit && (
|
||||
<CurrencyInput
|
||||
value={formState.primarySplitAmount}
|
||||
onValueChange={handlePrimaryAmountChange}
|
||||
placeholder="R$ 0,00"
|
||||
className="h-9 w-[45%] text-sm"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{formState.isSplit ? (
|
||||
<div className="w-full space-y-1 mb-1">
|
||||
<Label htmlFor="secondaryPagador">Dividir com</Label>
|
||||
<div className="flex gap-2">
|
||||
<Select
|
||||
value={formState.secondaryPagadorId}
|
||||
onValueChange={(value) =>
|
||||
onFieldChange("secondaryPagadorId", value)
|
||||
}
|
||||
>
|
||||
<SelectTrigger
|
||||
id="secondaryPagador"
|
||||
disabled={secondaryPagadorOptions.length === 0}
|
||||
className="w-[55%]"
|
||||
>
|
||||
<SelectValue placeholder="Selecione">
|
||||
{formState.secondaryPagadorId &&
|
||||
(() => {
|
||||
const selectedOption = secondaryPagadorOptions.find(
|
||||
(opt) => opt.value === formState.secondaryPagadorId,
|
||||
);
|
||||
return selectedOption ? (
|
||||
<PagadorSelectContent
|
||||
label={selectedOption.label}
|
||||
avatarUrl={selectedOption.avatarUrl}
|
||||
/>
|
||||
) : null;
|
||||
})()}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{secondaryPagadorOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
<PagadorSelectContent
|
||||
label={option.label}
|
||||
avatarUrl={option.avatarUrl}
|
||||
/>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<CurrencyInput
|
||||
value={formState.secondarySplitAmount}
|
||||
onValueChange={handleSecondaryAmountChange}
|
||||
placeholder="R$ 0,00"
|
||||
className="h-9 w-[45%] text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -148,7 +148,7 @@ export function PagadorInfoCard({
|
||||
alt={`Avatar de ${pagador.name}`}
|
||||
width={64}
|
||||
height={64}
|
||||
className="h-full w-full object-cover"
|
||||
className="h-full w-full object-cover rounded-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -214,7 +214,7 @@ export function PagadorInfoCard({
|
||||
{pagador.email}
|
||||
</Link>
|
||||
) : (
|
||||
"—"
|
||||
"Sem e-mail cadastrado"
|
||||
)
|
||||
}
|
||||
/>
|
||||
@@ -260,7 +260,7 @@ export function PagadorInfoCard({
|
||||
pagador.note ? (
|
||||
<span className="text-muted-foreground">{pagador.note}</span>
|
||||
) : (
|
||||
"—"
|
||||
"Sem observações"
|
||||
)
|
||||
}
|
||||
className="sm:col-span-2"
|
||||
|
||||
@@ -63,7 +63,7 @@ export function PagadorCard({ pagador, onEdit, onRemove }: PagadorCardProps) {
|
||||
<p className="mt-1 text-xs text-muted-foreground">{pagador.email}</p>
|
||||
) : (
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
Sem Email cadastrado
|
||||
Sem email cadastrado
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
"use client";
|
||||
import { RiCheckLine, RiCloseCircleLine } from "@remixicon/react";
|
||||
import Image from "next/image";
|
||||
import {
|
||||
useCallback,
|
||||
@@ -33,7 +32,6 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useControlledState } from "@/hooks/use-controlled-state";
|
||||
import { useFormState } from "@/hooks/use-form-state";
|
||||
import {
|
||||
@@ -270,16 +268,9 @@ export function PagadorDialog({
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset className="flex flex-col gap-3">
|
||||
<div className="grid grid-cols-4 gap-3 sm:grid-cols-5">
|
||||
{availableAvatars.length === 0 ? (
|
||||
<div className="col-span-5 flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed border-border/60 bg-muted/10 p-6 text-center text-sm text-muted-foreground">
|
||||
<RiCloseCircleLine className="size-6" />
|
||||
Nenhum avatar disponível. Adicione imagens em
|
||||
<span className="font-mono text-xs">public/avatares</span>
|
||||
.
|
||||
</div>
|
||||
) : null}
|
||||
<fieldset className="flex flex-col gap-2">
|
||||
<Label>Avatar</Label>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{availableAvatars.map((avatar) => {
|
||||
const isSelected = avatar === formState.avatarUrl;
|
||||
return (
|
||||
@@ -287,22 +278,16 @@ export function PagadorDialog({
|
||||
type="button"
|
||||
key={avatar}
|
||||
onClick={() => updateField("avatarUrl", avatar)}
|
||||
className="group relative flex items-center justify-center overflow-hidden rounded-xl border border-border/70 p-2 transition-all hover:border-primary/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 data-[selected=true]:border-primary data-[selected=true]:bg-primary/10"
|
||||
className="group relative flex items-center justify-center rounded-full p-0.5 transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 data-[selected=true]:ring-2 data-[selected=true]:ring-primary"
|
||||
data-selected={isSelected}
|
||||
aria-pressed={isSelected}
|
||||
>
|
||||
<span className="absolute inset-0 rounded-xl border-2 border-primary/80 opacity-0 transition-opacity group-data-[selected=true]:opacity-100" />
|
||||
{isSelected ? (
|
||||
<span className="absolute right-1 top-1 flex size-4 items-center justify-center rounded-full bg-sidebar-foreground text-primary-foreground shadow-sm">
|
||||
<RiCheckLine className="size-3.5" />
|
||||
</span>
|
||||
) : null}
|
||||
<Image
|
||||
src={getAvatarSrc(avatar)}
|
||||
alt={`Avatar ${avatar}`}
|
||||
width={72}
|
||||
height={72}
|
||||
className="size-12 rounded-lg object-cover"
|
||||
width={40}
|
||||
height={40}
|
||||
className="size-12 rounded-full object-cove hover:scale-110 transition-transform duration-200"
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
@@ -312,12 +297,11 @@ export function PagadorDialog({
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="pagador-note">Anotações</Label>
|
||||
<Textarea
|
||||
<Input
|
||||
id="pagador-note"
|
||||
rows={2}
|
||||
value={formState.note}
|
||||
onChange={(event) => updateField("note", event.target.value)}
|
||||
placeholder="Observações, preferências ou detalhes relevantes sobre este pagador"
|
||||
placeholder="Observações sobre este pagador"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ export function StatusSelectContent({ label }: { label: string }) {
|
||||
return (
|
||||
<span className="flex items-center gap-2">
|
||||
<DotIcon
|
||||
bg_dot={
|
||||
color={
|
||||
isActive
|
||||
? "bg-emerald-600 dark:bg-emerald-300"
|
||||
: "bg-slate-400 dark:bg-slate-500"
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useCallback, useMemo, useState, useTransition } from "react";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
import { CategoryReportSkeleton } from "@/components/skeletons/category-report-skeleton";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import type { CategoryChartData } from "@/lib/relatorios/fetch-category-chart-data";
|
||||
import type { CategoryReportData } from "@/lib/relatorios/types";
|
||||
@@ -123,36 +124,39 @@ export function CategoryReportPage({
|
||||
|
||||
{/* Empty States */}
|
||||
{!isPending && hasNoCategories && (
|
||||
<EmptyState
|
||||
title="Nenhuma categoria cadastrada"
|
||||
description="Você precisa cadastrar categorias antes de visualizar o relatório."
|
||||
media={<RiPieChartLine className="h-12 w-12" />}
|
||||
mediaVariant="icon"
|
||||
/>
|
||||
<Card className="flex w-full items-center justify-center py-12">
|
||||
<EmptyState
|
||||
title="Nenhuma categoria cadastrada"
|
||||
description="Você precisa cadastrar categorias antes de visualizar o relatório."
|
||||
media={<RiPieChartLine className="size-6 text-primary" />}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{!isPending &&
|
||||
!hasNoCategories &&
|
||||
hasNoData &&
|
||||
filters.selectedCategories.length === 0 && (
|
||||
<EmptyState
|
||||
title="Selecione pelo menos uma categoria"
|
||||
description="Use o filtro acima para selecionar as categorias que deseja visualizar no relatório."
|
||||
media={<RiFilter3Line className="h-12 w-12" />}
|
||||
mediaVariant="icon"
|
||||
/>
|
||||
<Card className="flex w-full items-center justify-center py-12">
|
||||
<EmptyState
|
||||
title="Selecione pelo menos uma categoria"
|
||||
description="Use o filtro acima para selecionar as categorias que deseja visualizar no relatório."
|
||||
media={<RiFilter3Line className="size-6 text-primary" />}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{!isPending &&
|
||||
!hasNoCategories &&
|
||||
hasNoData &&
|
||||
filters.selectedCategories.length > 0 && (
|
||||
<EmptyState
|
||||
title="Nenhum lançamento encontrado"
|
||||
description="Não há transações no período selecionado para as categorias filtradas."
|
||||
media={<RiPieChartLine className="h-12 w-12" />}
|
||||
mediaVariant="icon"
|
||||
/>
|
||||
<Card className="flex w-full items-center justify-center py-12">
|
||||
<EmptyState
|
||||
title="Nenhum lançamento encontrado"
|
||||
description="Não há transações no período selecionado para as categorias filtradas."
|
||||
media={<RiPieChartLine className="size-6 text-primary" />}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Tabs: Table and Chart */}
|
||||
|
||||
@@ -24,10 +24,15 @@ export function NavUser({ user, pagadorAvatarUrl }: NavUserProps) {
|
||||
useSidebar();
|
||||
|
||||
const avatarSrc = useMemo(() => {
|
||||
// Priorizar o avatar do pagador admin quando disponível
|
||||
if (pagadorAvatarUrl) {
|
||||
return getAvatarSrc(pagadorAvatarUrl);
|
||||
}
|
||||
// Fallback para a imagem do usuário (Google, etc)
|
||||
if (user.image) {
|
||||
return user.image;
|
||||
}
|
||||
return getAvatarSrc(pagadorAvatarUrl);
|
||||
return getAvatarSrc(null);
|
||||
}, [user.image, pagadorAvatarUrl]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,6 +9,7 @@ import { fetchIncomeExpenseBalance } from "./income-expense-balance";
|
||||
import { fetchDashboardInvoices } from "./invoices";
|
||||
import { fetchDashboardCardMetrics } from "./metrics";
|
||||
import { fetchDashboardNotifications } from "./notifications";
|
||||
import { fetchDashboardPagadores } from "./pagadores";
|
||||
import { fetchPaymentConditions } from "./payments/payment-conditions";
|
||||
import { fetchPaymentMethods } from "./payments/payment-methods";
|
||||
import { fetchPaymentStatus } from "./payments/payment-status";
|
||||
@@ -25,6 +26,7 @@ export async function fetchDashboardData(userId: string, period: string) {
|
||||
notificationsSnapshot,
|
||||
paymentStatusData,
|
||||
incomeExpenseBalanceData,
|
||||
pagadoresSnapshot,
|
||||
recentTransactionsData,
|
||||
paymentConditionsData,
|
||||
paymentMethodsData,
|
||||
@@ -44,6 +46,7 @@ export async function fetchDashboardData(userId: string, period: string) {
|
||||
fetchDashboardNotifications(userId, period),
|
||||
fetchPaymentStatus(userId, period),
|
||||
fetchIncomeExpenseBalance(userId, period),
|
||||
fetchDashboardPagadores(userId, period),
|
||||
fetchRecentTransactions(userId, period),
|
||||
fetchPaymentConditions(userId, period),
|
||||
fetchPaymentMethods(userId, period),
|
||||
@@ -65,6 +68,7 @@ export async function fetchDashboardData(userId: string, period: string) {
|
||||
notificationsSnapshot,
|
||||
paymentStatusData,
|
||||
incomeExpenseBalanceData,
|
||||
pagadoresSnapshot,
|
||||
recentTransactionsData,
|
||||
paymentConditionsData,
|
||||
paymentMethodsData,
|
||||
|
||||
77
lib/dashboard/pagadores.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { and, desc, eq, isNull, or, sql } from "drizzle-orm";
|
||||
import { lancamentos, pagadores } from "@/db/schema";
|
||||
import { ACCOUNT_AUTO_INVOICE_NOTE_PREFIX } from "@/lib/accounts/constants";
|
||||
import { toNumber } from "@/lib/dashboard/common";
|
||||
import { db } from "@/lib/db";
|
||||
import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants";
|
||||
|
||||
export type DashboardPagador = {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string | null;
|
||||
avatarUrl: string | null;
|
||||
totalExpenses: number;
|
||||
isAdmin: boolean;
|
||||
};
|
||||
|
||||
export type DashboardPagadoresSnapshot = {
|
||||
pagadores: DashboardPagador[];
|
||||
totalExpenses: number;
|
||||
};
|
||||
|
||||
export async function fetchDashboardPagadores(
|
||||
userId: string,
|
||||
period: string,
|
||||
): Promise<DashboardPagadoresSnapshot> {
|
||||
const rows = await db
|
||||
.select({
|
||||
id: pagadores.id,
|
||||
name: pagadores.name,
|
||||
email: pagadores.email,
|
||||
avatarUrl: pagadores.avatarUrl,
|
||||
role: pagadores.role,
|
||||
totalExpenses: sql<number>`COALESCE(SUM(ABS(${lancamentos.amount})), 0)`,
|
||||
})
|
||||
.from(lancamentos)
|
||||
.innerJoin(pagadores, eq(lancamentos.pagadorId, pagadores.id))
|
||||
.where(
|
||||
and(
|
||||
eq(lancamentos.userId, userId),
|
||||
eq(lancamentos.period, period),
|
||||
eq(lancamentos.transactionType, "Despesa"),
|
||||
or(
|
||||
isNull(lancamentos.note),
|
||||
sql`${lancamentos.note} NOT LIKE ${`${ACCOUNT_AUTO_INVOICE_NOTE_PREFIX}%`}`,
|
||||
),
|
||||
),
|
||||
)
|
||||
.groupBy(
|
||||
pagadores.id,
|
||||
pagadores.name,
|
||||
pagadores.email,
|
||||
pagadores.avatarUrl,
|
||||
pagadores.role,
|
||||
)
|
||||
.orderBy(desc(sql`SUM(ABS(${lancamentos.amount}))`));
|
||||
|
||||
const pagadoresList = rows
|
||||
.map((row) => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
email: row.email,
|
||||
avatarUrl: row.avatarUrl,
|
||||
totalExpenses: toNumber(row.totalExpenses),
|
||||
isAdmin: row.role === PAGADOR_ROLE_ADMIN,
|
||||
}))
|
||||
.filter((p) => p.totalExpenses > 0);
|
||||
|
||||
const totalExpenses = pagadoresList.reduce(
|
||||
(sum, p) => sum + p.totalExpenses,
|
||||
0,
|
||||
);
|
||||
|
||||
return {
|
||||
pagadores: pagadoresList,
|
||||
totalExpenses,
|
||||
};
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
RiBarcodeLine,
|
||||
RiBillLine,
|
||||
RiExchangeLine,
|
||||
RiGroupLine,
|
||||
RiLineChartLine,
|
||||
RiMoneyDollarCircleLine,
|
||||
RiNumbersLine,
|
||||
@@ -24,6 +25,7 @@ import { IncomeExpenseBalanceWidget } from "@/components/dashboard/income-expens
|
||||
import { InstallmentExpensesWidget } from "@/components/dashboard/installment-expenses-widget";
|
||||
import { InvoicesWidget } from "@/components/dashboard/invoices-widget";
|
||||
import { MyAccountsWidget } from "@/components/dashboard/my-accounts-widget";
|
||||
import { PagadoresWidget } from "@/components/dashboard/pagadores-widget";
|
||||
import { PaymentConditionsWidget } from "@/components/dashboard/payment-conditions-widget";
|
||||
import { PaymentMethodsWidget } from "@/components/dashboard/payment-methods-widget";
|
||||
import { PaymentStatusWidget } from "@/components/dashboard/payment-status-widget";
|
||||
@@ -93,6 +95,24 @@ export const widgetsConfig: WidgetConfig[] = [
|
||||
<IncomeExpenseBalanceWidget data={data.incomeExpenseBalanceData} />
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "pagadores",
|
||||
title: "Pagadores",
|
||||
subtitle: "Despesas por pagador no período",
|
||||
icon: <RiGroupLine className="size-4" />,
|
||||
component: ({ data }) => (
|
||||
<PagadoresWidget pagadores={data.pagadoresSnapshot.pagadores} />
|
||||
),
|
||||
action: (
|
||||
<Link
|
||||
href="/pagadores"
|
||||
className="text-sm font-medium text-muted-foreground hover:text-primary transition-colors inline-flex items-center gap-1"
|
||||
>
|
||||
Ver todos
|
||||
<RiArrowRightLine className="size-4" />
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "recent-transactions",
|
||||
title: "Lançamentos Recentes",
|
||||
|
||||
@@ -7,6 +7,11 @@ import {
|
||||
LANCAMENTO_TRANSACTION_TYPES,
|
||||
} from "./constants";
|
||||
|
||||
/**
|
||||
* Split type for dividing transactions between payers
|
||||
*/
|
||||
export type SplitType = "equal" | "60-40" | "70-30" | "80-20" | "custom";
|
||||
|
||||
/**
|
||||
* Form state type for lancamento dialog
|
||||
*/
|
||||
@@ -21,6 +26,9 @@ export type LancamentoFormState = {
|
||||
pagadorId: string | undefined;
|
||||
secondaryPagadorId: string | undefined;
|
||||
isSplit: boolean;
|
||||
splitType: SplitType;
|
||||
primarySplitAmount: string;
|
||||
secondarySplitAmount: string;
|
||||
contaId: string | undefined;
|
||||
cartaoId: string | undefined;
|
||||
categoriaId: string | undefined;
|
||||
@@ -115,6 +123,9 @@ export function buildLancamentoInitialState(
|
||||
pagadorId: fallbackPagadorId ?? undefined,
|
||||
secondaryPagadorId: undefined,
|
||||
isSplit: false,
|
||||
splitType: "equal",
|
||||
primarySplitAmount: "",
|
||||
secondarySplitAmount: "",
|
||||
contaId:
|
||||
paymentMethod === "Cartão de crédito"
|
||||
? undefined
|
||||
@@ -146,6 +157,39 @@ export function buildLancamentoInitialState(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Split presets with their percentages
|
||||
*/
|
||||
const SPLIT_PRESETS: Record<SplitType, { primary: number; secondary: number }> =
|
||||
{
|
||||
equal: { primary: 50, secondary: 50 },
|
||||
"60-40": { primary: 60, secondary: 40 },
|
||||
"70-30": { primary: 70, secondary: 30 },
|
||||
"80-20": { primary: 80, secondary: 20 },
|
||||
custom: { primary: 50, secondary: 50 },
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates split amounts based on total and split type
|
||||
*/
|
||||
export function calculateSplitAmounts(
|
||||
totalAmount: number,
|
||||
splitType: SplitType,
|
||||
): { primary: string; secondary: string } {
|
||||
if (totalAmount <= 0) {
|
||||
return { primary: "", secondary: "" };
|
||||
}
|
||||
|
||||
const preset = SPLIT_PRESETS[splitType];
|
||||
const primaryAmount = (totalAmount * preset.primary) / 100;
|
||||
const secondaryAmount = totalAmount - primaryAmount;
|
||||
|
||||
return {
|
||||
primary: primaryAmount.toFixed(2),
|
||||
secondary: secondaryAmount.toFixed(2),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies field dependencies when form state changes
|
||||
* This function encapsulates the business logic for field interdependencies
|
||||
@@ -202,9 +246,38 @@ export function applyFieldDependencies(
|
||||
}
|
||||
}
|
||||
|
||||
// When split is disabled, clear secondary pagador
|
||||
// When split is disabled, clear secondary pagador and split fields
|
||||
if (key === "isSplit" && value === false) {
|
||||
updates.secondaryPagadorId = undefined;
|
||||
updates.splitType = "equal";
|
||||
updates.primarySplitAmount = "";
|
||||
updates.secondarySplitAmount = "";
|
||||
}
|
||||
|
||||
// When split is enabled and amount exists, calculate initial split amounts
|
||||
if (key === "isSplit" && value === true) {
|
||||
const totalAmount = Number.parseFloat(currentState.amount) || 0;
|
||||
if (totalAmount > 0) {
|
||||
const half = (totalAmount / 2).toFixed(2);
|
||||
updates.primarySplitAmount = half;
|
||||
updates.secondarySplitAmount = half;
|
||||
}
|
||||
}
|
||||
|
||||
// When amount changes and split is enabled, recalculate split amounts
|
||||
if (key === "amount" && typeof value === "string" && currentState.isSplit) {
|
||||
const totalAmount = Number.parseFloat(value) || 0;
|
||||
if (totalAmount > 0) {
|
||||
const splitAmounts = calculateSplitAmounts(
|
||||
totalAmount,
|
||||
currentState.splitType,
|
||||
);
|
||||
updates.primarySplitAmount = splitAmounts.primary;
|
||||
updates.secondarySplitAmount = splitAmounts.secondary;
|
||||
} else {
|
||||
updates.primarySplitAmount = "";
|
||||
updates.secondarySplitAmount = "";
|
||||
}
|
||||
}
|
||||
|
||||
// When primary pagador changes, clear secondary if it matches
|
||||
|
||||
@@ -4,4 +4,4 @@ export type PagadorStatus = (typeof PAGADOR_STATUS_OPTIONS)[number];
|
||||
|
||||
export const PAGADOR_ROLE_ADMIN = "admin";
|
||||
export const PAGADOR_ROLE_TERCEIRO = "terceiro";
|
||||
export const DEFAULT_PAGADOR_AVATAR = "avatar_010.svg";
|
||||
export const DEFAULT_PAGADOR_AVATAR = "default_icon.png";
|
||||
|
||||
@@ -3,11 +3,22 @@ import { DEFAULT_PAGADOR_AVATAR } from "./constants";
|
||||
/**
|
||||
* Normaliza o caminho do avatar extraindo apenas o nome do arquivo.
|
||||
* Remove qualquer caminho anterior e retorna null se não houver avatar.
|
||||
* Preserva URLs completas (http/https/data).
|
||||
*/
|
||||
export const normalizeAvatarPath = (
|
||||
avatar: string | null | undefined,
|
||||
): string | null => {
|
||||
if (!avatar) return null;
|
||||
|
||||
// Preservar URLs completas (Google, etc)
|
||||
if (
|
||||
avatar.startsWith("http://") ||
|
||||
avatar.startsWith("https://") ||
|
||||
avatar.startsWith("data:")
|
||||
) {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
const file = avatar.split("/").filter(Boolean).pop();
|
||||
return file ?? avatar;
|
||||
};
|
||||
|
||||
BIN
public/avatares/4825015.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/avatares/4825021.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/avatares/4825027.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/avatares/4825031.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/avatares/4825035.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/avatares/4825038.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/avatares/4825044.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/avatares/4825047.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/avatares/4825051.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/avatares/4825057.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/avatares/4825062.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/avatares/4825066.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/avatares/4825072.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/avatares/4825076.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/avatares/4825082.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/avatares/4825087.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/avatares/4825096.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/avatares/4825108.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/avatares/4825112.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/avatares/4825123.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-74"><circle cx="320" cy="320" r="320" transform="translate(501 195)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-21484 -20497)"><circle cx="320" cy="320" r="320" transform="translate(21484 20497)" fill="#f2f2f2"/><g transform="translate(20983 20302)" clip-path="url(#a-74)"><g transform="translate(426.41 -258.111)"><path d="M395,524.524a6.435,6.435,0,0,1-4.076-1.454,6.665,6.665,0,0,1-2.442-4.747,207.7,207.7,0,0,1,16.5-95.076c8.734-20.222,18.782-33.252,31.621-41.007,17.128-10.345,40.629-11.171,64.478-2.267,13.629,5.089,23.459,11.74,30.05,20.333,8.794,11.466,11.553,26.177,13.223,40.365a361.8,361.8,0,0,1,1.769,64.689,6.3,6.3,0,0,1-3.5,5.306,6.9,6.9,0,0,1-6.85-.451,14.172,14.172,0,0,0-1.25-.732,15.2,15.2,0,0,0-13.967.177,31.236,31.236,0,0,0-4.448,3.193l-8.574,6.941a6.62,6.62,0,0,1-7.543.478,46.521,46.521,0,0,0-20.309-6,129.64,129.64,0,0,0-28.3,2.054l-55.42,8.124A6.7,6.7,0,0,1,395,524.524Z" transform="translate(-62.412 244.496)" fill="#2f2e41"/><path d="M.022,18.3,19.69,93.288,94.679,78.538S42.356,24.584,49.721,0L0,18.3H.022Z" transform="translate(374.009 727.802) rotate(11)" fill="#ed9da0"/><path d="M507.867,693H421.459V439.014h86.408a62.423,62.423,0,0,1,62.353,62.353V630.643A62.423,62.423,0,0,1,507.867,693Z" transform="translate(-5.075 356.432)" fill="#2f2e41"/><path d="M455.71,548.908a10.9,10.9,0,0,1-10.885-10.885V443.688h21.77v94.336a10.9,10.9,0,0,1-10.885,10.885Z" transform="translate(35.055 364.458)" fill="#3f3d56"/><path d="M507.1,566.409H443.88a13.758,13.758,0,0,1-13.742-13.743V514.842A13.758,13.758,0,0,1,443.88,501.1H507.1a13.758,13.758,0,0,1,13.742,13.743v37.824A13.758,13.758,0,0,1,507.1,566.409Z" transform="translate(9.83 463.063)" fill="#3f3d56"/><path d="M254.356,376.062l-8.481,113.624L189.626,659.372l-22.591-13.131,30.648-172.572,10.408-99.555Z" transform="translate(57 539.824)" fill="#ed9da0"/><path d="M595.814,489.3,534.3,460.5,516.545,429.56l-59.706,3.385-18.067,29.492L385.628,473.2l7.81,192.079c-3.479,6.023-20.428,66.212-20.428,66.212s151.176,77,193.883-21.235c0,0,8.42-28.734-5.8-88.934S595.814,489.3,595.814,489.3Z" transform="translate(-88.287 340.193)" fill="#F96837"/><path d="M420.193,457.853,402.727,445.62s-24.157,9.917-24.972,29.981-14.7,80.108-14.7,80.108L418.2,585.356Z" transform="translate(-105.386 367.777)" fill="#F96837"/><path d="M355.826,379.547l-8.479,113.621-94.129,141.28-22.588-13.131,68.524-144.163L309.563,377.6Z" transform="translate(166.226 545.81)" fill="#ed9da0"/><path d="M458.658,457.967l28.773-6.423s17.338,5.537,19.705,31.579,4.353,71.365,4.353,71.365l-60.383,44.4-14.992-63.686Z" transform="translate(20.095 377.952)" fill="#F96837"/><circle cx="55.16" cy="55.16" r="55.16" transform="translate(337.846 649.294)" fill="#ed9da0"/><path d="M413.6,449.76h0q-10.54-.005-21.107-.028a6.3,6.3,0,0,1-4.5-1.918,6.1,6.1,0,0,1-1.725-4.471,72.52,72.52,0,0,1,33.742-58.106h0a70.451,70.451,0,0,1,107.028,56.321,6.209,6.209,0,0,1-5.943,6.553c-24.411,1.032-51.491,1.534-87.8,1.628h-.018a6.193,6.193,0,0,1-5.757-3.866l-.584-1.43a3.844,3.844,0,0,0-7.3.555A6.194,6.194,0,0,1,413.6,449.76Z" transform="translate(-65.522 246.376)" fill="#2f2e41"/><path d="M459.776,605.157c-14.825-13.95-21.2-34.192-21.3-54.181-.116-22.83,8.147-44.514,18.834-64.364,6.463-12.005,13.828-23.493,21.2-34.955,2.479-3.856-3.666-7.421-6.133-3.585-24.932,38.779-52.388,84.711-36.31,132.37a72.271,72.271,0,0,0,18.689,29.737c3.327,3.131,8.359-1.882,5.022-5.022Z" transform="translate(11.772 369.161)" fill="#3f3d56"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-78"><circle cx="320" cy="320" r="320" transform="translate(532 131)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-640 -220)"><circle cx="320" cy="320" r="320" transform="translate(640 220)" fill="#f2f2f2"/><g transform="translate(108 89)" clip-path="url(#a-78)"><g transform="translate(-786.643 -263.817)"><path d="M321.754,88.167l2.579,41.86-78.164,3.966,24.206-55.152Z" transform="translate(1347.951 613.625)" fill="#ed9da0"/><path d="M334.533,103.531c-20.951,11.01-54.461,8-92.437,0l-5.938,309.974s123.757,40.089,164.6-11.83L374.29,136.459l-39.769-32.925h0Z" transform="translate(1339.744 633.859)" fill="#F96837"/><path d="M292.933,94.674l-56.348,33.351a54.255,54.255,0,0,0-24.438,61.938L255.7,338.706S184.781,460.54,207.824,471.287c51.783,24.153,129.052,18.273,129.052,18.273l-17.27-291.7L292.931,94.669h0Z" transform="translate(1312.751 626.596)" fill="#3f3d58"/><path d="M288.877,102.924l63.714,24.752,15.049,183.8,42.143,148.069c-71.378,26.055-64.712,13.913-64.712,13.913L333.248,217.964,288.879,102.929h0Z" transform="translate(1382.953 633.363)" fill="#3f3d58"/><path d="M369.77,447.653l-.218-1.005L304.424,145.416a25.9,25.9,0,1,1,50.482-11.6L426.439,427.87,369.767,447.65Z" transform="translate(1395.136 642.123)" fill="#3f3d58"/><circle cx="63.414" cy="63.414" r="63.414" transform="translate(1572.377 586.084)" fill="#ed9da0"/><path d="M352.177,18.334c13.969,4.908,21.961,7.719,29.283,14.771,12.366,11.914,14.408,27.836,16.3,42.631,1.484,11.574,3.4,26.538-3.383,43.634-2.313,5.834-13.534,31.828-35.006,35.112-4.217.645-14.118.814-11.264-1.293,26.412-19.5,37.684-31.27,36.761-61.322-.575-18.674-29.107-38.834-46.048-42.457a28.853,28.853,0,0,0-23.442,5.462c-14.239,11.69-13.633,60.029-28.648,70.133-6.175,4.157-2.061-25.1-6.412-20.354-8.584,9.36-3.079,23.684-1.535,29.153,7.318,25.9,14.984,6.745,22.123,28.858,7.717,23.872-59.961,39.946-62.264,45.277-4.007,9.273,53.223,53.269,37.515,60.9-19.938,9.689-35.656-2.929-44.924,7.888-5.181,6.042-2.378,12.451-11.738,31.26-3.055,6.141-4.592,9.21-5.935,9.1-6.4-.515-16.762-51.744,0-99.452,7.033-20.022,13.923-39.634,32.384-54.978,9.766-8.11,17.954-11.027,20.286-20.5,3.33-13.534-10.5-19.3-13.27-40.651-1.895-14.6-3.226-35.48,1.933-48.863,4.867-12.639,9.094-23.609,20.153-33.556C277.706,16.7,299.147.46,321.883,0c10.467-.21,18.159,14.06,30.293,18.326h0Z" transform="translate(1313.784 549.004)" fill="#090814"/><path d="M334.292,212.03c19.575-2.061,36.449,6.752,37.669,19.684s-13.667,25.078-33.259,27.137a47.53,47.53,0,0,1-23.07-2.97l-83.082,7.644L230.057,223l82.168-3.234a48.2,48.2,0,0,1,22.067-7.733Z" transform="translate(1334.749 722.537)" fill="#ed9da0"/><path d="M260.939,114.224h0a38.592,38.592,0,0,0-43.16,30.264c-14.582,69.338-40.753,217.04.35,219.505,53.743,3.224,105.335-9.667,105.335-9.667l-12.9-74.164-41.92-4.3L293.3,160.529a38.6,38.6,0,0,0-32.357-46.3Z" transform="translate(1306.877 642.308)" fill="#3f3d58"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-88"><circle cx="320" cy="320" r="320" transform="translate(1129 200)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-68 -152)"><circle cx="320" cy="320" r="320" transform="translate(68 152)" fill="#f2f2f2"/><g transform="translate(-1061 -48)" clip-path="url(#a-88)"><g transform="translate(1282.835 383.564)"><path d="M322.991,81.632a77.011,77.011,0,1,0-100.083,73.49l2.574,148.209L343.189,187.152s-45.895-17.77-54.687-41.318a76.927,76.927,0,0,0,34.489-64.2Z" transform="translate(-88.792 -2.564)" fill="#ed9da0"/><path d="M316.956,145.878s26.276-9.358,39.746-36.688c12.372-25.1,13.729-67.868-21.4-78.254,0,0,20.239-17.474-17.075-28.12l4.964,4.579s-4.38-7.91-26.009-3.232c0,0-79.924-9.309-94.11,17.007,0,0-42.9,8.791-20.053,41.422,0,0,1.181,6.35,9.332,6.23L188.277,63.5l12.411,5.326s17.262-27.495,33.554-12.292c0,0,31.159-1.311,46.062-4.041,0,0-2.991,40.025,25.612,47.82S316.956,145.878,316.956,145.878Z" transform="translate(-117.59 -2.564)" fill="#090814"/><path d="M326.614,167.618c-32.442,32.6-63.25,41.349-91.6,14.169L194.983,475.145l16.646,24.119,101.232.288,13.753-331.935Z" transform="translate(-98.23 -2.564)" fill="#F96837"/><path d="M73.546,164.669l16.928,13.913,51.392,29.332A76.58,76.58,0,0,1,188.3,256.9a461.327,461.327,0,0,1,17.4,80.883c8.447,69.355,2.313,160.805,2.313,160.805l-78.132.679,3.4-45.86,12.569-113.461-.333,159.61H54.465s-6.231-270.71,7.347-330.913a7.284,7.284,0,0,1,11.734-3.97Z" transform="translate(160.166 -2.564)" fill="#090814"/><path d="M423.367,181.787l-61.562,29.6a75.081,75.081,0,0,0-41,52.524L295.009,389.2l-8.43,75.786s36.266,32.479,60.065,21.709l-1.7,12.569h55.032l23.389-317.477Z" transform="translate(-286.579 -2.564)" fill="#090814"/><path d="M242.031,183.241,202.393,473.7l-3.454-5,40.035-293.358c25.9,24.833,53.852,19.672,83.229-6.266a4.738,4.738,0,0,1,7.875,3.471c-31.14,29.712-60.736,36.888-88.047,10.7Z" transform="translate(-105.651 -2.564)" fill="#090814"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-90"><circle cx="320" cy="320" r="320" transform="translate(-17355 -6339)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-694 -110)"><circle cx="320" cy="320" r="320" transform="translate(694 110)" fill="#f2f2f2"/><g transform="translate(18049 6449)" clip-path="url(#a-90)"><path d="M697.018,68.443s-30.266-27.136-70.97,24-104.364,76.188-118.98,96.018c0,0,60.534-25.049,81.408-35.485s19.832-8.349,19.832-8.349-28.18,19.832-33.4,39.663-1.044,36.529-10.436,56.359,179.513,13.567,179.513,13.567,18.787-32.35,13.567-65.752S755.464,72.617,697.018,68.443Z" transform="translate(-17678.941 -6248.833)" fill="#090814"/><path d="M625.971,139.83s6.582,46.07-21.625,56.412-17.865,24.445-17.865,24.445l42.31,20.684,45.131-14.1L688.965,204.7S664.52,199.063,671.1,182.14s8.462-22.565,8.462-22.565Z" transform="translate(-17665.141 -6234.853)" fill="#ffb9b9"/><path d="M726.124,251.578s-6.582,86.5-4.7,90.26,0,134.45,0,134.45,13.163,70.515-3.761,74.277S704.5,471.587,704.5,471.587L687.575,362.523l1.88-108.124Z" transform="translate(-17646.828 -6214.972)" fill="#ffb9b9"/><ellipse cx="41.786" cy="41.786" rx="41.786" ry="41.786" transform="translate(-17043.348 -6146.212)" fill="#ffb9b9"/><path d="M584.607,194.763l12.42-4.338s-4.9,8.1,21.428,12.8,53.589,6.366,65.816-9.039c0,0,4.7-2.242,11.279,4.338s10.342,4.7,10.342,4.7l-4.7,24.445-9.4,45.131-12.223,33.848-34.787-7.521L607.17,271.856l-14.1-36.669V201.345Z" transform="translate(-17665.145 -6225.853)" fill="#F96837"/><path d="M706.412,207.4l9.4-6.582s31.967,5.641,33.848,20.684l-24.446,47.013a53.521,53.521,0,0,1-.941,40.429c-9.4,21.625-8.462,26.326-8.462,26.326l-6.582,28.207-119.406,9.4s-4.7-11.279-6.582-13.163-1.88-8.462,0-8.462,0-2.821-1.88-5.641-2.821-3.761,0-7.521-4.7-37.608-4.7-37.608V263.809L544.7,221.5s11.279-16.924,16.924-18.8,32.474-9.3,32.474-9.3l6.073,8.94,8.462,68.047,12.222,41.369,51.464-8.744,19.992-33.565,13.163-39.488Z" transform="translate(-17672.246 -6225.323)" fill="#F96837"/><path d="M715.874,212.466l7.521,5.641s6.582,52.652,4.7,56.412-34.787,7.521-35.728,5.641S715.874,212.466,715.874,212.466Z" transform="translate(-17645.98 -6221.93)" fill="#F96837"/><path d="M584.452,190.684l9.4,62.053s-8.462,92.14-6.582,110.944l1.88,5.641s-3.761-1.88-4.7,1.88,0,15.989,0,15.989-5.641,5.641-7.521,36.669-24.445,105.3-15.989,108.124,59.233,16.924,86.5,14.1,125.053-35.733,124.116-44.195-47.95-127.868-47.95-127.868-8.462-14.1-8.462-15.989,11.279-9.4,8.462-16.924-17.866-86.494-17.866-86.494l10.342-56.412-14.1-3.761-10.342,54.537s-40.429,19.745-82.739,1.88l-9.4-63.935Z" transform="translate(-17669.691 -6226.475)" fill="#090814"/><path d="M619.02,109.233s69.576,47.95,88.375,26.325-32.907-40.429-32.907-40.429l-43.249-4.7Z" transform="translate(-17659.023 -6243.642)" fill="#090814"/><path d="M539.134,261.157s6.582,86.5,4.7,90.26,0,134.45,0,134.45-13.163,70.515,3.761,74.277,13.163-78.977,13.163-78.977L577.682,372.1,575.8,263.977Z" transform="translate(-17673.266 -6213.268)" fill="#ffb9b9"/><path d="M553.875,214.861l-7.521,2.821s-14.1,59.233-10.342,59.233,48.891,5.641,48.891,3.761-8.462-47.95-8.462-47.95Z" transform="translate(-17673.906 -6221.505)" fill="#F96837"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-98"><circle cx="320" cy="320" r="320" transform="translate(16647 15904)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-640 -220)"><circle cx="320" cy="320" r="320" transform="translate(640 220)" fill="#f2f2f2"/><g transform="translate(-16007 -15684)" clip-path="url(#a-98)"><g transform="translate(16783.697 16044.811)"><path d="M574.925,358.759s9.545,31.361,4.091,40.906,9.545,30,34.088,20.453,25.907-20.453,25.907-20.453-9.545-15-12.272-46.36Z" transform="translate(-417.302 -277.318)" fill="#ffb9b9"/><path d="M499.912,567.9s-49.087,24.544-27.27,57.268c12.681,19.022,36.879,56.01,54.921,83.652a278.988,278.988,0,0,1,34.362,74.916l3.437,11.873L579,811.967l28.634-32.725s-42.269-77.721-42.269-92.72S531.273,623.8,531.273,623.8l34.088-21.816S527.182,558.352,499.912,567.9Z" transform="translate(-467.052 -178.981)" fill="#ffb9b9"/><path d="M601.733,627.822S603.1,666,604.46,681c1.125,12.374-9.815,47.021-6.022,85.566a362.319,362.319,0,0,1-.826,74.927l-5.424,49.49,40.906,4.091,13.635-111.809s8.181-79.084,4.091-104.991l1.363-54.541S622.186,612.823,601.733,627.822Z" transform="translate(-409.34 -154.368)" fill="#ffb9b9"/><path d="M579.352,520.482S483.9,581.84,482.541,600.93c0,0,54.541-5.454,55.9,42.269,0,0,32.725-12.272,40.906-15s51.814-31.361,51.814-31.361,17.726,13.635,17.726,35.452-1.364,60,0,62.722,32.725-36.815,58.632-2.727L725.249,598.2s5.454-57.268-5.454-61.359L643.437,508.21Z" transform="translate(-459.908 -205.878)" fill="#2f2e41"/><circle cx="40.906" cy="40.906" r="40.906" transform="translate(136.488 16.674)" fill="#ffb9b9"/><path d="M603.718,393.155s46.14,12.186,52.385-10.951c0,0,56.7,10.951,66.241,47.766s-23.18,125.444-23.18,128.171,12.272,50.451,4.091,53.178-57.268-39.542-95.447-28.634-57.268,2.727-57.268,2.727L533.422,437.453a34.179,34.179,0,0,1,12.152-30.332c8.545-7.033,19.883-14.632,30.875-16.693,21.816-4.091,22.723-6.33,22.723-6.33Z" transform="translate(-436.551 -263.991)" fill="#F96837"/><path d="M551.6,553s12.272,69.54,28.634,60-4.091-60-4.091-60Z" transform="translate(-428.061 -185.221)" fill="#ffb9b9"/><path d="M593.792,559.16S572.529,626.5,591.451,625.6s24.105-55.091,24.105-55.091Z" transform="translate(-413.297 -182.381)" fill="#ffb9b9"/><path d="M567.1,324.219s13.159-28.511,38.38-21.932,39.477,16.449,40.573,26.318-.548,24.673-.548,24.673-2.742-20.287-20.287-15.9-44.96,1.1-44.96,1.1l-4.386,39.477s-4.935-7.128-10.417-2.741S549.556,332.992,567.1,324.219Z" transform="translate(-425.405 -301.302)" fill="#2f2e41"/><path d="M674.792,416.423s-32.725,88.629-30,99.537,0,12.272-4.091,15-15,31.361-15,31.361-42.269,72.267-39.542,73.63,21.816,16.362,27.271,15,1.364-19.089,9.545-21.816,36.815-20.453,46.36-42.269,54.7-157.614,27.063-176.156C696.4,410.708,685.7,400.061,674.792,416.423Z" transform="translate(-412.178 -251.808)" fill="#F96837"/><path d="M551.207,403.7l-.554.231a34.336,34.336,0,0,0-20.4,24.689c-2.977,14.251-5.907,34.863-3.591,54.164,4.091,34.088,6.818,49.087,12.272,60S555.3,605.5,556.661,608.224s5.454,23.18,5.454,23.18,21.816-6.818,34.088-4.091c0,0-10.908-19.089-8.181-23.18s-6.818-62.722-6.818-62.722Z" transform="translate(-439.944 -254.079)" fill="#F96837"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-92"><circle cx="320" cy="320" r="320" transform="translate(980 239)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-33 100)"><circle cx="320" cy="320" r="320" transform="translate(33 -100)" fill="#f2f2f2"/><g transform="translate(-947 -339)" clip-path="url(#a-92)"><g transform="translate(-433.976 85.328)"><path d="M1058.619,314.491l-6.877,33.775-33.668,56.586-41.521-17.734S920.135,328,955.587,319.553a31.091,31.091,0,0,0,11.772-5.245c6.968-5.245,9.149-12.885,9.149-20.356,0-12.336-5.764-24.229-5.764-24.229l72.627-22.872a116,116,0,0,0-5.215,29.429c-.549,19.823,6.8,29.52,12.824,34.171a22.021,22.021,0,0,0,7.64,4.041Z" transform="translate(740.266 176.516)" fill="#ed9da0"/><path d="M1054.149,260.58a57.181,57.181,0,1,1-16.72-40.665A57.425,57.425,0,0,1,1054.149,260.58Z" transform="translate(737.859 153.576)" fill="#ed9da0"/><path d="M1016.181,348.1s-29.7-41.17-18.511-57.165l-50.182,20.57s-30.207-3.66-41.17,41.414a77.964,77.964,0,0,0-1.876,22.872c.4,6.8-.518,18.771-8.264,34.247-12.4,24.778-9.576,81.639,15.767,87.28s34.339,2.806,34.339,2.806-3.37,103.047-18.008,114.864S965.588,624,965.588,624s44.891,2.257,67.976,5.627,87.829-11.817,87.829-11.817-9.576-43.366-12.946-70.95-11.268-86.335-11.268-86.335l57.44-77.766s10.125-47.01-25.342-67.839S1080.482,289,1080.482,289s-35.589,57.943-54.161,60.794C1026.321,349.794,1019.261,352.631,1016.181,348.1Z" transform="translate(711.48 198.637)" fill="#F96837"/><path d="M932.516,338.47s-.564,18.587,2.806,25.922,15.767,47.864,15.767,47.864H922.94s15.248-16.331,14.074-24.214S932.516,338.47,932.516,338.47Z" transform="translate(729.273 224.6)" opacity="0.1"/><path d="M1014.766,457.584s-62.182-15.248-67.976-28.163S925,387.5,925,387.5l6.557-8.844L961.809,402.4s36.031,28.712,52.926,31.533S1014.766,457.584,1014.766,457.584Z" transform="translate(730.354 245.692)" fill="#ed9da0"/><path d="M1014.766,457.584s-62.182-15.248-67.976-28.163S925,387.5,925,387.5l6.557-8.844L961.809,402.4s36.031,28.712,52.926,31.533S1014.766,457.584,1014.766,457.584Z" transform="translate(730.354 245.692)" opacity="0.05"/><path d="M1057.793,382.519v33.729h-5.428a157.85,157.85,0,0,0-76.534,19.808l-10.182,5.657-2.729,1.525-17.459-39.31,16.331-14.638h.839c3.995.381,21.271,1.83,28.59-.64,6.953-2.363,15.584-9.85,36.062-4.574,10.094,2.577,18.709,13.891,28.5,10.354Z" transform="translate(741.091 247.566)" fill="#ed9da0"/><path d="M1098.089,355.356l11.268,12.656v30.695s-9.545,96.841-40.042,107.545-84.688-6.206-84.688-6.206-14.013-37.16-7.456-39.4,57.943-15.828,57.943-15.828-.732-56.815,10.536-73.71c0,0-7.319-52.911,18.023-54.039S1098.089,355.356,1098.089,355.356Z" transform="translate(756.817 213.355)" fill="#F96837"/><path d="M960.79,337.55l17.627,72.429S992.323,409.9,960.79,337.55Z" transform="translate(749.137 224.117)" opacity="0.1"/><path d="M1005.862,329.61s-23.086,37.815-14.074,76.9l4.3.32S988.4,388.727,1005.862,329.61Z" transform="translate(764.31 219.95)" opacity="0.1"/><path d="M978.433,386.85s-5.627,39.4,4.574,55.168c0,0-20.616,8.447-49.557,6.755l-19.7-61.923Z" transform="translate(724.45 249.99)" fill="#F96837"/><path d="M559.363,249.976c-6.68.87-11.719-5.966-14.055-12.283s-4.116-13.673-9.924-17.086c-7.934-4.662-18.085.945-27.158-.593-10.254-1.738-16.91-12.6-17.434-22.974s3.609-20.362,7.661-29.933l1.415,11.9a23.586,23.586,0,0,1,10.305-20.616l-1.816,17.45a18.523,18.523,0,0,1,21.306-15.335l-.287,10.4c11.836-1.408,23.773-2.816,35.642-1.745s23.822,4.827,32.818,12.645c13.457,11.693,18.371,30.945,16.723,48.707s-8.972,34.424-16.615,50.538c-1.921,4.054-4.578,8.626-9.034,9.143-4,.463-7.667-2.882-8.912-6.72a24.338,24.338,0,0,1,.108-11.959c1.126-5.984,2.543-12.1,1.487-18.093s-5.372-11.92-11.415-12.655-12.228,6.174-9.322,11.523Z" transform="translate(1186.412 171.578)" fill="#090814"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-82"><circle cx="320" cy="320" r="320" transform="translate(10854 -10709)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-685 -115)"><circle cx="320" cy="320" r="320" transform="translate(685 115)" fill="#f2f2f2"/><g transform="translate(-10169 10824)" clip-path="url(#a-82)"><g transform="translate(9973 -10818)"><path d="M265.123,161.609c6.564-1.071,13.708,6.781,16.691,10.06,7.965,8.755,9.628,18.941,10.271,23.264,10.15,68.226,15.224,102.338-5.778,118.2-19.96,15.079-56.443,11.035-63.555-2.515-2.77-5.278-.454-10.8,3.21-21.378,6.771-19.548,10.763-39.922,16.691-59.731,13.537-45.232,12.4-66.262,22.469-67.9Z" transform="translate(974.366 154.5)" fill="#090814"/><path d="M88.8,416.253,57.519,475.3c-7.986,15.074-45.777,247.272-28.971,250.2l72.8,2.415,30.2,1.585,31.046.447,76.954,2.553L196.321,430.085,88.8,416.253Z" transform="translate(976 154.5)" fill="#2f2e41"/><path d="M165.826,243.032l62.246,2.515L233.1,266.3l14.99,12.229a19.968,19.968,0,0,1,7.1,18.609l-7,43.983s13.2,31.437-20.12,51.557l-33.324,54.072L79.059,434.8s-10.689-1.258-3.144-8.8,16.976-44.641,16.976-44.641-1.257-16.348,3.144-20.749,1.337-15.719,1.337-15.719l17.9-66.175a29.573,29.573,0,0,1,28.546-21.85h19.852l2.154-13.832Z" transform="translate(976 154.5)" fill="#F96837"/><path d="M644.667,666.158,101.049,520.871a28.742,28.742,0,0,1-6.282-53.033L315.691,348.022a28.866,28.866,0,0,1,18.378-3.094l365.157,60.2a28.743,28.743,0,0,1,23.469,34.192l-42.462,204.9a28.791,28.791,0,0,1-28.072,22.928A29.01,29.01,0,0,1,644.667,666.158Z" transform="translate(976 154.5)" fill="#fff"/><path d="M644.667,666.158,101.049,520.871a28.742,28.742,0,0,1-6.282-53.033L315.691,348.022a28.866,28.866,0,0,1,18.378-3.094l365.157,60.2a28.743,28.743,0,0,1,23.469,34.192l-42.462,204.9a28.791,28.791,0,0,1-28.072,22.928A29.01,29.01,0,0,1,644.667,666.158Zm54.07-258.071-365.157-60.2a25.857,25.857,0,0,0-16.459,2.771L96.2,470.475a25.742,25.742,0,0,0,5.625,47.5L645.442,663.26A25.744,25.744,0,0,0,677.3,643.613l42.462-204.9a25.742,25.742,0,0,0-21.02-30.622l.244-1.48Z" transform="translate(976 154.5)" fill="#090814"/><path d="M619.761,464.494l-48.48,122.332A23.871,23.871,0,0,1,541.323,600.6L184.988,478c-19.675-6.77-21.874-33.718-3.555-43.587l114.675-61.781a23.871,23.871,0,0,1,16.314-2.328l290.14,62.053a23.871,23.871,0,0,1,17.2,32.137Z" transform="translate(976 154.5)" fill="#f2f2f2"/><circle cx="51.557" cy="51.557" r="51.557" transform="translate(1147.171 314.852)" fill="#ed9da0"/><path d="M233.417,135.2c-14.516-2.366-22.311-3.637-30.18-1.886-15.763,3.507-24.907,17.6-31.437,27.665-15.617,24.07-8.556,34.186-23.892,67.9-11,24.188-16.548,23.189-17.6,35.839-2.219,26.554,20.369,53.116,44.641,63.5,1.621.694,26.845,11.249,33.952,2.515,5.21-6.4-3.994-17.423-15.09-47.156-19.511-52.281-10.292-69.754-7.545-74.192,1.735-2.8,6.685-9.774,9.431-8.8,2.484.879.334,7.259,2.515,12.575,5.844,14.243,41.363,17.406,69.162,6.288,8.2-3.279,13.228-5.291,16.976-10.689,12.716-18.315-2.465-56.7-26.407-67.9-5.447-2.549-11.805-3.586-24.521-5.659Z" transform="translate(976 154.5)" fill="#090814"/><path d="M196.554,442.382c12.539,6.36,19.422,17.986,15.373,25.965s-17.494,9.29-30.037,2.926a35.187,35.187,0,0,1-12.772-10.632l-52.79-27.619,13.489-24.5,50.609,29.829a35.19,35.19,0,0,1,16.128,4.028Z" transform="translate(976 154.5)" fill="#ed9da0"/><path d="M443.448,406.845c13.209,4.818,21.43,15.538,18.363,23.944s-16.26,11.313-29.473,6.491a35.188,35.188,0,0,1-13.95-9.031l-55.709-21.12L373.146,381.2l53.808,23.573A35.19,35.19,0,0,1,443.448,406.845Z" transform="translate(976 154.5)" fill="#ed9da0"/><path d="M136.589,269.754s-10.689-22.006-35.21-5.03-82.995,87.4-82.995,87.4-30.18,26.407-13.2,35.839,144.316,63,144.316,63l22.221-18.082-33.742-20.925-72.435-37.2L128.383,327.6l8.206-57.845Z" transform="translate(976 154.5)" fill="#F96837"/><path d="M243.477,282.958s7.481-10.689,20.717,0,51.33,72.235,51.33,72.235l93.944,38.425-13.832,28.294-112.546-40.24-49.042-66.647,9.431-32.066Z" transform="translate(976 154.5)" fill="#F96837"/><g transform="translate(-88.759 -20.435)"><ellipse cx="20.12" cy="10.06" rx="20.12" ry="10.06" transform="translate(1482.294 619.167)" fill="#F96837"/><ellipse cx="20.12" cy="10.06" rx="20.12" ry="10.06" transform="translate(1463.432 649.976)" fill="#3f3d56"/><ellipse cx="54.701" cy="27.351" rx="54.701" ry="27.351" transform="translate(1320.705 591.188)" fill="#F96837"/><path d="M402.787,492.835a1.369,1.369,0,0,0,.178-.011,1.5,1.5,0,0,0,1.313-1.666L400.9,462.6a1.5,1.5,0,0,0-1.669-1.312l-53.709,6.459a1.5,1.5,0,0,0,.358,2.979l52.217-6.279,3.205,27.062A1.5,1.5,0,0,0,402.787,492.835Z" transform="translate(976 154.5)" fill="#fff"/></g></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 4.8 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-76"><circle cx="320" cy="320" r="320" transform="translate(626 151)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-626 -151)"><circle cx="320" cy="320" r="320" transform="translate(626 151)" fill="#f2f2f2"/><g clip-path="url(#a-76)"><path d="M581.722,260.562S595.577,365,574.262,376.728s126.823,12.789,126.823,12.789-33.038-90.588-18.118-118.3Z" transform="translate(318.813 155.394)" fill="#ffb9b9"/><circle cx="73.536" cy="73.536" r="73.536" transform="translate(881.887 324.39)" fill="#ffb9b9"/><path d="M809.257,390.045l-12.32,56.1-26.05,118.69-.78,6.5-8.99,75.25-5.98,49.99-4.01,33.58c-24.38,12.53-42.05,21.18-42.05,21.18s-1.52-7.62-3.97-17.37c-17.11,5.13-48.77,13.64-75.6,15.34,9.77,10.89-141.12-266.12-146.91-303.16-4.66-29.81-8.16-55-8.9-60.36-.1-.7-.15-1.06-.15-1.06l112.43-49.68c7.99,18.53,45.3,24.1,45.3,24.1,30.91-2.13,55.14-18.43,55.14-18.43Z" transform="translate(318.813 155.394)" fill="#F96837"/><path d="M720.129,154.235l13.749-5.5s-28.749-31.651-68.747-28.9l11.25-12.385s-27.5-11.009-52.5,17.89c-13.141,15.191-28.346,33.048-37.825,53.163H571.33l6.146,13.532-21.509,13.532,22.077-2.431a75.616,75.616,0,0,0-.6,22.445,29.041,29.041,0,0,0,10.634,19h0s17.052-35.3,17.052-40.8v13.761S618.88,205.157,618.88,196.9l7.5,9.633,3.75-15.137,46.248,15.137-7.5-12.385,28.749,4.128-11.25-15.137s32.5,17.89,33.749,33.027,10.762,29.481,10.762,29.481S756.378,174.877,720.129,154.235Z" transform="translate(297.666 174.133)" fill="#090814"/><path d="M889.187,647.955c-7.49,8.12-26.05,20.35-48.55,33.59-8.37,4.92-17.28,9.99-26.37,15.03-21.69,12.03-44.4,23.95-63.14,33.58-24.38,12.53-42.05,21.18-42.05,21.18s-1.52-7.62-3.97-17.37c-3.28-13.05-8.22-29.92-13.37-37.39-.18-.26-.36-.5-.54-.74-1.5-1.97-3.01-3.12-4.5-3.12l74.42-46.13,32.16-19.94-23.17-55.31-29.06-69.38,17.54-55.81,17.63-56.1h33.04s10.94,23.88,24.93,57.18c2.09,4.98,4.25,10.17,6.45,15.53C869.417,532.755,905.3,630.5,889.187,647.955Z" transform="translate(318.813 155.394)" fill="#F96837"/><path d="M556.677,695.915a47.792,47.792,0,0,0-8.1.66c-22.99,3.95-29.77,24.76-31.7,38.7a71.847,71.847,0,0,0-.7,12.86l-20.31-15.62-7.4-5.69c-17.81-6.21-33.68-17.24-47.44-30.25a238.478,238.478,0,0,1-31.95-37.89,334.144,334.144,0,0,1-24.72-42.4,31.184,31.184,0,0,1-.43-26.45l25.15-56.05,36.76-81.92q.4-2.925.89-5.72c7.29-41.8,26.82-60.36,26.82-60.36h14.92l9.98,60.36,12.4,74.99-8.69,28.34-20.08,65.45,19.19,20.84Z" transform="translate(318.813 155.394)" fill="#F96837"/><path d="M828.381,510.145H661.938v-3.431H586.466v3.431H419.337A11.259,11.259,0,0,0,408.079,521.4V749.315a11.259,11.259,0,0,0,11.259,11.259H828.381a11.259,11.259,0,0,0,11.259-11.259V521.4a11.259,11.259,0,0,0-11.259-11.259Z" transform="translate(318.813 119.599)" fill="#090814"/><circle cx="25" cy="25" r="25" transform="translate(921.445 684.314)" fill="#f2f2f2"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
@@ -1,21 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/">
|
||||
<defs>
|
||||
<clipPath id="clip-path-107">
|
||||
<circle id="Ellipse_889" data-name="Ellipse 889" cx="320" cy="320" r="320" transform="translate(-4451 -15900)" fill="none" stroke="#707070" stroke-width="1"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="Group_306" data-name="Group 306" transform="translate(-640 -220)">
|
||||
<path id="Path_5233-108" data-name="Path 5233" d="M320,0C496.731,0,640,143.269,640,320S496.731,640,320,640,0,496.731,0,320,143.269,0,320,0Z" transform="translate(640 220)" fill="#F96837"/>
|
||||
<g id="Mask_Group_9" data-name="Mask Group 9" transform="translate(5091 16120)" clip-path="url(#clip-path-107)">
|
||||
<g id="Group_302" data-name="Group 302" transform="translate(-4315.748 -15782.601)">
|
||||
<ellipse id="Ellipse_851" data-name="Ellipse 851" cx="55.3" cy="55.3" rx="55.3" ry="55.3" transform="translate(148.307 30.406)" fill="#ffb9b9"/>
|
||||
<path id="Path_4985-109" data-name="Path 4985" d="M970.3,323.643s-2.514,77.922-15.082,87.977,45.245,52.785,45.245,52.785l37.7-60.326v-55.3Z" transform="translate(-814.455 -225.374)" fill="#ffb9b9"/>
|
||||
<path id="Path_4986-110" data-name="Path 4986" d="M855.123,269.622l-30.517-46.081L807.367,247,782.23,317.381l20.111,273.984,118.143,2.514,15.082-314.2-37.7-45.244Z" transform="translate(-674.142 -65.778)" fill="#f2f2f2"/>
|
||||
<path id="Path_4987-111" data-name="Path 4987" d="M920.045,374.6l20.111-2.514s5.026,2.514,7.541,20.108,32.667,173.442,32.667,173.442L940.145,756.662,894.9,696.336,922.56,590.773,894.908,485.2Z" transform="translate(-610.868 -153.163)" fill="#090814"/>
|
||||
<path id="Path_4988-112" data-name="Path 4988" d="M906.682,248.1H891.6L853.894,451.7l35.189,158.361,35.192-57.814-10.055-62.84,5.013-55.3,17.6-32.68Z" transform="translate(-853.894 -29.172)" fill="#090814"/>
|
||||
<path id="Path_4991-113" data-name="Path 4991" d="M970.562,369.89l10.055-2.514s7.541-42.743,25.137-37.7,62.841,10.055,62.841-10.055-42.744-37.7-67.867-35.192-67.867,10.055-65.355,47.756,18.733,74.384,18.733,74.384l1.319-22.356Z" transform="translate(-799.632 -284.185)" fill="#090814"/>
|
||||
<path id="Path_4994-114" data-name="Path 4994" d="M1212.25,404.431l-80.437-32.677-18.852-13.826L1056.4,608.034,1018.7,494.92l11.311-144.533L925.7,404.431l35.192,170.928,5.026,65.355L950.834,693.5s-52.786,37.7-35.19,77.922,37.7,42.743,37.7,42.743,85.463-80.436,90.5-100.544,12.567-55.3,12.567-55.3,42.743,160.873,93,158.358,50.274-55.3,50.274-55.3l-12.567-55.3-20.108-57.814,10.055-95.513Z" transform="translate(-885.472 -185.507)" fill="#090814"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-94"><circle cx="320" cy="320" r="320" transform="translate(1316 176)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-640 -220)"><circle cx="320" cy="320" r="320" transform="translate(640 220)" fill="#f2f2f2"/><g transform="translate(-676 44)" clip-path="url(#a-94)"><g transform="translate(627.8 -209.043)"><path d="M43.489,0s7.87,20.237,6.226,40.26a21.219,21.219,0,0,1-3.508,10.025h0l96.416,45.774s43.565,4.51,32.692,23.537-50.284-9.513-50.284-9.513S21.745,95.132,13.59,80.183,0,2.718,0,2.718Z" transform="translate(897.712 784.099) rotate(8)" fill="#ed9da0"/><path d="M847.9,199.179s8.054,40.27,8.054,46.31,34.229,24.162,34.229,24.162l38.256-48.323s-24.162-34.229-24.162-42.283Z" transform="translate(101.764 449.918)" fill="#ed9da0"/><circle cx="52.35" cy="52.35" r="52.35" transform="translate(915.432 558.492)" fill="#ed9da0"/><path d="M895.23,240.777s-17.549-4.671-22.869-12.4c0,0-55.657,54.686-55.657,64.753L861,371.652s0,28.189,4.027,30.2,0,0,0,8.054-12.081,60.4-8.054,68.458,8.054,2.013,4.027,14.094-14.094,76.512-14.094,76.512,36.242-12.081,88.593,8.054,114.768-8.054,114.768-8.054-16.108-36.242-12.081-48.323-10.067-34.229-10.067-34.229l-10.067-185.24s14.094-82.552,4.027-86.579l-20.135-8.054-64.479-7.925S921.405,238.763,895.23,240.777Z" transform="translate(84.633 460.671)" fill="#F96837"/><path d="M838.426,250.526,818.291,264.62s-10.067,30.2,0,44.3,41.686,30.2,41.686,30.2h12.678Z" transform="translate(83.047 489.178)" fill="#F96837"/><path d="M840.034,143.073l-9.081-3.635s18.987-20.9,45.4-19.086l-7.43-8.18s18.162-7.271,34.672,11.815c8.679,10.033,18.721,21.826,24.981,35.111h9.725l-4.059,8.937,14.206,8.937-14.581-1.605a49.453,49.453,0,0,1-1.379,23.146l.391,7.064s-16.9-26.15-16.9-29.785v9.089s-9.081-8.18-9.081-13.633l-4.953,6.362-2.477-10-30.544,10,4.953-8.18-18.987,2.727,7.43-10s-21.464,11.815-22.289,21.813-11.557,22.721-11.557,22.721l-4.953-9.089S816.094,156.705,840.034,143.073Z" transform="translate(87.78 412.443)" fill="#2f2e41"/><path d="M996.031,262.223s-11.66,29.982-9.224,59.647a31.438,31.438,0,0,0,5.2,14.852h0L849.159,404.538s-64.543,6.682-48.435,34.871,74.5-14.094,74.5-14.094,153.024-22.148,165.1-44.3,20.135-114.768,20.135-114.768Z" transform="translate(74.438 495.602)" fill="#ed9da0"/><path d="M934.773,208.937h30.2s22.148,4.027,28.189,44.3,12.081,50.337,6.04,50.337-78.525-2.014-78.525-4.027S934.773,208.937,934.773,208.937Z" transform="translate(141.738 466.336)" fill="#F96837"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-86"><circle cx="320" cy="320" r="320" transform="translate(390 119)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-747 -202)"><circle cx="320" cy="320" r="320" transform="translate(747 202)" fill="#f2f2f2"/><g transform="translate(357 83)" clip-path="url(#a-86)"><path d="M618.779,384.128l-28.972-36.216L568.077,273.67l83.3-88.728s18.108-68.81,1.811-65.188-19.919,54.323-19.919,54.323L528.24,255.562S539.1,369.641,569.888,409.479l23.54,74.242Z" transform="translate(51.789 138.409)" fill="#ed9da0"/><path d="M655.37,384.128l28.972-36.216,21.729-74.242-83.3-88.728s-18.108-68.81-1.811-65.188,19.919,54.323,19.919,54.323l105.025,81.485s-10.865,114.079-41.648,153.916l-23.54,74.242Z" transform="translate(94.87 138.409)" fill="#ed9da0"/><path d="M606.631,260.815s1.811,38.026-9.054,50.7-21.729,77.864,30.783,79.674,47.08-54.323,47.08-54.323l-10.865-30.783s-16.3-23.54-10.865-45.27Z" transform="translate(82.044 209.209)" fill="#ed9da0"/><path d="M648.645,323.648,620.39,289.5l-19.138,8.772-19.918,63.377s-16.3,30.783,3.622,63.377c0,0,3.622,21.729-1.811,27.162s-7.243,39.837-7.243,39.837l-23.54,45.27s134,23.54,173.834-9.054c0,0-20.9-77.069-8.229-100.61s14.486-59.628,0-75.925-29.8-58.867-29.8-58.867l-8.769-5.609Z" transform="translate(63.883 222.455)" fill="#F96837"/><ellipse cx="56.799" cy="56.799" rx="56.799" ry="56.799" transform="translate(656.797 371.123)" fill="#090814"/><ellipse cx="42.09" cy="42.089" rx="42.09" ry="42.089" transform="translate(667.604 404.685)" fill="#ed9da0"/><ellipse cx="15.829" cy="15.829" rx="15.829" ry="15.829" transform="translate(707.177 350)" fill="#090814"/><path d="M353.077,485.294S336.9,512.2,299.3,522.265s-.307,66.583-.307,66.583-13.563-20.55,6-42.313S356.037,509.893,353.077,485.294Z" transform="translate(365.168 -102.235)" fill="#090814"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-84"><circle cx="320" cy="320" r="320" transform="translate(1131 211)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-605 -80)"><circle cx="320" cy="320" r="320" transform="translate(605 80)" fill="#f2f2f2"/><g transform="translate(-526 -131)" clip-path="url(#a-84)"><path d="M308.917,275.306a56.766,56.766,0,1,0-76.214,50.68l7.587,72.956,58.052-43.966s-11.356-15.94-17.023-33.58A56.7,56.7,0,0,0,308.917,275.306Z" transform="translate(1202.512 213.572)" fill="#ed9da0"/><path d="M40.4,521.694l-16.694-55.37s-31.3,121.137-1.081,121.137,82.654-37.327,82.654-37.327L65.141,501.289Z" transform="translate(1245.398 155.822)" fill="#ed9da0"/><path d="M459.466,572.6l-.193,83.81-12.25,62.834-74.1-.177,30.356-141.756Z" transform="translate(1161.584 131.316)" fill="#ed9da0"/><path d="M205.109,374.625,178,391.067s-55.991,5.332-61.324,24.885S97.125,435.5,98.014,447.059L70.463,481.72s37.772,40.438,37.772,52.881,24.441-6.879,24.441-6.879V673.867H327.914l5.175-122.38s48.881-34.661,62.213-9.776l-14.22-59.546s.889-43.549-27.551-64.879l-67.545-32s-5.584-9.6-26.914-11.377l-14.857,36.262-32.884,21.33Z" transform="translate(1231.332 177.133)" fill="#F96837"/><path d="M72.54,351.749,65.678,488.9l-47.541,3.285L34.8,349.941c-6.576-7.017-10.511-17.481-9.959-29,.965-20.149,15.265-35.835,31.94-35.036s29.41,17.78,28.444,37.929C84.674,335.353,79.756,345.393,72.54,351.749Z" transform="translate(1243.398 197.434)" fill="#ed9da0"/><path d="M460.626,274.851l-10.355-4.145s18.826-15.054,48.948-12.981c0,0,46.455-2.167,53.593,12.981l19.868,22.418-4.628,10.191,16.2,10.19-16.626-1.83a56.391,56.391,0,0,1-1.573,26.392l.446,8.055s-19.272-29.818-19.272-33.963v10.363s-10.354-9.327-10.354-15.545l-5.648,7.254-2.824-11.4-34.828,11.4,5.648-9.327-21.65,3.109,8.472-11.4s-24.474,13.472-25.415,24.872-13.178,25.908-13.178,25.908L441.8,337.031S433.328,290.4,460.626,274.851Z" transform="translate(950.26 150.506)" fill="#090814"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" height="640" viewBox="0 0 640 640" role="img" artist="Katerina Limpitsouni" source="https://undraw.co/"><defs><clipPath id="a-96"><circle cx="320" cy="320" r="320" transform="translate(-6887 -15230)" fill="none" stroke="#707070" stroke-width="1"/></clipPath></defs><g transform="translate(-640 -220)"><circle cx="320" cy="320" r="320" transform="translate(640 220)" fill="#f2f2f2"/><g transform="translate(7527 15450)" clip-path="url(#a-96)"><g transform="translate(-7107 -15079)"><path d="M631.3,168a86.2,86.2,0,1,0-131.232,45.789L447.449,345.682l258.486-21.906s-130.944-70.3-132.623-98.389A86.112,86.112,0,0,0,631.3,168Z" fill="#a0616a"/><path d="M693.129,291.664l20.021-9.249s22.872,2.916,29.694,28.721,37.97,164.049,37.97,164.049,18.247,18.007,7.789,42.838c0,0,3.643,27.5-7.789,31.643s-88.021,63.265-88.021,63.265l.337-321.266Z" fill="#F96837"/><path d="M632.829,255.642,574.5,225.2c-11.934,59.384-66.926,61.574-78.86,2.191l-38.058,28.251-80.321,26.773,11.683,311.424,163.034-.47.012.47H701.467L713.15,282.415l-80.321-26.773Z" fill="#F96837"/><path d="M397.284,291.664l-20.021-9.249s-22.872,2.916-29.694,28.721,5.841,175,5.841,175-18.247,18.007-7.789,42.838c0,0-3.643,27.5,7.789,31.643s43.873,5.974,43.873,5.974V291.664Z" fill="#F96837"/><path d="M476.326,101.572l-5.943,60.63S408.019,41.194,485.575,18.818c0,0-7.553-10.227,3.408-13.63S603.857-14.532,612.14,36.342c0,0,54.285,33.645,37.856,69.642L630.639,148.3l-17.524.974s-.494-80.569-27.26-77.887S476.326,101.572,476.326,101.572Z" fill="#090814"/></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
BIN
public/avatares/default_icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |