feat: transactions api done
Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
parent
d7295d9f31
commit
1ae3e0ce2b
9 changed files with 202 additions and 74 deletions
|
|
@ -16,17 +16,49 @@ Including another URLconf
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from drf_yasg.views import get_schema_view
|
||||||
|
from drf_yasg import openapi
|
||||||
|
from rest_framework import permissions
|
||||||
|
from django.urls import include, path, re_path
|
||||||
from foldbank.api import AccountsAPI, TransactionsAPI, UpcomingRecurringPaymentAPI
|
from foldbank.api import AccountsAPI, TransactionsAPI, UpcomingRecurringPaymentAPI
|
||||||
|
|
||||||
|
schema_view = get_schema_view(
|
||||||
|
openapi.Info(
|
||||||
|
title="Grapevine API",
|
||||||
|
default_version="v1",
|
||||||
|
description="",
|
||||||
|
terms_of_service="https://gvine.app/terms/",
|
||||||
|
contact=openapi.Contact(email="support@gvine.app"),
|
||||||
|
license=openapi.License(name="BSD License"),
|
||||||
|
),
|
||||||
|
public=True,
|
||||||
|
permission_classes=[permissions.AllowAny],
|
||||||
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path("api/v1/transactions/", TransactionsAPI.as_view()),
|
path("api/v1/transactions/", TransactionsAPI.as_view()),
|
||||||
path("api/v1/accounts/", AccountsAPI.as_view()),
|
path("api/v1/accounts/", AccountsAPI.as_view()),
|
||||||
path("api/v1/recurringPayments/upcoming/", UpcomingRecurringPaymentAPI.as_view()),
|
path("api/v1/recurringPayments/upcoming/", UpcomingRecurringPaymentAPI.as_view()),
|
||||||
|
re_path(
|
||||||
|
r"^swagger(?P<format>\.json|\.yaml)$",
|
||||||
|
schema_view.without_ui(cache_timeout=0),
|
||||||
|
name="schema-json",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
r"^swagger/$",
|
||||||
|
schema_view.with_ui("swagger", cache_timeout=0),
|
||||||
|
name="schema-swagger-ui",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
r"^redoc/$",
|
||||||
|
schema_view.with_ui("redoc", cache_timeout=0),
|
||||||
|
name="schema-redoc",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,12 @@ class UserAdminConfig(UserAdmin):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionConfig(admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
"from_account",
|
||||||
|
"created_at",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
admin.site.register(User, UserAdminConfig)
|
admin.site.register(User, UserAdminConfig)
|
||||||
|
|
@ -91,6 +97,6 @@ admin.site.register(Tag)
|
||||||
admin.site.register(Bank)
|
admin.site.register(Bank)
|
||||||
admin.site.register(Account)
|
admin.site.register(Account)
|
||||||
admin.site.register(RecurringPayment)
|
admin.site.register(RecurringPayment)
|
||||||
admin.site.register(Transaction)
|
admin.site.register(Transaction, TransactionConfig)
|
||||||
admin.site.register(RecurringPaymentTransactionLink)
|
admin.site.register(RecurringPaymentTransactionLink)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ class LimitOffsetPagination(_LimitOffsetPagination):
|
||||||
|
|
||||||
|
|
||||||
def get_transactions(user):
|
def get_transactions(user):
|
||||||
return Transaction.objects.filter(from_account__user=user).order_by("created_at")
|
return Transaction.objects.filter(from_account__user=user).order_by("-created_at")
|
||||||
|
|
||||||
|
|
||||||
class TransactionsAPI(generics.ListAPIView):
|
class TransactionsAPI(generics.ListAPIView):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# standard imports
|
# standard importspopulatedb
|
||||||
import datetime
|
import datetime
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
# third-party imports
|
# third-party imports
|
||||||
from django.utils.timezone import make_aware
|
from django.utils.timezone import make_aware
|
||||||
|
|
@ -226,6 +227,9 @@ class Command(BaseCommand):
|
||||||
Account.objects.get_or_create(**account)
|
Account.objects.get_or_create(**account)
|
||||||
|
|
||||||
# recurring payment
|
# recurring payment
|
||||||
|
ist = ZoneInfo("Asia/Kolkata")
|
||||||
|
today = datetime.datetime.now(tz=ist)
|
||||||
|
yesterday = datetime.datetime.now(tz=ist) - datetime.timedelta(days=1)
|
||||||
recurring_payments = [
|
recurring_payments = [
|
||||||
{
|
{
|
||||||
"from_account": Account.objects.get(user=nishant, bank=Bank.objects.get(name="Axis Bank")),
|
"from_account": Account.objects.get(user=nishant, bank=Bank.objects.get(name="Axis Bank")),
|
||||||
|
|
@ -233,9 +237,9 @@ class Command(BaseCommand):
|
||||||
"amount": "36031",
|
"amount": "36031",
|
||||||
"tag": Tag.objects.get(title="Rent"),
|
"tag": Tag.objects.get(title="Rent"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=23)),
|
"created_at": datetime.datetime(year=2023, month=1, day=23, tzinfo=ist),
|
||||||
"frequency": datetime.timedelta(days=30),
|
"frequency": datetime.timedelta(days=30),
|
||||||
"due_on": make_aware(datetime.datetime(year=2023, month=1, day=23)),
|
"due_on": datetime.datetime(year=2023, month=1, day=23, tzinfo=ist),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -244,9 +248,9 @@ class Command(BaseCommand):
|
||||||
"amount": "36031",
|
"amount": "36031",
|
||||||
"tag": Tag.objects.get(title="Rent"),
|
"tag": Tag.objects.get(title="Rent"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=20)),
|
"created_at": datetime.datetime(year=2023, month=1, day=20, tzinfo=ist),
|
||||||
"frequency": datetime.timedelta(days=30),
|
"frequency": datetime.timedelta(days=30),
|
||||||
"due_on": make_aware(datetime.datetime(year=2023, month=2, day=19)),
|
"due_on": datetime.datetime(year=2023, month=2, day=19, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
@ -261,7 +265,7 @@ class Command(BaseCommand):
|
||||||
"amount": "3940",
|
"amount": "3940",
|
||||||
"tag": Tag.objects.get(title="Tag"),
|
"tag": Tag.objects.get(title="Tag"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=23, hour=11, minute=17)),
|
"created_at": datetime.datetime(year=today.year, month=today.month, day=today.day, hour=11, minute=17, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -270,7 +274,7 @@ class Command(BaseCommand):
|
||||||
"amount": "35",
|
"amount": "35",
|
||||||
"tag": Tag.objects.get(title="Food & Drinks", sub_category="Drink"),
|
"tag": Tag.objects.get(title="Food & Drinks", sub_category="Drink"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=23, hour=23, minute=45)),
|
"created_at": datetime.datetime(year=today.year, month=today.month, day=today.day, hour=23, minute=45, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -279,7 +283,7 @@ class Command(BaseCommand):
|
||||||
"amount": "2399",
|
"amount": "2399",
|
||||||
"tag": Tag.objects.get(title="Groceries"),
|
"tag": Tag.objects.get(title="Groceries"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=23, hour=5, minute=37)),
|
"created_at": datetime.datetime(year=yesterday.year, month=yesterday.month, day=yesterday.day, hour=5, minute=37, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -288,7 +292,7 @@ class Command(BaseCommand):
|
||||||
"amount": "312",
|
"amount": "312",
|
||||||
"tag": Tag.objects.get(title="Food & Drinks", sub_category="Food"),
|
"tag": Tag.objects.get(title="Food & Drinks", sub_category="Food"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=23, hour=12, minute=17)),
|
"created_at": datetime.datetime(year=yesterday.year, month=yesterday.month, day=yesterday.day, hour=12, minute=17, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -297,7 +301,7 @@ class Command(BaseCommand):
|
||||||
"amount": "75",
|
"amount": "75",
|
||||||
"tag": Tag.objects.get(title="Transport"),
|
"tag": Tag.objects.get(title="Transport"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=2, hour=10, minute=32)),
|
"created_at": datetime.datetime(year=2023, month=1, day=2, hour=10, minute=32, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -306,7 +310,7 @@ class Command(BaseCommand):
|
||||||
"amount": "249",
|
"amount": "249",
|
||||||
"tag": Tag.objects.get(title="Food & Drinks", sub_category="Swiggy"),
|
"tag": Tag.objects.get(title="Food & Drinks", sub_category="Swiggy"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=1, hour=11, minute=17)),
|
"created_at": datetime.datetime(year=2023, month=1, day=1, hour=11, minute=17, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -315,11 +319,13 @@ class Command(BaseCommand):
|
||||||
"amount": "199",
|
"amount": "199",
|
||||||
"tag": Tag.objects.get(title="Subscription", sub_category="Netflix"),
|
"tag": Tag.objects.get(title="Subscription", sub_category="Netflix"),
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"created_at": make_aware(datetime.datetime(year=2023, month=1, day=23, hour=23, minute=45)),
|
"created_at": datetime.datetime(year=2022, month=12, day=31, hour=23, minute=45, tzinfo=ist),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
# Transaction.objects.all().delete()
|
# Transaction.objects.all().delete()
|
||||||
for t in transactions:
|
for t in transactions:
|
||||||
Transaction.objects.get_or_create(**t)
|
tnx, _ = Transaction.objects.get_or_create(**t)
|
||||||
|
tnx.created_at = t["defaults"]["created_at"]
|
||||||
|
tnx.save()
|
||||||
|
|
||||||
|
|
|
||||||
5
dev.env
5
dev.env
|
|
@ -1,8 +1,9 @@
|
||||||
# Django
|
# Django
|
||||||
SECRET_KEY=sample
|
SECRET_KEY=sample
|
||||||
DEBUG=true
|
DEBUG=true
|
||||||
ALLOWED_HOSTS=0.0.0.0,localhost,127.0.0.1,*
|
ALLOWED_HOSTS=0.0.0.0,localhost,127.0.0.1,localhost:3000
|
||||||
CSRF_TRUSTED_ORIGINS=https://foldbank.codingcoffee.me
|
CSRF_TRUSTED_ORIGINS=http://localhost:3000,https://foldbank.codingcoffee.me
|
||||||
|
CORS_ALLOWED_ORIGINS=http://localhost:3000,https://foldbank.codingcoffee.me
|
||||||
DJANGO_LOG_LEVEL=INFO
|
DJANGO_LOG_LEVEL=INFO
|
||||||
# Django - Postgres
|
# Django - Postgres
|
||||||
POSTGRES_SERVER=postgres-db
|
POSTGRES_SERVER=postgres-db
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,15 @@
|
||||||
version: '3.7'
|
version: '3.7'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# web:
|
web:
|
||||||
# image: node:16.19.1-alpine3.17
|
image: node:16.19.1-alpine3.17
|
||||||
# restart: unless-stopped
|
restart: unless-stopped
|
||||||
# volumes:
|
volumes:
|
||||||
# - ./web:/app
|
- ./web:/app
|
||||||
# working_dir: /app
|
working_dir: /app
|
||||||
# entrypoint: npm run dev
|
entrypoint: npm run dev
|
||||||
# ports:
|
ports:
|
||||||
# - 3000:3000
|
- 3000:3000
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: foldbank-backend-dev
|
image: foldbank-backend-dev
|
||||||
|
|
|
||||||
|
|
@ -1,64 +1,109 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styles from './recentTnx.module.css'
|
import styles from './recentTnx.module.css'
|
||||||
import { BsTriangleFill } from 'react-icons/bs';
|
import { BsTriangleFill } from 'react-icons/bs';
|
||||||
import SingleTransaction from './SingleTransaction'
|
import SingleTransaction from './SingleTransaction'
|
||||||
|
import useSWR from 'swr'
|
||||||
|
|
||||||
|
|
||||||
export default function RecentTransactions() {
|
export default function RecentTransactions() {
|
||||||
const transactions = [
|
const fetcher = (...args) => fetch(...args).then((res) => res.json())
|
||||||
{
|
const { data, error } = useSWR(`http://localhost:8000/api/v1/transactions/`, fetcher)
|
||||||
title: "Fenny's Banglore",
|
|
||||||
datetime: "Today, 11:17 am",
|
if (error) return <div>Error: Failed to load</div>
|
||||||
amount: "3,940",
|
if (!data) return <div>Loading...</div>
|
||||||
tag: "Tag",
|
|
||||||
}, {
|
const transactions = data.results
|
||||||
title: "Sendoor",
|
|
||||||
datetime: "Today, 11:45 pm",
|
// const transactions = [
|
||||||
amount: "35",
|
// {
|
||||||
tag: "Food & Drinks",
|
// title: "Fenny's Banglore",
|
||||||
icon_type: "drink",
|
// datetime: "Today, 11:17 am",
|
||||||
}, {
|
// amount: "3,940",
|
||||||
title: "Reliance Fresh",
|
// tag: "Tag",
|
||||||
datetime: "Yesterday, 5:37 pm",
|
// }, {
|
||||||
amount: "2,399",
|
// title: "Sendoor",
|
||||||
tag: "Groceries",
|
// datetime: "Today, 11:45 pm",
|
||||||
icon_type: "groceries",
|
// amount: "35",
|
||||||
}, {
|
// tag: "Food & Drinks",
|
||||||
title: "Chai Point",
|
// icon_type: "drink",
|
||||||
datetime: "Yesterday, 12:17 pm",
|
// }, {
|
||||||
amount: "312",
|
// title: "Reliance Fresh",
|
||||||
tag: "Food & Drinks",
|
// datetime: "Yesterday, 5:37 pm",
|
||||||
icon_type: "food",
|
// amount: "2,399",
|
||||||
}, {
|
// tag: "Groceries",
|
||||||
title: "Uber",
|
// icon_type: "groceries",
|
||||||
datetime: "Jan 2, 10:32 am",
|
// }, {
|
||||||
amount: "75",
|
// title: "Chai Point",
|
||||||
tag: "Transport",
|
// datetime: "Yesterday, 12:17 pm",
|
||||||
icon_type: "transport",
|
// amount: "312",
|
||||||
}, {
|
// tag: "Food & Drinks",
|
||||||
title: "Swiggy",
|
// icon_type: "food",
|
||||||
datetime: "Jan 1, 11:17 pm",
|
// }, {
|
||||||
amount: "249",
|
// title: "Uber",
|
||||||
tag: "Food & Drinks",
|
// datetime: "Jan 2, 10:32 am",
|
||||||
icon_type: "swiggy",
|
// amount: "75",
|
||||||
}, {
|
// tag: "Transport",
|
||||||
title: "Netflix",
|
// icon_type: "transport",
|
||||||
datetime: "Dec 31, 11:59 pm",
|
// }, {
|
||||||
amount: "199",
|
// title: "Swiggy",
|
||||||
tag: "Subsciption",
|
// datetime: "Jan 1, 11:17 pm",
|
||||||
icon_type: "netflix",
|
// amount: "249",
|
||||||
|
// tag: "Food & Drinks",
|
||||||
|
// icon_type: "swiggy",
|
||||||
|
// }, {
|
||||||
|
// title: "Netflix",
|
||||||
|
// datetime: "Dec 31, 11:59 pm",
|
||||||
|
// amount: "199",
|
||||||
|
// tag: "Subsciption",
|
||||||
|
// icon_type: "netflix",
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
|
||||||
|
const relateive_date = (date) => {
|
||||||
|
const today = new Date();
|
||||||
|
let fuzzy;
|
||||||
|
|
||||||
|
if (today.getYear() == date.getYear()) {
|
||||||
|
if (today.getMonth() == date.getMonth()) {
|
||||||
|
if (today.getDate() == date.getDate()) {
|
||||||
|
fuzzy = 'Today';
|
||||||
|
} else if (today.getDate() == date.getDate() + 1) {
|
||||||
|
fuzzy = 'Yesterday';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
if (fuzzy == undefined){
|
||||||
|
const monthNames = [
|
||||||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||||
|
];
|
||||||
|
fuzzy = `${monthNames[date.getMonth()]} ${date.getDate()}`
|
||||||
|
}
|
||||||
|
|
||||||
|
let hours = date.getHours()
|
||||||
|
let ampm = 'AM';
|
||||||
|
if (hours >= 12) {
|
||||||
|
ampm = 'PM';
|
||||||
|
hours -= 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzzy = fuzzy + `, ${hours}:${date.getMinutes()} ${ampm}`
|
||||||
|
return fuzzy
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const recent_transactions = [];
|
const recent_transactions = [];
|
||||||
transactions.forEach((transaction) => {
|
transactions.forEach((transaction) => {
|
||||||
recent_transactions.push(
|
recent_transactions.push(
|
||||||
<SingleTransaction
|
<SingleTransaction
|
||||||
title={transaction.title}
|
title={transaction.to_account.holders_name}
|
||||||
tag={transaction.tag}
|
tag={transaction.tag.title}
|
||||||
datetime={transaction.datetime}
|
datetime={relateive_date(new Date(transaction.created_at))}
|
||||||
amount={transaction.amount}
|
amount={transaction.amount}
|
||||||
icon_type={transaction.icon_type}
|
icon_type={transaction.tag.icon_type}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
37
web/package-lock.json
generated
37
web/package-lock.json
generated
|
|
@ -23,6 +23,7 @@
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-icons": "^4.7.1",
|
"react-icons": "^4.7.1",
|
||||||
|
"swr": "^2.1.0",
|
||||||
"typescript": "4.9.5"
|
"typescript": "4.9.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -3901,6 +3902,20 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/swr": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/swr/-/swr-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-4hYl5p3/KalQ1MORealM79g/DtLohmud6yyfXw5l4wjtFksYUnocRFudvyaoUtgj3FrVNK9lS25Av9dsZYvz0g==",
|
||||||
|
"dependencies": {
|
||||||
|
"use-sync-external-store": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"pnpm": "7"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.11.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/synckit": {
|
"node_modules/synckit": {
|
||||||
"version": "0.8.5",
|
"version": "0.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
|
||||||
|
|
@ -4061,6 +4076,14 @@
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-sync-external-store": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|
@ -6776,6 +6799,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
|
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
|
||||||
},
|
},
|
||||||
|
"swr": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/swr/-/swr-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-4hYl5p3/KalQ1MORealM79g/DtLohmud6yyfXw5l4wjtFksYUnocRFudvyaoUtgj3FrVNK9lS25Av9dsZYvz0g==",
|
||||||
|
"requires": {
|
||||||
|
"use-sync-external-store": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"synckit": {
|
"synckit": {
|
||||||
"version": "0.8.5",
|
"version": "0.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
|
||||||
|
|
@ -6895,6 +6926,12 @@
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"use-sync-external-store": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"which": {
|
"which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-icons": "^4.7.1",
|
"react-icons": "^4.7.1",
|
||||||
|
"swr": "^2.1.0",
|
||||||
"typescript": "4.9.5"
|
"typescript": "4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue