Compare commits
54 Commits
6ff47ce1c4
...
test
| Author | SHA1 | Date | |
|---|---|---|---|
| d0c1f49d3e | |||
| 508418523f | |||
| 0853424c4e | |||
| 12e9e49f9b | |||
|
|
25ad592be3 | ||
| a984d2ac0d | |||
|
|
26e6a3c384 | ||
| a4c1773415 | |||
| 8e07daac66 | |||
| 6408b93e5c | |||
| 27fa88b076 | |||
| f60d1bb6de | |||
|
|
b67c4e3aef | ||
| 95b73b9836 | |||
|
|
0d29d8f6a2 | ||
|
|
884e15bb8a | ||
| 99fe11fbeb | |||
|
|
1ea50af96a | ||
|
|
b6bf6ed5c6 | ||
| 7a66d6f429 | |||
| 43f856ee8d | |||
| 506c64e240 | |||
| 718b4d23f1 | |||
| 22e8556c9d | |||
|
|
52c17d7017 | ||
|
|
e094865fc7 | ||
|
|
01c8f4333f | ||
|
|
6cebcacb5d | ||
| c79e08dbb8 | |||
| 789d59b0c9 | |||
| 7388d0f828 | |||
|
|
a0dcb56fda | ||
| e30088209e | |||
|
|
0da596826e | ||
|
|
7aa16c644f | ||
| 56a1495a0b | |||
|
|
72ac41cac0 | ||
|
|
a44885faa5 | ||
| 429268dc82 | |||
| b8caba4a99 | |||
| a7ba68e23a | |||
| 8ff8ffa50e | |||
| 836b6a3bfe | |||
| b980984c3a | |||
| baaa3efcdd | |||
| da165c1a98 | |||
| 126625bace | |||
| 1e6f3c46d1 | |||
| bc7eb7122c | |||
| d30628e941 | |||
| 2d5d6a7487 | |||
| 3943614abb | |||
| ea8d05ddce | |||
| 9fc208192d |
8
.env
8
.env
@@ -21,6 +21,14 @@ AUTH_JWT_SECRET=5c020e6ed3d8d6e67e5804d67c83c4bd5ae474df749af6d63d8f20e7e2ba29b3
|
|||||||
AUTH_JWT_EXPIRATION=86400
|
AUTH_JWT_EXPIRATION=86400
|
||||||
AUTH_REFRESH_EXPIRATION=604800
|
AUTH_REFRESH_EXPIRATION=604800
|
||||||
|
|
||||||
|
# Meili search
|
||||||
|
MEILISEARCH_URL=http://localhost:7700
|
||||||
|
MEILISEARCH_API_KEY=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||||
|
|
||||||
|
# Google Translate Client
|
||||||
|
GOOGLE_APPLICATION_CREDENTIALS=./google-cred.json
|
||||||
|
GOOGLE_CLOUD_PROJECT_ID=translation-343517
|
||||||
|
|
||||||
# Google OAuth2
|
# Google OAuth2
|
||||||
OAUTH_GOOGLE_CLIENT_ID=331979954218-9vrpe08oqhhcgj6bvu6d4lds0dt630m9.apps.googleusercontent.com
|
OAUTH_GOOGLE_CLIENT_ID=331979954218-9vrpe08oqhhcgj6bvu6d4lds0dt630m9.apps.googleusercontent.com
|
||||||
OAUTH_GOOGLE_CLIENT_SECRET=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
|
OAUTH_GOOGLE_CLIENT_SECRET=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
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,3 +4,5 @@ assets/public/dist
|
|||||||
bin/
|
bin/
|
||||||
i18n/*.json
|
i18n/*.json
|
||||||
*_templ.go
|
*_templ.go
|
||||||
|
tmp/main
|
||||||
|
test.go
|
||||||
12
Taskfile.yml
12
Taskfile.yml
@@ -73,10 +73,22 @@ vars:
|
|||||||
MP_SMTP_AUTH_ALLOW_INSECURE: true
|
MP_SMTP_AUTH_ALLOW_INSECURE: true
|
||||||
MP_ENABLE_SPAMASSASSIN: postmark
|
MP_ENABLE_SPAMASSASSIN: postmark
|
||||||
MP_VERBOSE: true
|
MP_VERBOSE: true
|
||||||
|
meilisearch:
|
||||||
|
image: getmeili/meilisearch:latest
|
||||||
|
container_name: meilisearch
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 7700:7700
|
||||||
|
volumes:
|
||||||
|
- meilisearch:/data.ms
|
||||||
|
environment:
|
||||||
|
MEILI_MASTER_KEY: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db_data:
|
db_data:
|
||||||
mailpit_data:
|
mailpit_data:
|
||||||
|
meilisearch:
|
||||||
|
|
||||||
|
|
||||||
includes:
|
includes:
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type Config struct {
|
|||||||
Email EmailConfig
|
Email EmailConfig
|
||||||
I18n I18n
|
I18n I18n
|
||||||
Pdf PdfPrinter
|
Pdf PdfPrinter
|
||||||
|
GoogleTranslate GoogleTranslateConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type I18n struct {
|
type I18n struct {
|
||||||
@@ -82,6 +83,14 @@ type PdfPrinter struct {
|
|||||||
ServerUrl string `env:"PDF_SERVER_URL,http://localhost:8000"`
|
ServerUrl string `env:"PDF_SERVER_URL,http://localhost:8000"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GoogleTranslateConfig holds configuration for the Google Cloud Translation API.
|
||||||
|
// CredentialsFile should point to a service account JSON key file.
|
||||||
|
// ProjectID is your Google Cloud project ID (e.g. "my-project-123").
|
||||||
|
type GoogleTranslateConfig struct {
|
||||||
|
CredentialsFile string `env:"GOOGLE_APPLICATION_CREDENTIALS"`
|
||||||
|
ProjectID string `env:"GOOGLE_CLOUD_PROJECT_ID"`
|
||||||
|
}
|
||||||
|
|
||||||
var cfg *Config
|
var cfg *Config
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -153,6 +162,11 @@ func load() *Config {
|
|||||||
slog.Error("not possible to load env variables for email : ", err.Error(), "")
|
slog.Error("not possible to load env variables for email : ", err.Error(), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = loadEnv(&cfg.GoogleTranslate)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("not possible to load env variables for google translate : ", err.Error(), "")
|
||||||
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ func AuthHandlerRoutes(r fiber.Router) fiber.Router {
|
|||||||
r.Post("/reset-password", handler.ResetPassword)
|
r.Post("/reset-password", handler.ResetPassword)
|
||||||
r.Post("/logout", handler.Logout)
|
r.Post("/logout", handler.Logout)
|
||||||
r.Post("/refresh", handler.RefreshToken)
|
r.Post("/refresh", handler.RefreshToken)
|
||||||
|
r.Post("/update-choice", handler.UpdateJWTToken)
|
||||||
|
|
||||||
// Google OAuth2
|
// Google OAuth2
|
||||||
r.Get("/google", handler.GoogleLogin)
|
r.Get("/google", handler.GoogleLogin)
|
||||||
@@ -344,6 +345,11 @@ func (h *AuthHandler) CompleteRegistration(c fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusCreated).JSON(response)
|
return c.Status(fiber.StatusCreated).JSON(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompleteRegistration handles completion of registration with password
|
||||||
|
func (h *AuthHandler) UpdateJWTToken(c fiber.Ctx) error {
|
||||||
|
return h.UpdateJWTToken(c)
|
||||||
|
}
|
||||||
|
|
||||||
// GoogleLogin redirects the user to Google's OAuth2 consent page
|
// GoogleLogin redirects the user to Google's OAuth2 consent page
|
||||||
func (h *AuthHandler) GoogleLogin(c fiber.Ctx) error {
|
func (h *AuthHandler) GoogleLogin(c fiber.Ctx) error {
|
||||||
// Generate a random state token and store it in a short-lived cookie
|
// Generate a random state token and store it in a short-lived cookie
|
||||||
@@ -408,9 +414,12 @@ func (h *AuthHandler) GoogleCallback(c fiber.Ctx) error {
|
|||||||
|
|
||||||
// Redirect to the locale-prefixed charts page after successful Google login.
|
// Redirect to the locale-prefixed charts page after successful Google login.
|
||||||
// The user's preferred language is stored in the auth response; fall back to "en".
|
// The user's preferred language is stored in the auth response; fall back to "en".
|
||||||
lang := response.User.Lang
|
lang, err := h.authService.GetLangISOCode(response.User.LangID)
|
||||||
if lang == "" {
|
if err != nil {
|
||||||
lang = "en"
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadLangID)).JSON(fiber.Map{
|
||||||
|
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadLangID),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Redirect().To(h.config.App.BaseURL + "/" + lang)
|
return c.Redirect().To(h.config.App.BaseURL + "/" + lang)
|
||||||
}
|
}
|
||||||
|
|||||||
128
app/delivery/web/api/restricted/listProducts.go
Normal file
128
app/delivery/web/api/restricted/listProducts.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package restricted
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/config"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/service/listProductsService"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/query_params"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListProductsHandler handles endpoints that receive, save and translate product descriptions.
|
||||||
|
type ListProductsHandler struct {
|
||||||
|
listProductsService *listProductsService.ListProductsService
|
||||||
|
config *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewListProductsHandler creates a new ListProductsHandler instance
|
||||||
|
func NewListProductsHandler() *ListProductsHandler {
|
||||||
|
listProductsService := listProductsService.New()
|
||||||
|
return &ListProductsHandler{
|
||||||
|
listProductsService: listProductsService,
|
||||||
|
config: config.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListProductsHandlerRoutes(r fiber.Router) fiber.Router {
|
||||||
|
handler := NewListProductsHandler()
|
||||||
|
|
||||||
|
r.Get("/get-listing", handler.GetListing)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ListProductsHandler) GetListing(c fiber.Ctx) error {
|
||||||
|
paging, filters, err := ParseProductFilters(c)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// overrides := map[string]string{
|
||||||
|
// "override_country": c.Query("override_country", ""),
|
||||||
|
// "override_currency": c.Query("override_currency", ""),
|
||||||
|
// }
|
||||||
|
|
||||||
|
id_lang, err := strconv.Atoi(c.Cookies("lang_id", "2"))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
|
}
|
||||||
|
|
||||||
|
listing, err := h.listProductsService.GetListing(uint(id_lang), paging, filters)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(response.Make(&listing.Items, int(listing.Count), i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var columnMapping map[string]string = map[string]string{}
|
||||||
|
|
||||||
|
// var columnMapping map[string]string = map[string]string{
|
||||||
|
// "product_id": "id",
|
||||||
|
// "price": "price_taxed",
|
||||||
|
// "name": "name",
|
||||||
|
// "category_id": "category_id",
|
||||||
|
// "feature_id": "feature_id",
|
||||||
|
// "feature": "feature_name",
|
||||||
|
// "value_id": "value_id",
|
||||||
|
// "value": "value_name",
|
||||||
|
// "status": "active_sale",
|
||||||
|
// "stock": "in_stock",
|
||||||
|
// }
|
||||||
|
|
||||||
|
func ParseProductFilters(c fiber.Ctx) (find.Paging, *filters.FiltersList, error) {
|
||||||
|
var p find.Paging
|
||||||
|
fl := filters.NewFiltersList()
|
||||||
|
// productFilters := new(model.ProductFilters)
|
||||||
|
|
||||||
|
// err := c.Bind().Query(productFilters)
|
||||||
|
// if err != nil {
|
||||||
|
// return p, &fl, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if productFilters.Name != "" {
|
||||||
|
// fl.Append(filters.Where("name LIKE ?", fmt.Sprintf("%%%s%%", productFilters.Name)))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if productFilters.Sort != "" {
|
||||||
|
// ord, err := query_params.ParseOrdering[model.Product](c, columnMapping)
|
||||||
|
// if err != nil {
|
||||||
|
// return p, &fl, err
|
||||||
|
// }
|
||||||
|
// for _, o := range ord {
|
||||||
|
// fl.Append(filters.Order(o.Column, o.IsDesc))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if len(productFilters.Features) > 0 {
|
||||||
|
// fl.Append(featureValueFilters(productFilters.Features))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fl.Append(query_params.ParseWhereScopes[model.Product](c, []string{"name"}, columnMapping)...)
|
||||||
|
|
||||||
|
pageNum, pageElems := query_params.ParsePagination(c)
|
||||||
|
p = find.Paging{Page: pageNum, Elements: pageElems}
|
||||||
|
|
||||||
|
return p, &fl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FeatVal = map[uint][]uint
|
||||||
|
|
||||||
|
func featureValueFilters(feats FeatVal) filters.Filter {
|
||||||
|
filt := func(db *gorm.DB) *gorm.DB {
|
||||||
|
return db.Where("value_id IN ?", lo.Flatten(lo.Values(feats))).Group("id").Having("COUNT(id) = ?", len(lo.Keys(feats)))
|
||||||
|
}
|
||||||
|
return filters.NewFilter(filters.FEAT_VAL_PRODUCT_FILTER, filt)
|
||||||
|
}
|
||||||
52
app/delivery/web/api/restricted/localeSelector.go
Normal file
52
app/delivery/web/api/restricted/localeSelector.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package restricted
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/service/localeSelectorService"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LocaleSelectorHandler for getting languages and countries data
|
||||||
|
type LocaleSelectorHandler struct {
|
||||||
|
localeSelectorService *localeSelectorService.LocaleSelectorService
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocaleSelectorHandler creates a new LocaleSelectorHandler instance
|
||||||
|
func NewLocaleSelectorHandler() *LocaleSelectorHandler {
|
||||||
|
localeSelectorService := localeSelectorService.New()
|
||||||
|
return &LocaleSelectorHandler{
|
||||||
|
localeSelectorService: localeSelectorService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LocaleSelectorHandlerRoutes(r fiber.Router) fiber.Router {
|
||||||
|
handler := NewLocaleSelectorHandler()
|
||||||
|
|
||||||
|
r.Get("/get-languages", handler.GetLanguages)
|
||||||
|
r.Get("/get-countries", handler.GetCountries)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *LocaleSelectorHandler) GetLanguages(c fiber.Ctx) error {
|
||||||
|
languages, err := h.localeSelectorService.GetLanguages()
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(response.Make(&languages, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *LocaleSelectorHandler) GetCountries(c fiber.Ctx) error {
|
||||||
|
countries, err := h.localeSelectorService.GetCountriesAndCurrencies()
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(response.Make(&countries, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
65
app/delivery/web/api/restricted/meiliSearch.go
Normal file
65
app/delivery/web/api/restricted/meiliSearch.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package restricted
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/service/meiliService"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MeiliSearchHandler struct {
|
||||||
|
meiliService *meiliService.MeiliService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMeiliSearchHandler() *MeiliSearchHandler {
|
||||||
|
meiliService := meiliService.New()
|
||||||
|
return &MeiliSearchHandler{
|
||||||
|
meiliService: meiliService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MeiliSearchHandlerRoutes(r fiber.Router) fiber.Router {
|
||||||
|
handler := NewMeiliSearchHandler()
|
||||||
|
|
||||||
|
r.Get("/test", handler.Test)
|
||||||
|
r.Get("/create-index", handler.CreateIndex)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MeiliSearchHandler) CreateIndex(c fiber.Ctx) error {
|
||||||
|
id_lang, err := strconv.Atoi(c.Cookies("lang_id", "2"))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.meiliService.CreateIndex(uint(id_lang))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
nothing := ""
|
||||||
|
return c.JSON(response.Make(¬hing, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MeiliSearchHandler) Test(c fiber.Ctx) error {
|
||||||
|
id_lang, err := strconv.Atoi(c.Cookies("lang_id", "2"))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
|
}
|
||||||
|
|
||||||
|
test, err := h.meiliService.Test(uint(id_lang))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(response.Make(&test, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
47
app/delivery/web/api/restricted/menu.go
Normal file
47
app/delivery/web/api/restricted/menu.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package restricted
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/service/menuService"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MenuHandler struct {
|
||||||
|
menuService *menuService.MenuService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMenuHandler() *MenuHandler {
|
||||||
|
menuService := menuService.New()
|
||||||
|
return &MenuHandler{
|
||||||
|
menuService: menuService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MenuHandlerRoutes(r fiber.Router) fiber.Router {
|
||||||
|
handler := NewMenuHandler()
|
||||||
|
|
||||||
|
r.Get("/get-menu", handler.GetMenu)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MenuHandler) GetMenu(c fiber.Ctx) error {
|
||||||
|
id_lang, err := strconv.Atoi(c.Cookies("lang_id", "2"))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
|
}
|
||||||
|
|
||||||
|
menu, err := h.menuService.GetMenu(uint(id_lang))
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(response.Make(&menu, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"git.ma-al.com/goc_daniel/b2b/app/config"
|
"git.ma-al.com/goc_daniel/b2b/app/config"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/service/productDescriptionService"
|
"git.ma-al.com/goc_daniel/b2b/app/service/productDescriptionService"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
@@ -41,144 +43,110 @@ func ProductDescriptionHandlerRoutes(r fiber.Router) fiber.Router {
|
|||||||
func (h *ProductDescriptionHandler) GetProductDescription(c fiber.Ctx) error {
|
func (h *ProductDescriptionHandler) GetProductDescription(c fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("userID").(uint)
|
userID, ok := c.Locals("userID").(uint)
|
||||||
if !ok {
|
if !ok {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody), // possibly could return a different error
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
productID_attribute := c.Query("productID")
|
productID_attribute := c.Query("productID")
|
||||||
productID, err := strconv.Atoi(productID_attribute)
|
productID, err := strconv.Atoi(productID_attribute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
productShopID_attribute := c.Query("productShopID")
|
|
||||||
productShopID, err := strconv.Atoi(productShopID_attribute)
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
productLangID_attribute := c.Query("productLangID")
|
productLangID_attribute := c.Query("productLangID")
|
||||||
productLangID, err := strconv.Atoi(productLangID_attribute)
|
productLangID, err := strconv.Atoi(productLangID_attribute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := h.productDescriptionService.GetProductDescription(userID, uint(productID), uint(productShopID), uint(productLangID))
|
description, err := h.productDescriptionService.GetProductDescription(userID, uint(productID), uint(productLangID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(err)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
"error": responseErrors.GetErrorCode(c, err),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(response)
|
return c.JSON(response.Make(description, 1, i18n.T_(c, response.Message_OK)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveProductDescription saves the description for a given product ID, in given shop and language
|
// SaveProductDescription saves the description for a given product ID, in given language
|
||||||
func (h *ProductDescriptionHandler) SaveProductDescription(c fiber.Ctx) error {
|
func (h *ProductDescriptionHandler) SaveProductDescription(c fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("userID").(uint)
|
userID, ok := c.Locals("userID").(uint)
|
||||||
if !ok {
|
if !ok {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody), // possibly could return a different error
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
productID_attribute := c.Query("productID")
|
productID_attribute := c.Query("productID")
|
||||||
productID, err := strconv.Atoi(productID_attribute)
|
productID, err := strconv.Atoi(productID_attribute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
productShopID_attribute := c.Query("productShopID")
|
|
||||||
productShopID, err := strconv.Atoi(productShopID_attribute)
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
productLangID_attribute := c.Query("productLangID")
|
productLangID_attribute := c.Query("productLangID")
|
||||||
productLangID, err := strconv.Atoi(productLangID_attribute)
|
productLangID, err := strconv.Atoi(productLangID_attribute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updates := make(map[string]string)
|
updates := make(map[string]string)
|
||||||
if err := c.Bind().Body(&updates); err != nil {
|
if err := c.Bind().Body(&updates); err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = h.productDescriptionService.SaveProductDescription(userID, uint(productID), uint(productShopID), uint(productLangID), updates)
|
err = h.productDescriptionService.SaveProductDescription(userID, uint(productID), uint(productLangID), updates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(err)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
"error": responseErrors.GetErrorCode(c, err),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(fiber.Map{
|
return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK)))
|
||||||
"message": i18n.T_(c, "product_description.successfully_updated_fields"),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProductDescription returns the product description for a given product ID
|
// TranslateProductDescription returns translated product description
|
||||||
func (h *ProductDescriptionHandler) TranslateProductDescription(c fiber.Ctx) error {
|
func (h *ProductDescriptionHandler) TranslateProductDescription(c fiber.Ctx) error {
|
||||||
userID, ok := c.Locals("userID").(uint)
|
userID, ok := c.Locals("userID").(uint)
|
||||||
if !ok {
|
if !ok {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody), // possibly could return a different error
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
productID_attribute := c.Query("productID")
|
productID_attribute := c.Query("productID")
|
||||||
productID, err := strconv.Atoi(productID_attribute)
|
productID, err := strconv.Atoi(productID_attribute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
productShopID_attribute := c.Query("productShopID")
|
|
||||||
productShopID, err := strconv.Atoi(productShopID_attribute)
|
|
||||||
if err != nil {
|
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
productFromLangID_attribute := c.Query("productFromLangID")
|
productFromLangID_attribute := c.Query("productFromLangID")
|
||||||
productFromLangID, err := strconv.Atoi(productFromLangID_attribute)
|
productFromLangID, err := strconv.Atoi(productFromLangID_attribute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
productToLangID_attribute := c.Query("productToLangID")
|
productToLangID_attribute := c.Query("productToLangID")
|
||||||
productToLangID, err := strconv.Atoi(productToLangID_attribute)
|
productToLangID, err := strconv.Atoi(productToLangID_attribute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
"error": responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := h.productDescriptionService.TranslateProductDescription(userID, uint(productID), uint(productShopID), uint(productFromLangID), uint(productToLangID))
|
aiModel := c.Query("model")
|
||||||
|
if aiModel != "OpenAI" && aiModel != "Google" {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
|
}
|
||||||
|
|
||||||
|
description, err := h.productDescriptionService.TranslateProductDescription(userID, uint(productID), uint(productFromLangID), uint(productToLangID), aiModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(err)).JSON(fiber.Map{
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
"error": responseErrors.GetErrorCode(c, err),
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(response)
|
return c.JSON(response.Make(description, 1, i18n.T_(c, response.Message_OK)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,6 @@ func (h *SettingsHandler) GetSettings(cfg *config.Config) fiber.Handler {
|
|||||||
Version: version.GetInfo(),
|
Version: version.GetInfo(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(response.Make(c, fiber.StatusOK, nullable.GetNil(settings), nullable.GetNil(0), i18n.T_(c, response.Message_OK)))
|
return c.JSON(response.Make(nullable.GetNil(settings), 0, i18n.T_(c, response.Message_OK)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,10 +89,27 @@ func (s *Server) Setup() error {
|
|||||||
auth := s.public.Group("/auth")
|
auth := s.public.Group("/auth")
|
||||||
public.AuthHandlerRoutes(auth)
|
public.AuthHandlerRoutes(auth)
|
||||||
|
|
||||||
// Repo routes (restricted)
|
// product description routes (restricted)
|
||||||
productDescription := s.restricted.Group("/product-description")
|
productDescription := s.restricted.Group("/product-description")
|
||||||
restricted.ProductDescriptionHandlerRoutes(productDescription)
|
restricted.ProductDescriptionHandlerRoutes(productDescription)
|
||||||
|
|
||||||
|
// listing products routes (restricted)
|
||||||
|
listProducts := s.restricted.Group("/list-products")
|
||||||
|
restricted.ListProductsHandlerRoutes(listProducts)
|
||||||
|
|
||||||
|
// locale selector (restricted)
|
||||||
|
// this is basically for changing user's selected language and country
|
||||||
|
localeSelector := s.restricted.Group("/langs-and-countries")
|
||||||
|
restricted.LocaleSelectorHandlerRoutes(localeSelector)
|
||||||
|
|
||||||
|
// menu (restricted)
|
||||||
|
menu := s.restricted.Group("/menu")
|
||||||
|
restricted.MenuHandlerRoutes(menu)
|
||||||
|
|
||||||
|
// meili search (restricted)
|
||||||
|
meiliSearch := s.restricted.Group("/meili-search")
|
||||||
|
restricted.MeiliSearchHandlerRoutes(meiliSearch)
|
||||||
|
|
||||||
// // Restricted routes example
|
// // Restricted routes example
|
||||||
// restricted := s.api.Group("/restricted")
|
// restricted := s.api.Group("/restricted")
|
||||||
// restricted.Use(middleware.AuthMiddleware())
|
// restricted.Use(middleware.AuthMiddleware())
|
||||||
|
|||||||
11
app/model/countries.go
Normal file
11
app/model/countries.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// Represents a country together with its associated currency
|
||||||
|
type Country struct {
|
||||||
|
ID uint `gorm:"primaryKey;column:id" json:"id"`
|
||||||
|
Name string `gorm:"column:name" json:"name"`
|
||||||
|
Flag string `gorm:"size:16;not null;column:flag" json:"flag"`
|
||||||
|
CurrencyID uint `gorm:"column:id_currency" json:"currency_id"`
|
||||||
|
CurrencyISOCode string `gorm:"column:iso_code" json:"currency_iso_code"`
|
||||||
|
CurrencyName string `gorm:"column:name" json:"currency_name"`
|
||||||
|
}
|
||||||
@@ -25,7 +25,8 @@ type Customer struct {
|
|||||||
PasswordResetExpires *time.Time `json:"-"`
|
PasswordResetExpires *time.Time `json:"-"`
|
||||||
LastPasswordResetRequest *time.Time `json:"-"`
|
LastPasswordResetRequest *time.Time `json:"-"`
|
||||||
LastLoginAt *time.Time `json:"last_login_at,omitempty"`
|
LastLoginAt *time.Time `json:"last_login_at,omitempty"`
|
||||||
Lang string `gorm:"size:10;default:'en'" json:"lang"` // User's preferred language
|
LangID uint `gorm:"default:2" json:"lang_id"` // User's preferred language
|
||||||
|
CountryID uint `gorm:"default:2" json:"country_id"` // User's selected country
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||||
@@ -76,9 +77,8 @@ type UserSession struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Role CustomerRole `json:"role"`
|
Role CustomerRole `json:"role"`
|
||||||
FirstName string `json:"first_name"`
|
LangID uint `json:"lang_id"`
|
||||||
LastName string `json:"last_name"`
|
CountryID uint `json:"country_id"`
|
||||||
Lang string `json:"lang"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToSession converts User to UserSession
|
// ToSession converts User to UserSession
|
||||||
@@ -87,9 +87,8 @@ func (u *Customer) ToSession() *UserSession {
|
|||||||
UserID: u.ID,
|
UserID: u.ID,
|
||||||
Email: u.Email,
|
Email: u.Email,
|
||||||
Role: u.Role,
|
Role: u.Role,
|
||||||
FirstName: u.FirstName,
|
LangID: u.LangID,
|
||||||
LastName: u.LastName,
|
CountryID: u.CountryID,
|
||||||
Lang: u.Lang,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +106,8 @@ type RegisterRequest struct {
|
|||||||
ConfirmPassword string `json:"confirm_password" form:"confirm_password"`
|
ConfirmPassword string `json:"confirm_password" form:"confirm_password"`
|
||||||
FirstName string `json:"first_name" form:"first_name"`
|
FirstName string `json:"first_name" form:"first_name"`
|
||||||
LastName string `json:"last_name" form:"last_name"`
|
LastName string `json:"last_name" form:"last_name"`
|
||||||
Lang string `form:"lang" json:"lang"`
|
LangID uint `form:"lang_id" json:"lang_id"`
|
||||||
|
CountryID uint `form:"country_id" json:"country_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompleteRegistrationRequest represents the completion of registration with email verification
|
// CompleteRegistrationRequest represents the completion of registration with email verification
|
||||||
|
|||||||
99
app/model/product.go
Normal file
99
app/model/product.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// Product contains each and every column from the table ps_product.
|
||||||
|
type Product struct {
|
||||||
|
ProductID uint `gorm:"column:id_product;primaryKey" json:"product_id" form:"product_id"`
|
||||||
|
SupplierID uint `gorm:"column:id_supplier" json:"supplier_id" form:"supplier_id"`
|
||||||
|
ManufacturerID uint `gorm:"column:id_manufacturer" json:"manufacturer_id" form:"manufacturer_id"`
|
||||||
|
CategoryDefaultID uint `gorm:"column:id_category_default" json:"category_default_id" form:"category_default_id"`
|
||||||
|
ShopDefaultID uint `gorm:"column:id_shop_default" json:"shop_default_id" form:"shop_default_id"`
|
||||||
|
TaxRulesGroupID uint `gorm:"column:id_tax_rules_group" json:"tax_rules_group_id" form:"tax_rules_group_id"`
|
||||||
|
OnSale uint `gorm:"column:on_sale" json:"on_sale" form:"on_sale"`
|
||||||
|
OnlineOnly uint `gorm:"column:online_only" json:"online_only" form:"online_only"`
|
||||||
|
EAN13 string `gorm:"column:ean13;type:varchar(13)" json:"ean13" form:"ean13"`
|
||||||
|
ISBN string `gorm:"column:isbn;type:varchar(32)" json:"isbn" form:"isbn"`
|
||||||
|
UPC string `gorm:"column:upc;type:varchar(12)" json:"upc" form:"upc"`
|
||||||
|
EkoTax float32 `gorm:"column:eko_tax;type:decimal(20,6)" json:"eko_tax" form:"eko_tax"`
|
||||||
|
Quantity uint `gorm:"column:quantity" json:"quantity" form:"quantity"`
|
||||||
|
MinimalQuantity uint `gorm:"column:minimal_quantity" json:"minimal_quantity" form:"minimal_quantity"`
|
||||||
|
LowStockThreshold uint `gorm:"column:low_stock_threshold" json:"low_stock_threshold" form:"low_stock_threshold"`
|
||||||
|
LowStockAlert uint `gorm:"column:low_stock_alert" json:"low_stock_alert" form:"low_stock_alert"`
|
||||||
|
Price float32 `gorm:"column:price;type:decimal(20,6)" json:"price" form:"price"`
|
||||||
|
WholesalePrice float32 `gorm:"column:wholesale_price;type:decimal(20,6)" json:"wholesale_price" form:"wholesale_price"`
|
||||||
|
Unity string `gorm:"column:unity;type:varchar(255)" json:"unity" form:"unity"`
|
||||||
|
UnitPriceRatio float32 `gorm:"column:unit_price_ratio;type:decimal(20,6)" json:"unit_price_ratio" form:"unit_price_ratio"`
|
||||||
|
UnitID uint `gorm:"column:id_unit;primaryKey" json:"unit_id" form:"unit_id"`
|
||||||
|
AdditionalShippingCost float32 `gorm:"column:additional_shipping_cost;type:decimal(20,2)" json:"additional_shipping_cost" form:"additional_shipping_cost"`
|
||||||
|
Reference string `gorm:"column:reference;type:varchar(64)" json:"reference" form:"reference"`
|
||||||
|
SupplierReference string `gorm:"column:supplier_reference;type:varchar(64)" json:"supplier_reference" form:"supplier_reference"`
|
||||||
|
Location string `gorm:"column:location;type:varchar(64)" json:"location" form:"location"`
|
||||||
|
|
||||||
|
Width float32 `gorm:"column:width;type:decimal(20,6)" json:"width" form:"width"`
|
||||||
|
Height float32 `gorm:"column:height;type:decimal(20,6)" json:"height" form:"height"`
|
||||||
|
Depth float32 `gorm:"column:depth;type:decimal(20,6)" json:"depth" form:"depth"`
|
||||||
|
Weight float32 `gorm:"column:weight;type:decimal(20,6)" json:"weight" form:"weight"`
|
||||||
|
OutOfStock uint `gorm:"column:out_of_stock" json:"out_of_stock" form:"out_of_stock"`
|
||||||
|
AdditionalDeliveryTimes uint `gorm:"column:additional_delivery_times" json:"additional_delivery_times" form:"additional_delivery_times"`
|
||||||
|
QuantityDiscount uint `gorm:"column:quantity_discount" json:"quantity_discount" form:"quantity_discount"`
|
||||||
|
Customizable uint `gorm:"column:customizable" json:"customizable" form:"customizable"`
|
||||||
|
UploadableFiles uint `gorm:"column:uploadable_files" json:"uploadable_files" form:"uploadable_files"`
|
||||||
|
TextFields uint `gorm:"column:text_fields" json:"text_fields" form:"text_fields"`
|
||||||
|
|
||||||
|
Active uint `gorm:"column:active" json:"active" form:"active"`
|
||||||
|
RedirectType string `gorm:"column:redirect_type;type:enum('','404','301-product','302-product','301-category','302-category')" json:"redirect_type" form:"redirect_type"`
|
||||||
|
TypeRedirectedID int `gorm:"column:id_type_redirected" json:"type_redirected_id" form:"type_redirected_id"`
|
||||||
|
AvailableForOrder uint `gorm:"column:available_for_order" json:"available_for_order" form:"available_for_order"`
|
||||||
|
AvailableDate string `gorm:"column:available_date;type:date" json:"available_date" form:"available_date"`
|
||||||
|
ShowCondition uint `gorm:"column:show_condition" json:"show_condition" form:"show_condition"`
|
||||||
|
Condition string `gorm:"column:condition;type:enum('new','used','refurbished')" json:"condition" form:"condition"`
|
||||||
|
ShowPrice uint `gorm:"column:show_price" json:"show_price" form:"show_price"`
|
||||||
|
|
||||||
|
Indexed uint `gorm:"column:indexed" json:"indexed" form:"indexed"`
|
||||||
|
Visibility string `gorm:"column:visibility;type:enum('both','catalog','search','none')" json:"visibility" form:"visibility"`
|
||||||
|
CacheIsPack uint `gorm:"column:cache_is_pack" json:"cache_is_pack" form:"cache_is_pack"`
|
||||||
|
CacheHasAttachments uint `gorm:"column:cache_has_attachments" json:"cache_has_attachments" form:"cache_has_attachments"`
|
||||||
|
IsVirtual uint `gorm:"column:is_virtual" json:"is_virtual" form:"is_virtual"`
|
||||||
|
CacheDefaultAttribute uint `gorm:"column:cache_default_attribute" json:"cache_default_attribute" form:"cache_default_attribute"`
|
||||||
|
DateAdd string `gorm:"column:date_add;type:datetime" json:"date_add" form:"date_add"`
|
||||||
|
DateUpd string `gorm:"column:date_upd;type:datetime" json:"date_upd" form:"date_upd"`
|
||||||
|
AdvancedStockManagement uint `gorm:"column:advanced_stock_management" json:"advanced_stock_management" form:"advanced_stock_management"`
|
||||||
|
PackStockType uint `gorm:"column:pack_stock_type" json:"pack_stock_type" form:"pack_stock_type"`
|
||||||
|
State uint `gorm:"column:state" json:"state" form:"state"`
|
||||||
|
DeliveryDays uint `gorm:"column:delivery_days" json:"delivery_days" form:"delivery_days"`
|
||||||
|
}
|
||||||
|
type ProductInList struct {
|
||||||
|
ProductID uint `gorm:"column:ID;primaryKey" json:"product_id" form:"product_id"`
|
||||||
|
Name string `gorm:"column:name" json:"name" form:"name"`
|
||||||
|
ImageID uint `gorm:"column:id_image"`
|
||||||
|
LinkRewrite string `gorm:"column:link_rewrite"`
|
||||||
|
Active uint `gorm:"column:active" json:"active" form:"active"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductFilters struct {
|
||||||
|
Sort string `json:"sort,omitempty" query:"sort,omitempty" example:"price,asc;name,desc"` // sort rule
|
||||||
|
ProductID uint `json:"product_id,omitempty" query:"product_id,omitempty" example:"1"`
|
||||||
|
Price float64 `json:"price,omitempty" query:"price,omitempty" example:"123.45"`
|
||||||
|
Name string `json:"name,omitempty" query:"name,omitempty" example:"Sztabka Złota Britannia"`
|
||||||
|
CategoryID uint `json:"category_id,omitempty" query:"category_id,omitempty" example:"2"`
|
||||||
|
CategoryName string `json:"category_name,omitempty" query:"category_name,omitempty" example:"Złote Monety"`
|
||||||
|
Features FeatVal `query:"features,omitempty"`
|
||||||
|
ActiveSale bool `query:"sale_active,omitempty"`
|
||||||
|
InStock uint `query:"stock,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScannedCategory struct {
|
||||||
|
CategoryID uint `gorm:"column:ID;primaryKey"`
|
||||||
|
Name string `gorm:"column:name"`
|
||||||
|
Active uint `gorm:"column:active"`
|
||||||
|
Position uint `gorm:"column:position"`
|
||||||
|
ParentID uint `gorm:"column:id_parent"`
|
||||||
|
IsRoot uint `gorm:"column:is_root_category"`
|
||||||
|
}
|
||||||
|
type Category struct {
|
||||||
|
CategoryID uint `json:"category_id" form:"category_id"`
|
||||||
|
Name string `json:"name" form:"name"`
|
||||||
|
Active uint `json:"active" form:"active"`
|
||||||
|
Subcategories []Category `json:"subcategories" form:"subcategories"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FeatVal = map[uint][]uint
|
||||||
@@ -18,3 +18,11 @@ type ProductDescription struct {
|
|||||||
DeliveryOutStock string `gorm:"column:delivery_out_stock;type:varchar(255)" json:"delivery_out_stock" form:"delivery_out_stock"`
|
DeliveryOutStock string `gorm:"column:delivery_out_stock;type:varchar(255)" json:"delivery_out_stock" form:"delivery_out_stock"`
|
||||||
Usage string `gorm:"column:usage;type:text" json:"usage" form:"usage"`
|
Usage string `gorm:"column:usage;type:text" json:"usage" form:"usage"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MeiliSearchProduct struct {
|
||||||
|
ProductID uint
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
DescriptionShort string
|
||||||
|
Usage string
|
||||||
|
}
|
||||||
|
|||||||
42
app/repos/categoriesRepo/categoriesRepo.go
Normal file
42
app/repos/categoriesRepo/categoriesRepo.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package categoriesRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UICategoriesRepo interface {
|
||||||
|
GetAllCategories(id_lang uint) ([]model.ScannedCategory, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoriesRepo struct{}
|
||||||
|
|
||||||
|
func New() UICategoriesRepo {
|
||||||
|
return &CategoriesRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CategoriesRepo) GetAllCategories(id_lang uint) ([]model.ScannedCategory, error) {
|
||||||
|
var allCategories []model.ScannedCategory
|
||||||
|
|
||||||
|
err := db.DB.Raw(`
|
||||||
|
SELECT
|
||||||
|
ps_category.id_category AS ID,
|
||||||
|
ps_category_lang.name AS name,
|
||||||
|
ps_category.active AS active,
|
||||||
|
ps_category_shop.position AS position,
|
||||||
|
ps_category.id_parent AS id_parent,
|
||||||
|
ps_category.is_root_category AS is_root_category
|
||||||
|
FROM ps_category
|
||||||
|
LEFT JOIN ps_category_lang
|
||||||
|
ON ps_category_lang.id_category = ps_category.id_category
|
||||||
|
AND ps_category_lang.id_shop = ?
|
||||||
|
AND ps_category_lang.id_lang = ?
|
||||||
|
LEFT JOIN ps_category_shop
|
||||||
|
ON ps_category_shop.id_category = ps_category.id_category
|
||||||
|
AND ps_category_shop.id_shop = ?`,
|
||||||
|
constdata.SHOP_ID, id_lang, constdata.SHOP_ID).
|
||||||
|
Scan(&allCategories).Error
|
||||||
|
|
||||||
|
return allCategories, err
|
||||||
|
}
|
||||||
82
app/repos/listProductsRepo/listProductsRepo.go
Normal file
82
app/repos/listProductsRepo/listProductsRepo.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package listProductsRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UIListProductsRepo interface {
|
||||||
|
GetListing(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListProductsRepo struct{}
|
||||||
|
|
||||||
|
func New() UIListProductsRepo {
|
||||||
|
return &ListProductsRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *ListProductsRepo) GetListing(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error) {
|
||||||
|
var listing []model.ProductInList
|
||||||
|
var total int64
|
||||||
|
|
||||||
|
// var resultIDs []uint
|
||||||
|
// q := db.DB.
|
||||||
|
// // SQL_CALC_FOUND_ROWS is a neat trick which works on MariaDB and
|
||||||
|
// // MySQL. It works when followed by `SELECT FOUND_ROWS();`. To learn
|
||||||
|
// // more see: https://mariarawmodel.com/kb/en/found_rows/
|
||||||
|
// // WARN: This might not work on different SQL databases
|
||||||
|
// Select("DISTINCT SQL_CALC_FOUND_ROWS id").
|
||||||
|
// // Debug().
|
||||||
|
// Scopes(view.FromDBViewForDisplay(langID, countryIso)).
|
||||||
|
// Scopes(scopesForFiltersOnDisplay(db.DB, langID, countryIso, filt)).
|
||||||
|
// Scopes(filt.OfCategory(filters.ORDER_FILTER)...).
|
||||||
|
// Limit(p.Limit()).
|
||||||
|
// Offset(p.Offset())
|
||||||
|
|
||||||
|
err := db.DB.Raw(`
|
||||||
|
SELECT
|
||||||
|
ps_product.id_product AS ID,
|
||||||
|
ps_product_lang.name AS name,
|
||||||
|
ps_product.active AS active,
|
||||||
|
ps_product_lang.link_rewrite AS link_rewrite,
|
||||||
|
COALESCE (
|
||||||
|
ps_image_shop.id_image, any_image.id_image
|
||||||
|
) AS id_image
|
||||||
|
FROM ps_product
|
||||||
|
LEFT JOIN ps_product_lang
|
||||||
|
ON ps_product_lang.id_product = ps_product.id_product
|
||||||
|
AND ps_product_lang.id_shop = ?
|
||||||
|
AND ps_product_lang.id_lang = ?
|
||||||
|
LEFT JOIN ps_image_shop
|
||||||
|
ON ps_image_shop.id_product = ps_product.id_product
|
||||||
|
AND ps_image_shop.id_shop = ?
|
||||||
|
AND ps_image_shop.cover = 1
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT id_product, MIN(id_image) AS id_image
|
||||||
|
FROM ps_image
|
||||||
|
GROUP BY id_product
|
||||||
|
) any_image
|
||||||
|
ON ps_product.id_product = any_image.id_product
|
||||||
|
LIMIT ? OFFSET ?`,
|
||||||
|
constdata.SHOP_ID, id_lang, constdata.SHOP_ID, p.Limit(), p.Offset()).
|
||||||
|
Scan(&listing).Error
|
||||||
|
if err != nil {
|
||||||
|
return find.Found[model.ProductInList]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.DB.Raw(`
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM ps_product`).
|
||||||
|
Scan(&total).Error
|
||||||
|
if err != nil {
|
||||||
|
return find.Found[model.ProductInList]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return find.Found[model.ProductInList]{
|
||||||
|
Items: listing,
|
||||||
|
Count: uint(total),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
36
app/repos/localeSelectorRepo/localeSelectorRepo.go
Normal file
36
app/repos/localeSelectorRepo/localeSelectorRepo.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package localeSelectorRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UILocaleSelectorRepo interface {
|
||||||
|
GetLanguages() ([]model.Language, error)
|
||||||
|
GetCountriesAndCurrencies() ([]model.Country, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocaleSelectorRepo struct{}
|
||||||
|
|
||||||
|
func New() UILocaleSelectorRepo {
|
||||||
|
return &LocaleSelectorRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *LocaleSelectorRepo) GetLanguages() ([]model.Language, error) {
|
||||||
|
var languages []model.Language
|
||||||
|
|
||||||
|
err := db.DB.Table("b2b_language").Scan(&languages).Error
|
||||||
|
|
||||||
|
return languages, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *LocaleSelectorRepo) GetCountriesAndCurrencies() ([]model.Country, error) {
|
||||||
|
var countries []model.Country
|
||||||
|
|
||||||
|
err := db.DB.Table("b2b_countries").
|
||||||
|
Select("b2b_countries.id, b2b_countries.name, b2b_countries.flag, ps_currency.id as id_currency, ps_currency.name as currency_name, ps_currency.iso_code as currency_iso_code").
|
||||||
|
Joins("JOIN ps_currency ON ps_currency.id = b2b_countries.currency").
|
||||||
|
Scan(&countries).Error
|
||||||
|
|
||||||
|
return countries, err
|
||||||
|
}
|
||||||
75
app/repos/productDescriptionRepo/productDescriptionRepo.go
Normal file
75
app/repos/productDescriptionRepo/productDescriptionRepo.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package productDescriptionRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UIProductDescriptionRepo interface {
|
||||||
|
GetProductDescription(productID uint, productLangID uint) (*model.ProductDescription, error)
|
||||||
|
CreateIfDoesNotExist(productID uint, productLangID uint) error
|
||||||
|
UpdateFields(productID uint, productLangID uint, updates map[string]string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductDescriptionRepo struct{}
|
||||||
|
|
||||||
|
func New() UIProductDescriptionRepo {
|
||||||
|
return &ProductDescriptionRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We assume that any user has access to all product descriptions
|
||||||
|
func (r *ProductDescriptionRepo) GetProductDescription(productID uint, productLangID uint) (*model.ProductDescription, error) {
|
||||||
|
var ProductDescription model.ProductDescription
|
||||||
|
|
||||||
|
err := db.DB.
|
||||||
|
Table("ps_product_lang").
|
||||||
|
Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, constdata.SHOP_ID, productLangID).
|
||||||
|
First(&ProductDescription).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("database error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ProductDescription, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it doesn't exist, returns an error.
|
||||||
|
func (r *ProductDescriptionRepo) CreateIfDoesNotExist(productID uint, productLangID uint) error {
|
||||||
|
record := model.ProductDescription{
|
||||||
|
ProductID: productID,
|
||||||
|
ShopID: constdata.SHOP_ID,
|
||||||
|
LangID: productLangID,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := db.DB.
|
||||||
|
Table("ps_product_lang").
|
||||||
|
Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, constdata.SHOP_ID, productLangID).
|
||||||
|
FirstOrCreate(&record).Error
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("database error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ProductDescriptionRepo) UpdateFields(productID uint, productLangID uint, updates map[string]string) error {
|
||||||
|
if len(updates) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
updatesIface := make(map[string]interface{}, len(updates))
|
||||||
|
for k, v := range updates {
|
||||||
|
updatesIface[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
err := db.DB.
|
||||||
|
Table("ps_product_lang").
|
||||||
|
Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, constdata.SHOP_ID, productLangID).
|
||||||
|
Updates(updatesIface).Error
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("database error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/config"
|
"git.ma-al.com/goc_daniel/b2b/app/config"
|
||||||
@@ -13,9 +14,13 @@ import (
|
|||||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/service/emailService"
|
"git.ma-al.com/goc_daniel/b2b/app/service/emailService"
|
||||||
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
|
|
||||||
"github.com/dlclark/regexp2"
|
"github.com/dlclark/regexp2"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -27,8 +32,9 @@ type JWTClaims struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Role model.CustomerRole `json:"customer_role"`
|
Role model.CustomerRole `json:"customer_role"`
|
||||||
FirstName string `json:"first_name"`
|
CartsIDs []uint `json:"carts_ids"`
|
||||||
LastName string `json:"last_name"`
|
LangID uint `json:"lang_id"`
|
||||||
|
CountryID uint `json:"country_id"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +155,8 @@ func (s *AuthService) Register(req *model.RegisterRequest) error {
|
|||||||
EmailVerified: false,
|
EmailVerified: false,
|
||||||
EmailVerificationToken: token,
|
EmailVerificationToken: token,
|
||||||
EmailVerificationExpires: &expiresAt,
|
EmailVerificationExpires: &expiresAt,
|
||||||
Lang: req.Lang,
|
LangID: req.LangID,
|
||||||
|
CountryID: req.CountryID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.db.Create(&user).Error; err != nil {
|
if err := s.db.Create(&user).Error; err != nil {
|
||||||
@@ -158,10 +165,11 @@ func (s *AuthService) Register(req *model.RegisterRequest) error {
|
|||||||
|
|
||||||
// Send verification email
|
// Send verification email
|
||||||
baseURL := config.Get().App.BaseURL
|
baseURL := config.Get().App.BaseURL
|
||||||
lang := req.Lang
|
lang, err := s.GetLangISOCode(req.LangID)
|
||||||
if lang == "" {
|
if err != nil {
|
||||||
lang = "en" // Default to English
|
return responseErrors.ErrBadLangID
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.email.SendVerificationEmail(user.Email, user.EmailVerificationToken, baseURL, lang); err != nil {
|
if err := s.email.SendVerificationEmail(user.Email, user.EmailVerificationToken, baseURL, lang); err != nil {
|
||||||
// Log error but don't fail registration - user can request resend
|
// Log error but don't fail registration - user can request resend
|
||||||
_ = err
|
_ = err
|
||||||
@@ -266,10 +274,11 @@ func (s *AuthService) RequestPasswordReset(emailAddr string) error {
|
|||||||
|
|
||||||
// Send password reset email
|
// Send password reset email
|
||||||
baseURL := config.Get().App.BaseURL
|
baseURL := config.Get().App.BaseURL
|
||||||
lang := "en"
|
lang, err := s.GetLangISOCode(user.LangID)
|
||||||
if user.Lang != "" {
|
if err != nil {
|
||||||
lang = user.Lang
|
return responseErrors.ErrBadLangID
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.email.SendPasswordResetEmail(user.Email, user.PasswordResetToken, baseURL, lang); err != nil {
|
if err := s.email.SendPasswordResetEmail(user.Email, user.PasswordResetToken, baseURL, lang); err != nil {
|
||||||
_ = err
|
_ = err
|
||||||
}
|
}
|
||||||
@@ -471,13 +480,24 @@ func hashToken(raw string) string {
|
|||||||
|
|
||||||
// generateAccessToken generates a short-lived JWT access token
|
// generateAccessToken generates a short-lived JWT access token
|
||||||
func (s *AuthService) generateAccessToken(user *model.Customer) (string, error) {
|
func (s *AuthService) generateAccessToken(user *model.Customer) (string, error) {
|
||||||
|
_, err := s.GetLangISOCode(user.LangID)
|
||||||
|
if err != nil {
|
||||||
|
return "", responseErrors.ErrBadLangID
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.CheckIfCountryExists(user.CountryID)
|
||||||
|
if err != nil {
|
||||||
|
return "", responseErrors.ErrBadCountryID
|
||||||
|
}
|
||||||
|
|
||||||
claims := JWTClaims{
|
claims := JWTClaims{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
Username: user.Email,
|
Username: user.Email,
|
||||||
Role: user.Role,
|
Role: user.Role,
|
||||||
FirstName: user.FirstName,
|
CartsIDs: []uint{},
|
||||||
LastName: user.LastName,
|
LangID: user.LangID,
|
||||||
|
CountryID: user.CountryID,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(s.config.JWTExpiration) * time.Second)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(s.config.JWTExpiration) * time.Second)),
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
@@ -488,6 +508,84 @@ func (s *AuthService) generateAccessToken(user *model.Customer) (string, error)
|
|||||||
return token.SignedString([]byte(s.config.JWTSecret))
|
return token.SignedString([]byte(s.config.JWTSecret))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *AuthService) UpdateJWTToken(c fiber.Ctx) error {
|
||||||
|
// Get user ID from JWT claims in context (set by auth middleware)
|
||||||
|
claims, ok := c.Locals("jwt_claims").(*JWTClaims)
|
||||||
|
if !ok || claims == nil {
|
||||||
|
return c.Status(fiber.StatusUnauthorized).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrNotAuthenticated)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var user model.Customer
|
||||||
|
// Find user by ID
|
||||||
|
if err := s.db.First(&user, claims.UserID).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse language and country_id from query params
|
||||||
|
langIDStr := c.Query("lang_id")
|
||||||
|
|
||||||
|
var langID uint
|
||||||
|
if langIDStr != "" {
|
||||||
|
parsedID, err := strconv.ParseUint(langIDStr, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadLangID)))
|
||||||
|
}
|
||||||
|
langID = uint(parsedID)
|
||||||
|
|
||||||
|
_, err = s.GetLangISOCode(langID)
|
||||||
|
if err != nil {
|
||||||
|
return responseErrors.ErrBadLangID
|
||||||
|
} else {
|
||||||
|
user.LangID = langID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
countryIDStr := c.Query("country_id")
|
||||||
|
|
||||||
|
var countryID uint
|
||||||
|
if countryIDStr != "" {
|
||||||
|
parsedID, err := strconv.ParseUint(countryIDStr, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadCountryID)))
|
||||||
|
}
|
||||||
|
countryID = uint(parsedID)
|
||||||
|
|
||||||
|
err = s.CheckIfCountryExists(countryID)
|
||||||
|
if err != nil {
|
||||||
|
return responseErrors.ErrBadCountryID
|
||||||
|
} else {
|
||||||
|
user.CountryID = countryID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update choice and get new token using AuthService
|
||||||
|
newToken, err := s.generateAccessToken(&user)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the updated user
|
||||||
|
if err := s.db.Save(&user).Error; err != nil {
|
||||||
|
return fmt.Errorf("database error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new JWT cookie
|
||||||
|
cookie := new(fiber.Cookie)
|
||||||
|
cookie.Name = "jwt_token"
|
||||||
|
cookie.Value = newToken
|
||||||
|
cookie.HTTPOnly = true
|
||||||
|
cookie.Secure = true
|
||||||
|
cookie.SameSite = fiber.CookieSameSiteLaxMode
|
||||||
|
|
||||||
|
c.Cookie(cookie)
|
||||||
|
|
||||||
|
return c.JSON(response.Make(&fiber.Map{"token": newToken}, 0, i18n.T_(c, response.Message_OK)))
|
||||||
|
}
|
||||||
|
|
||||||
// generateVerificationToken generates a random verification token
|
// generateVerificationToken generates a random verification token
|
||||||
func (s *AuthService) generateVerificationToken() (string, error) {
|
func (s *AuthService) generateVerificationToken() (string, error) {
|
||||||
bytes := make([]byte, 32)
|
bytes := make([]byte, 32)
|
||||||
@@ -507,3 +605,29 @@ func validatePassword(password string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *AuthService) GetLangISOCode(langID uint) (string, error) {
|
||||||
|
var lang string
|
||||||
|
|
||||||
|
if langID == 0 { // retrieve the default lang
|
||||||
|
err := db.DB.Table("b2b_language").Where("is_default = ?", 1).Select("iso_code").Scan(&lang).Error
|
||||||
|
return lang, err
|
||||||
|
} else {
|
||||||
|
err := db.DB.Table("b2b_language").Where("id = ?", langID).Where("active = ?", 1).Select("iso_code").Scan(&lang).Error
|
||||||
|
return lang, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *AuthService) CheckIfCountryExists(countryID uint) error {
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
err := db.DB.Table("b2b_countries").Where("id = ?", countryID).Count(&count).Error
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
return responseErrors.ErrBadCountryID
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.
|
|||||||
Role: model.RoleUser,
|
Role: model.RoleUser,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
EmailVerified: true,
|
EmailVerified: true,
|
||||||
Lang: "en",
|
LangID: 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.db.Create(&newUser).Error; err != nil {
|
if err := s.db.Create(&newUser).Error; err != nil {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package langsService
|
package langsService
|
||||||
|
|
||||||
import (
|
import (
|
||||||
langs_repo "git.ma-al.com/goc_daniel/b2b/app/langs"
|
langs_repo "git.ma-al.com/goc_daniel/b2b/app/repos/langsRepo"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||||
@@ -27,9 +27,10 @@ var LangSrv *LangService
|
|||||||
func (s *LangService) GetActive(c fiber.Ctx) response.Response[[]view.Language] {
|
func (s *LangService) GetActive(c fiber.Ctx) response.Response[[]view.Language] {
|
||||||
res, err := s.repo.GetActive()
|
res, err := s.repo.GetActive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Make[[]view.Language](c, fiber.StatusBadRequest, nil, nil, i18n.T_(c, response.Message_NOK))
|
c.Status(fiber.StatusBadRequest)
|
||||||
|
return response.Make[[]view.Language](nil, 0, i18n.T_(c, response.Message_NOK))
|
||||||
}
|
}
|
||||||
return response.Make(c, fiber.StatusOK, nullable.GetNil(res), nullable.GetNil(len(res)), i18n.T_(c, response.Message_OK))
|
return response.Make(nullable.GetNil(res), 0, i18n.T_(c, response.Message_OK))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadTranslations loads all translations from the database into the cache
|
// LoadTranslations loads all translations from the database into the cache
|
||||||
@@ -54,25 +55,27 @@ func (s *LangService) ReloadTranslations() error {
|
|||||||
func (s *LangService) GetTranslations(c fiber.Ctx, langID uint, scope string, components []string) response.Response[*i18n.TranslationResponse] {
|
func (s *LangService) GetTranslations(c fiber.Ctx, langID uint, scope string, components []string) response.Response[*i18n.TranslationResponse] {
|
||||||
translations, err := i18n.TransStore.GetTranslations(langID, scope, components)
|
translations, err := i18n.TransStore.GetTranslations(langID, scope, components)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Make[*i18n.TranslationResponse](c, fiber.StatusBadRequest, nil, nil, i18n.T_(c, Message_TranslationsNOK))
|
c.Status(fiber.StatusBadRequest)
|
||||||
|
return response.Make[*i18n.TranslationResponse](nil, 0, i18n.T_(c, Message_TranslationsNOK))
|
||||||
}
|
}
|
||||||
return response.Make(c, fiber.StatusOK, nullable.GetNil(translations), nil, i18n.T_(c, Message_TranslationsOK))
|
return response.Make(nullable.GetNil(translations), 0, i18n.T_(c, Message_TranslationsOK))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllTranslations returns all translations from the cache
|
// GetAllTranslations returns all translations from the cache
|
||||||
func (s *LangService) GetAllTranslationsResponse(c fiber.Ctx) response.Response[*i18n.TranslationResponse] {
|
func (s *LangService) GetAllTranslationsResponse(c fiber.Ctx) response.Response[*i18n.TranslationResponse] {
|
||||||
translations := i18n.TransStore.GetAllTranslations()
|
translations := i18n.TransStore.GetAllTranslations()
|
||||||
return response.Make(c, fiber.StatusOK, nullable.GetNil(translations), nil, i18n.T_(c, Message_TranslationsOK))
|
return response.Make(nullable.GetNil(translations), 0, i18n.T_(c, Message_TranslationsOK))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReloadTranslationsResponse returns response after reloading translations
|
// ReloadTranslationsResponse returns response after reloading translations
|
||||||
func (s *LangService) ReloadTranslationsResponse(c fiber.Ctx) response.Response[map[string]string] {
|
func (s *LangService) ReloadTranslationsResponse(c fiber.Ctx) response.Response[map[string]string] {
|
||||||
err := s.ReloadTranslations()
|
err := s.ReloadTranslations()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Make[map[string]string](c, fiber.StatusInternalServerError, nil, nil, i18n.T_(c, Message_LangsNotLoaded))
|
c.Status(fiber.StatusInternalServerError)
|
||||||
|
return response.Make[map[string]string](nil, 0, i18n.T_(c, Message_LangsNotLoaded))
|
||||||
}
|
}
|
||||||
result := map[string]string{"status": "success"}
|
result := map[string]string{"status": "success"}
|
||||||
return response.Make(c, fiber.StatusOK, nullable.GetNil(result), nil, i18n.T_(c, Message_LangsLoaded))
|
return response.Make(nullable.GetNil(result), 0, i18n.T_(c, Message_LangsLoaded))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultLanguage returns the default language
|
// GetDefaultLanguage returns the default language
|
||||||
|
|||||||
59
app/service/listProductsService/listProductsService.go
Normal file
59
app/service/listProductsService/listProductsService.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package listProductsService
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/repos/listProductsRepo"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListProductsService struct {
|
||||||
|
listProductsRepo listProductsRepo.UIListProductsRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *ListProductsService {
|
||||||
|
return &ListProductsService{
|
||||||
|
listProductsRepo: listProductsRepo.New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ListProductsService) GetListing(id_lang uint, p find.Paging, filters *filters.FiltersList) (find.Found[model.ProductInList], error) {
|
||||||
|
var products find.Found[model.ProductInList]
|
||||||
|
|
||||||
|
// currencyIso := c.Cookies("currency_iso", "")
|
||||||
|
// countryIso := c.Cookies("country_iso", "")
|
||||||
|
|
||||||
|
// if overrides["override_currency"] != "" {
|
||||||
|
// currencyIso = overrides["override_currency"]
|
||||||
|
// }
|
||||||
|
// if overrides["override_country"] != "" {
|
||||||
|
// countryIso = overrides["override_country"]
|
||||||
|
// }
|
||||||
|
|
||||||
|
products, err := s.listProductsRepo.GetListing(id_lang, p, filters)
|
||||||
|
if err != nil {
|
||||||
|
return products, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// var loopErr error
|
||||||
|
// parallel.ForEach(products.Items, func(t model.Product, i int) {
|
||||||
|
// // products.Items[i].PriceTaxed *= currRate.Rate.InexactFloat64()
|
||||||
|
// // products.Items[i].PriceTaxed = tiny_util.RoundUpMonetary(products.Items[i].PriceTaxed)
|
||||||
|
|
||||||
|
// if products.Items[i].Name.IsNull() {
|
||||||
|
// translation, err := s.listProductsRepo.GetTranslation(ctx, products.Items[i].ID, defaults.DefaultLanguageID)
|
||||||
|
// if err != nil {
|
||||||
|
// loopErr = err
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// products.Items[i].Name = nullable.FromPrimitiveString(translation.Name)
|
||||||
|
// products.Items[i].DescriptionShort = nullable.FromPrimitiveString(translation.DescriptionShort)
|
||||||
|
// products.Items[i].LinkRewrite = nullable.FromPrimitiveString(translation.LinkRewrite)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// if loopErr != nil {
|
||||||
|
// return products, errs.Handled(span, loopErr, errs.InternalError, errs.ERR_TODO)
|
||||||
|
// }
|
||||||
|
|
||||||
|
return products, nil
|
||||||
|
}
|
||||||
26
app/service/localeSelectorService/localeSelectorService.go
Normal file
26
app/service/localeSelectorService/localeSelectorService.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package localeSelectorService
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/repos/localeSelectorRepo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LocaleSelectorService literally sends back language and countries information.
|
||||||
|
type LocaleSelectorService struct {
|
||||||
|
repo localeSelectorRepo.UILocaleSelectorRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLocaleSelectorService creates a new LocaleSelector service
|
||||||
|
func New() *LocaleSelectorService {
|
||||||
|
return &LocaleSelectorService{
|
||||||
|
repo: localeSelectorRepo.New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LocaleSelectorService) GetLanguages() ([]model.Language, error) {
|
||||||
|
return s.repo.GetLanguages()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LocaleSelectorService) GetCountriesAndCurrencies() ([]model.Country, error) {
|
||||||
|
return s.repo.GetCountriesAndCurrencies()
|
||||||
|
}
|
||||||
155
app/service/meiliService/meiliService.go
Normal file
155
app/service/meiliService/meiliService.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
package meiliService
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||||
|
"github.com/meilisearch/meilisearch-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MeiliService struct {
|
||||||
|
meiliClient meilisearch.ServiceManager
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *MeiliService {
|
||||||
|
meiliURL := os.Getenv("MEILISEARCH_URL")
|
||||||
|
meiliAPIKey := os.Getenv("MEILISEARCH_API_KEY")
|
||||||
|
|
||||||
|
client := meilisearch.New(
|
||||||
|
meiliURL,
|
||||||
|
meilisearch.WithAPIKey(meiliAPIKey),
|
||||||
|
)
|
||||||
|
|
||||||
|
return &MeiliService{
|
||||||
|
meiliClient: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================================== FOR SUPERADMIN ONLY ====================================
|
||||||
|
func (s *MeiliService) CreateIndex(id_lang uint) error {
|
||||||
|
var products []model.ProductDescription
|
||||||
|
|
||||||
|
err := db.DB.
|
||||||
|
Table("ps_product_lang").
|
||||||
|
Where("id_shop = ? AND id_lang = ?", constdata.SHOP_ID, id_lang).
|
||||||
|
Scan(&products).Error
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("database error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var meiliProducts []model.MeiliSearchProduct
|
||||||
|
for i := 0; i < len(products); i++ {
|
||||||
|
var nextMeiliProduct model.MeiliSearchProduct
|
||||||
|
|
||||||
|
nextMeiliProduct.ProductID = products[i].ProductID
|
||||||
|
nextMeiliProduct.Name = products[i].Name
|
||||||
|
nextMeiliProduct.Description = cleanHTML(products[i].Description)
|
||||||
|
nextMeiliProduct.DescriptionShort = cleanHTML(products[i].DescriptionShort)
|
||||||
|
nextMeiliProduct.Usage = cleanHTML(products[i].Usage)
|
||||||
|
|
||||||
|
meiliProducts = append(meiliProducts, nextMeiliProduct)
|
||||||
|
}
|
||||||
|
|
||||||
|
indexName := "meili_products_shop" + strconv.FormatInt(constdata.SHOP_ID, 10) + "_lang" + strconv.FormatInt(int64(id_lang), 10)
|
||||||
|
primaryKey := "product_id"
|
||||||
|
docOptions := &meilisearch.DocumentOptions{
|
||||||
|
PrimaryKey: &primaryKey,
|
||||||
|
SkipCreation: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
task, err := s.meiliClient.Index(indexName).AddDocuments(meiliProducts, docOptions)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("meili AddDocuments error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
finishedTask, err := s.meiliClient.WaitForTask(task.TaskUID, 500*time.Millisecond)
|
||||||
|
fmt.Printf("Task status: %s\n", finishedTask.Status)
|
||||||
|
fmt.Printf("Task error: %s\n", finishedTask.Error)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================================== FOR DEBUG ONLY ====================================
|
||||||
|
func (s *MeiliService) Test(id_lang uint) (meilisearch.SearchResponse, error) {
|
||||||
|
indexName := "meili_products_shop" + strconv.FormatInt(constdata.SHOP_ID, 10) + "_lang" + strconv.FormatInt(int64(id_lang), 10)
|
||||||
|
|
||||||
|
searchReq := &meilisearch.SearchRequest{
|
||||||
|
Limit: 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform search
|
||||||
|
results, err := s.meiliClient.Index(indexName).Search("walek", searchReq)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Meilisearch error: %v\n", err)
|
||||||
|
return meilisearch.SearchResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Search results for query 'walek' in %s: %d hits\n", indexName, len(results.Hits))
|
||||||
|
|
||||||
|
return *results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search performs a full-text search on the specified index
|
||||||
|
func (s *MeiliService) Search(indexName string, query string, limit int) (meilisearch.SearchResponse, error) {
|
||||||
|
searchReq := &meilisearch.SearchRequest{
|
||||||
|
Limit: int64(limit),
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := s.meiliClient.Index(indexName).Search(query, searchReq)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Meilisearch search error: %v\n", err)
|
||||||
|
return meilisearch.SearchResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return *results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HealthCheck checks if Meilisearch is healthy and accessible
|
||||||
|
func (s *MeiliService) HealthCheck() (*meilisearch.Health, error) {
|
||||||
|
health, err := s.meiliClient.Health()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("meilisearch health check failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return health, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all tags from HTML text
|
||||||
|
func cleanHTML(s string) string {
|
||||||
|
r := strings.NewReader(s)
|
||||||
|
d := xml.NewDecoder(r)
|
||||||
|
|
||||||
|
text := ""
|
||||||
|
|
||||||
|
// Configure the decoder for HTML; leave off strict and autoclose for XHTML
|
||||||
|
d.Strict = true
|
||||||
|
d.AutoClose = xml.HTMLAutoClose
|
||||||
|
d.Entity = xml.HTMLEntity
|
||||||
|
for {
|
||||||
|
token, err := d.Token()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := token.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
text += "\n"
|
||||||
|
case xml.EndElement:
|
||||||
|
case xml.CharData:
|
||||||
|
text += string(v)
|
||||||
|
case xml.Comment:
|
||||||
|
case xml.ProcInst:
|
||||||
|
case xml.Directive:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
||||||
90
app/service/menuService/menuService.go
Normal file
90
app/service/menuService/menuService.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package menuService
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/repos/categoriesRepo"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MenuService struct {
|
||||||
|
categoriesRepo categoriesRepo.UICategoriesRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *MenuService {
|
||||||
|
return &MenuService{
|
||||||
|
categoriesRepo: categoriesRepo.New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MenuService) GetMenu(id_lang uint) (model.Category, error) {
|
||||||
|
all_categories, err := s.categoriesRepo.GetAllCategories(id_lang)
|
||||||
|
if err != nil {
|
||||||
|
return model.Category{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the root
|
||||||
|
root_index := 0
|
||||||
|
root_found := false
|
||||||
|
for i := 0; i < len(all_categories); i++ {
|
||||||
|
if all_categories[i].IsRoot == 1 {
|
||||||
|
root_index = i
|
||||||
|
root_found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !root_found {
|
||||||
|
return model.Category{}, responseErrors.ErrNoRootFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// now create the children and reorder them according to position
|
||||||
|
id_to_index := make(map[uint]int)
|
||||||
|
for i := 0; i < len(all_categories); i++ {
|
||||||
|
id_to_index[all_categories[i].CategoryID] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
children_indices := make(map[int][]ChildWithPosition)
|
||||||
|
for i := 0; i < len(all_categories); i++ {
|
||||||
|
parent_index := id_to_index[all_categories[i].ParentID]
|
||||||
|
children_indices[parent_index] = append(children_indices[parent_index], ChildWithPosition{Index: i, Position: all_categories[i].Position})
|
||||||
|
}
|
||||||
|
|
||||||
|
for key := range children_indices {
|
||||||
|
sort.Sort(ByPosition(children_indices[key]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally, create the tree
|
||||||
|
tree := s.createTree(root_index, &all_categories, &children_indices)
|
||||||
|
|
||||||
|
return tree, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MenuService) createTree(index int, all_categories *([]model.ScannedCategory), children_indices *(map[int][]ChildWithPosition)) model.Category {
|
||||||
|
node := s.scannedToNormalCategory((*all_categories)[index])
|
||||||
|
|
||||||
|
for i := 0; i < len((*children_indices)[index]); i++ {
|
||||||
|
node.Subcategories = append(node.Subcategories, s.createTree((*children_indices)[index][i].Index, all_categories, children_indices))
|
||||||
|
}
|
||||||
|
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MenuService) scannedToNormalCategory(scanned model.ScannedCategory) model.Category {
|
||||||
|
var normal model.Category
|
||||||
|
normal.Active = scanned.Active
|
||||||
|
normal.CategoryID = scanned.CategoryID
|
||||||
|
normal.Name = scanned.Name
|
||||||
|
normal.Subcategories = []model.Category{}
|
||||||
|
return normal
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChildWithPosition struct {
|
||||||
|
Index int
|
||||||
|
Position uint
|
||||||
|
}
|
||||||
|
type ByPosition []ChildWithPosition
|
||||||
|
|
||||||
|
func (a ByPosition) Len() int { return len(a) }
|
||||||
|
func (a ByPosition) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
func (a ByPosition) Less(i, j int) bool { return a[i].Position < a[j].Position }
|
||||||
8
app/service/productDescriptionService/google_out.txt
Normal file
8
app/service/productDescriptionService/google_out.txt
Normal file
File diff suppressed because one or more lines are too long
165
app/service/productDescriptionService/openai_out.txt
Normal file
165
app/service/productDescriptionService/openai_out.txt
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
<translation_of_product_description><p>The use of rehabilitation rollers in various types of exercises and treatments positively affects the alleviation of injuries and increases the chances for the patient to return to full physical fitness. They are used in movement rehabilitation, during corrective gymnastics, traditional and sports massages, as they are ideal for lifting and separating limbs. They can also be used to support the knees, feet, arms, and shoulders of the patient. Rehabilitation rollers are also recommended for children; using them during play significantly supports the development of gross motor skills.</p>
|
||||||
|
<p>Thanks to a wide range of colors and varied sizes, it is possible to compose a set for exercises necessary in every physiotherapy office, massage salon, as well as in schools and kindergartens.</p>
|
||||||
|
<p>The rehabilitation roller is a medical device in accordance with the essential requirements for medical devices and within the meaning of the Medical Devices Act, registered in the Register of Medical Devices maintained by the Office for Registration of Medicinal Products, Medical Devices, and Biocidal Products, equipped with the manufacturer's declaration of conformity and marked with the CE mark.</p>
|
||||||
|
<p></p>
|
||||||
|
<p><img alt="Medical device"></img></p>
|
||||||
|
<h4><strong>Recommended use:</strong></h4>
|
||||||
|
<ul>
|
||||||
|
<li>in rehabilitation</li>
|
||||||
|
<li>during massages (traditional, sports)</li>
|
||||||
|
<li>in corrective gymnastics (especially for children)</li>
|
||||||
|
<li>for alleviating injuries of specific parts of the body</li>
|
||||||
|
<li>for support: knees, ankles, patient's head</li>
|
||||||
|
<li>in exercises developing children's motor skills</li>
|
||||||
|
<li>in beauty salons</li>
|
||||||
|
<li>in children's playrooms</li>
|
||||||
|
</ul>
|
||||||
|
<p></p>
|
||||||
|
<h4><strong>Material specification:</strong></h4>
|
||||||
|
<p><strong>Cover:</strong> material with a PVC coating intended for medical devices, making it very easy to clean and disinfect:</p>
|
||||||
|
<ul>
|
||||||
|
<li>material compliant with the REACH regulation, certified with the STANDARD 100 by OEKO-TEX ® certificate</li>
|
||||||
|
<li>phthalate-free</li>
|
||||||
|
<li>fire-resistant</li>
|
||||||
|
<li>resistant to bodily fluids (blood, urine, sweat) and alcohol</li>
|
||||||
|
<li>UV-resistant, therefore suitable for outdoor use</li>
|
||||||
|
<li>scratch-resistant</li>
|
||||||
|
<li>oil-resistant</li>
|
||||||
|
</ul>
|
||||||
|
<p><img alt="REACH"></img><img alt="Oeko Tex Standard 100 Certificate"></img><img alt="Phthalate-Free"></img><img alt="Fire-Resistant"></img><img alt="Alcohol-Resistant"></img><img alt="UV-Resistant"></img><img alt="Suitable for Outdoor Use"></img><img alt="Scratch-Resistant"></img><img alt="Oil-Resistant"></img></p>
|
||||||
|
<p><strong>Filling:</strong> medium-hard polyurethane foam with enhanced resistance to deformation:</p>
|
||||||
|
<ul>
|
||||||
|
<li>has a HYGIENIC CERTIFICATE issued by the Institute of Maritime and Tropical Medicine in Gdynia</li>
|
||||||
|
<li>has the STANDARD 100 by OEKO-TEX ® certificate – product class I, issued by the Textile Research Institute in Łódź</li>
|
||||||
|
<li>produced from high-quality raw materials that do not deplete the ozone layer</li>
|
||||||
|
</ul>
|
||||||
|
<p><img alt="Oeko Tex Standard 100 Certificate"></img><img alt="Hygienic Certificate"></img><img alt="Hygienic Certificate"></img></p>
|
||||||
|
<p></p>
|
||||||
|
<p></p></translation_of_product_description>
|
||||||
|
|
||||||
|
<translation_of_product_short_description><p>Rehabilitation rollers find their use in various types of exercises. They are used in movement rehabilitation, during corrective gymnastics, traditional and sports massages, as they are ideal for lifting and separating limbs. They can also be used to support the knees, feet, arms, and shoulders of the patient. Rehabilitation rollers are also recommended for children; using them during play significantly supports the development of gross motor skills. The product is certified as a medical device.</p></translation_of_product_short_description>
|
||||||
|
|
||||||
|
<translation_of_product_meta_description></translation_of_product_meta_description>
|
||||||
|
|
||||||
|
<translation_of_product_meta_title></translation_of_product_meta_title>
|
||||||
|
|
||||||
|
<translation_of_product_name>Rehabilitation Roller 10 x 30 cm</translation_of_product_name>
|
||||||
|
|
||||||
|
<translation_of_product_available_now>available</translation_of_product_available_now>
|
||||||
|
|
||||||
|
<translation_of_product_available_later>on order</translation_of_product_available_later>
|
||||||
|
|
||||||
|
<translation_of_product_usage><p>I. Cleaning and maintenance</p>
|
||||||
|
<p>The upholstery should be cleaned superficially using permitted agents:</p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><span><b>Type of dirt</b></span></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span><span><b>Permitted agents</b></span></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span><span><b>Procedure</b></span></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Everyday dirt<o:p></o:p></span></b></span></p>
|
||||||
|
<p><span> </span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Mild detergent, preferably gray soap solution<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Clean regularly using a sponge or soft brush. Finally, wipe the cleaned area with a damp cloth and then dry it (to remove detergent residues).<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Local, stronger dirt<o:p></o:p></span></b></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>25% ethyl alcohol solution<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Gently wipe with a gauze tampon soaked in the solution. Finally, wipe the cleaned area with a damp cloth and then dry it (to remove detergent residues).<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Disinfection<o:p></o:p></span></b></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Widely available disinfectants containing:</span></p>
|
||||||
|
<p><span>- active chlorine – sodium dichloroisocyanurate, max concentration 10000 ppm </span></p>
|
||||||
|
<p><span>- active chlorine - chlorine dioxide in solution up to 20,000 ppm </span></p>
|
||||||
|
<p><span>- isopropyl alcohol max concentration 70 %</span> </p>
|
||||||
|
<p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Disinfect according to the recommendations of the manufacturer of the used agent.<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Before using any agent other than mild detergent, test the effect in an inconspicuous place, and perform cleaning very carefully.</span></b></span><span><o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><br></br>II. Information</p>
|
||||||
|
<p></p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><img alt=""></img></td>
|
||||||
|
<td>
|
||||||
|
<p>Shampoo using a sponge<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p> <img alt=""></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Do not wash!!! (delicate products) <o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p><img></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Do not bleach!!! (do not use bleaching agents that release free chlorine)<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p> <img alt=""></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Do not iron!!! (avoid contact with hot surfaces e.g., radiators)<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p> <img alt=""></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Do not dry clean!!!<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p></p>
|
||||||
|
<p>III. Warranty conditions</p>
|
||||||
|
<p>Warranty does not cover:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Permanent discolorations caused by contact with clothing containing active, migrating dyes (e.g., jeans, suede, etc.)</li>
|
||||||
|
<li>Marks from pens, inks, markers, etc. containing active dyes</li>
|
||||||
|
<li>Damage caused by high temperature, corrosive liquids, fire</li>
|
||||||
|
<li>Mechanical damages caused by pets and other users</li>
|
||||||
|
<li>Defects resulting from improper maintenance</li>
|
||||||
|
</ul></translation_of_product_usage>
|
||||||
@@ -5,52 +5,89 @@ import (
|
|||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/db"
|
"cloud.google.com/go/auth/credentials"
|
||||||
|
translate "cloud.google.com/go/translate/apiv3"
|
||||||
|
"cloud.google.com/go/translate/apiv3/translatepb"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/config"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/repos/productDescriptionRepo"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/service/langsService"
|
"git.ma-al.com/goc_daniel/b2b/app/service/langsService"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
"gorm.io/gorm"
|
|
||||||
|
|
||||||
"github.com/openai/openai-go/v3"
|
"github.com/openai/openai-go/v3"
|
||||||
"github.com/openai/openai-go/v3/option"
|
"github.com/openai/openai-go/v3/option"
|
||||||
"github.com/openai/openai-go/v3/responses"
|
"github.com/openai/openai-go/v3/responses"
|
||||||
|
googleopt "google.golang.org/api/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProductDescriptionService struct {
|
type ProductDescriptionService struct {
|
||||||
db *gorm.DB
|
productDescriptionRepo productDescriptionRepo.UIProductDescriptionRepo
|
||||||
client openai.Client
|
ctx context.Context
|
||||||
|
googleCli translate.TranslationClient
|
||||||
|
projectID string
|
||||||
|
openAIClient openai.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a ProductDescriptionService and authenticates against the
|
||||||
|
// Google Cloud Translation API using a service account key file.
|
||||||
|
//
|
||||||
|
// Required configuration (set in .env or environment):
|
||||||
|
//
|
||||||
|
// GOOGLE_APPLICATION_CREDENTIALS – absolute path to the service account JSON key file
|
||||||
|
// GOOGLE_CLOUD_PROJECT_ID – your Google Cloud project ID
|
||||||
|
//
|
||||||
|
// The service account must have the "Cloud Translation API User" role
|
||||||
|
// (roles/cloudtranslate.user) granted in Google Cloud IAM.
|
||||||
func New() *ProductDescriptionService {
|
func New() *ProductDescriptionService {
|
||||||
return &ProductDescriptionService{
|
ctx := context.Background()
|
||||||
db: db.Get(),
|
cfg := config.Get()
|
||||||
client: openai.NewClient(option.WithAPIKey("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"),
|
|
||||||
option.WithHTTPClient(&http.Client{Timeout: 300 * time.Second})),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We assume that any user has access to all product descriptions
|
// Read the service account key file whose path comes from config / env.
|
||||||
func (s *ProductDescriptionService) GetProductDescription(userID uint, productID uint, productShopID uint, productLangID uint) (*model.ProductDescription, error) {
|
data, err := os.ReadFile(cfg.GoogleTranslate.CredentialsFile)
|
||||||
var ProductDescription model.ProductDescription
|
|
||||||
|
|
||||||
err := s.db.
|
|
||||||
Table("ps_product_lang").
|
|
||||||
Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, productShopID, productLangID).
|
|
||||||
First(&ProductDescription).Error
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("database error: %w", err)
|
log.Fatalf("productDescriptionService: cannot read credentials file %q: %v",
|
||||||
|
cfg.GoogleTranslate.CredentialsFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ProductDescription, nil
|
// Build OAuth2 credentials scoped to the Cloud Translation API.
|
||||||
|
// The correct scope for Cloud Translation v3 is "cloud-translation".
|
||||||
|
creds, err := credentials.DetectDefault(&credentials.DetectOptions{
|
||||||
|
Scopes: []string{"https://www.googleapis.com/auth/cloud-translation"},
|
||||||
|
CredentialsJSON: data,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("productDescriptionService: cannot build Google credentials: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
googleCli, err := translate.NewTranslationClient(ctx, googleopt.WithAuthCredentials(creds))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("productDescriptionService: cannot create Translation client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
openAIClient := openai.NewClient(option.WithAPIKey("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"),
|
||||||
|
option.WithHTTPClient(&http.Client{Timeout: 300 * time.Second})) // five minutes timeout
|
||||||
|
|
||||||
|
return &ProductDescriptionService{
|
||||||
|
productDescriptionRepo: productDescriptionRepo.New(),
|
||||||
|
ctx: ctx,
|
||||||
|
openAIClient: openAIClient,
|
||||||
|
googleCli: *googleCli,
|
||||||
|
projectID: cfg.GoogleTranslate.ProjectID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ProductDescriptionService) GetProductDescription(userID uint, productID uint, productLangID uint) (*model.ProductDescription, error) {
|
||||||
|
return s.productDescriptionRepo.GetProductDescription(productID, productLangID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates relevant fields with the "updates" map
|
// Updates relevant fields with the "updates" map
|
||||||
func (s *ProductDescriptionService) SaveProductDescription(userID uint, productID uint, productShopID uint, productLangID uint, updates map[string]string) error {
|
func (s *ProductDescriptionService) SaveProductDescription(userID uint, productID uint, productLangID uint, updates map[string]string) error {
|
||||||
// only some fields can be affected
|
// only some fields can be affected
|
||||||
allowedFields := []string{"description", "description_short", "meta_description", "meta_title", "name", "available_now", "available_later", "usage"}
|
allowedFields := []string{"description", "description_short", "meta_description", "meta_title", "name", "available_now", "available_later", "usage"}
|
||||||
for key := range updates {
|
for key := range updates {
|
||||||
@@ -69,51 +106,27 @@ func (s *ProductDescriptionService) SaveProductDescription(userID uint, productI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record := model.ProductDescription{
|
err := s.productDescriptionRepo.CreateIfDoesNotExist(productID, productLangID)
|
||||||
ProductID: productID,
|
|
||||||
ShopID: productShopID,
|
|
||||||
LangID: productLangID,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := s.db.
|
|
||||||
Table("ps_product_lang").
|
|
||||||
Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, productShopID, productLangID).
|
|
||||||
FirstOrCreate(&record).Error
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("database error: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(updates) == 0 {
|
return s.productDescriptionRepo.UpdateFields(productID, productLangID, updates)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
updatesIface := make(map[string]interface{}, len(updates))
|
|
||||||
for k, v := range updates {
|
|
||||||
updatesIface[k] = v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.db.
|
// TranslateProductDescription fetches the product description for productFromLangID,
|
||||||
Table("ps_product_lang").
|
// translates every text field into productToLangID using the Google Cloud
|
||||||
Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, productShopID, productLangID).
|
// Translation API (v3 TranslateText), and returns the translated record.
|
||||||
Updates(updatesIface).Error
|
//
|
||||||
|
// The Google Cloud project must have the Cloud Translation API enabled and the
|
||||||
|
// service account must hold the "Cloud Translation API User" role.
|
||||||
|
func (s *ProductDescriptionService) TranslateProductDescription(userID uint, productID uint, productFromLangID uint, productToLangID uint, aiModel string) (*model.ProductDescription, error) {
|
||||||
|
|
||||||
|
productDescription, err := s.productDescriptionRepo.GetProductDescription(productID, productFromLangID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("database error: %w", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
productDescription.LangID = productToLangID
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates relevant fields with the "updates" map
|
|
||||||
func (s *ProductDescriptionService) TranslateProductDescription(userID uint, productID uint, productShopID uint, productFromLangID uint, productToLangID uint) (*model.ProductDescription, error) {
|
|
||||||
var ProductDescription model.ProductDescription
|
|
||||||
|
|
||||||
err := s.db.
|
|
||||||
Table("ps_product_lang").
|
|
||||||
Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, productShopID, productFromLangID).
|
|
||||||
First(&ProductDescription).Error
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("database error: %w", err)
|
|
||||||
}
|
|
||||||
ProductDescription.LangID = productToLangID
|
|
||||||
|
|
||||||
// we translate all changeable fields, and we keep the exact same HTML structure in relevant fields.
|
// we translate all changeable fields, and we keep the exact same HTML structure in relevant fields.
|
||||||
lang, err := langsService.LangSrv.GetLanguageById(productToLangID)
|
lang, err := langsService.LangSrv.GetLanguageById(productToLangID)
|
||||||
@@ -121,14 +134,14 @@ func (s *ProductDescriptionService) TranslateProductDescription(userID uint, pro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := []*string{&ProductDescription.Description,
|
fields := []*string{&productDescription.Description,
|
||||||
&ProductDescription.DescriptionShort,
|
&productDescription.DescriptionShort,
|
||||||
&ProductDescription.MetaDescription,
|
&productDescription.MetaDescription,
|
||||||
&ProductDescription.MetaTitle,
|
&productDescription.MetaTitle,
|
||||||
&ProductDescription.Name,
|
&productDescription.Name,
|
||||||
&ProductDescription.AvailableNow,
|
&productDescription.AvailableNow,
|
||||||
&ProductDescription.AvailableLater,
|
&productDescription.AvailableLater,
|
||||||
&ProductDescription.Usage,
|
&productDescription.Usage,
|
||||||
}
|
}
|
||||||
keys := []string{"translation_of_product_description",
|
keys := []string{"translation_of_product_description",
|
||||||
"translation_of_product_short_description",
|
"translation_of_product_short_description",
|
||||||
@@ -140,32 +153,139 @@ func (s *ProductDescriptionService) TranslateProductDescription(userID uint, pro
|
|||||||
"translation_of_product_usage",
|
"translation_of_product_usage",
|
||||||
}
|
}
|
||||||
|
|
||||||
request := "Translate to " + lang.ISOCode + " without changing the html structure.\n"
|
request := ""
|
||||||
|
if aiModel == "OpenAI" {
|
||||||
|
request = "Translate to " + lang.ISOCode + " without changing the html structure.\n"
|
||||||
|
}
|
||||||
for i := 0; i < len(keys); i++ {
|
for i := 0; i < len(keys); i++ {
|
||||||
request += "\n<" + keys[i] + ">"
|
request += "\n<" + keys[i] + ">"
|
||||||
request += *fields[i]
|
request += *fields[i]
|
||||||
request += "</" + keys[i] + ">\n"
|
request += "</" + keys[i] + ">\n"
|
||||||
}
|
}
|
||||||
|
if aiModel == "OpenAI" {
|
||||||
request = cleanForPrompt(request)
|
request = cleanForPrompt(request)
|
||||||
|
}
|
||||||
|
|
||||||
openai_response, _ := s.client.Responses.New(context.Background(), responses.ResponseNewParams{
|
if aiModel == "OpenAI" {
|
||||||
|
response, _ := s.openAIClient.Responses.New(context.Background(), responses.ResponseNewParams{
|
||||||
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(request)},
|
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(request)},
|
||||||
Model: openai.ChatModelGPT4_1Mini,
|
Model: openai.ChatModelGPT4_1Mini,
|
||||||
// Model: openai.ChatModelGPT4_1Nano,
|
// Model: openai.ChatModelGPT4_1Nano,
|
||||||
})
|
})
|
||||||
if openai_response.Status != "completed" {
|
if response.Status != "completed" {
|
||||||
return nil, responseErrors.ErrOpenAIResponseFail
|
return nil, responseErrors.ErrAIResponseFail
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(keys); i++ {
|
for i := 0; i < len(keys); i++ {
|
||||||
success, resolution := resolveResponse(*fields[i], openai_response.OutputText(), keys[i])
|
success, resolution := resolveResponse(*fields[i], response.OutputText(), keys[i])
|
||||||
if !success {
|
if !success {
|
||||||
return nil, responseErrors.ErrOpenAIBadOutput
|
return nil, responseErrors.ErrAIBadOutput
|
||||||
}
|
}
|
||||||
*fields[i] = resolution
|
*fields[i] = resolution
|
||||||
|
|
||||||
|
// fmt.Println(resolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ProductDescription, nil
|
} else if aiModel == "Google" {
|
||||||
|
// TranslateText is the standard Cloud Translation v3 endpoint.
|
||||||
|
req := &translatepb.TranslateTextRequest{
|
||||||
|
Parent: fmt.Sprintf("projects/%s/locations/global", s.projectID),
|
||||||
|
TargetLanguageCode: lang.ISOCode,
|
||||||
|
MimeType: "text/html",
|
||||||
|
Contents: []string{request},
|
||||||
|
}
|
||||||
|
responseGoogle, err := s.googleCli.TranslateText(s.ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TranslateText returns one Translation per input string.
|
||||||
|
if len(responseGoogle.GetTranslations()) == 0 {
|
||||||
|
return nil, responseErrors.ErrAIBadOutput
|
||||||
|
}
|
||||||
|
response := responseGoogle.GetTranslations()[0].GetTranslatedText()
|
||||||
|
|
||||||
|
for i := 0; i < len(keys); i++ {
|
||||||
|
success, match := getStringInBetween(response, "<"+keys[i]+">", "</"+keys[i]+">")
|
||||||
|
if !success || !isValidXHTML(match) {
|
||||||
|
return nil, responseErrors.ErrAIBadOutput
|
||||||
|
}
|
||||||
|
*fields[i] = match
|
||||||
|
|
||||||
|
// fmt.Println(match)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return productDescription, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanForPrompt(s string) string {
|
||||||
|
r := strings.NewReader(s)
|
||||||
|
d := xml.NewDecoder(r)
|
||||||
|
|
||||||
|
prompt := ""
|
||||||
|
|
||||||
|
// Configure the decoder for HTML; leave off strict and autoclose for XHTML
|
||||||
|
d.Strict = true
|
||||||
|
d.AutoClose = xml.HTMLAutoClose
|
||||||
|
d.Entity = xml.HTMLEntity
|
||||||
|
for {
|
||||||
|
token, err := d.Token()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := token.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
prompt += "<" + attrName(v.Name)
|
||||||
|
|
||||||
|
for _, attr := range v.Attr {
|
||||||
|
if v.Name.Local == "img" && attr.Name.Local == "alt" {
|
||||||
|
prompt += fmt.Sprintf(` %s="%s"`, attrName(attr.Name), attr.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt += ">"
|
||||||
|
case xml.EndElement:
|
||||||
|
prompt += "</" + attrName(v.Name) + ">"
|
||||||
|
case xml.CharData:
|
||||||
|
prompt += string(v)
|
||||||
|
case xml.Comment:
|
||||||
|
case xml.ProcInst:
|
||||||
|
case xml.Directive:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveResponse(original string, response string, key string) (bool, string) {
|
||||||
|
success, match := getStringInBetween(response, "<"+key+">", "</"+key+">")
|
||||||
|
if !success || !isValidXHTML(match) {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
success, resolution := rebuildFromResponse("<"+key+">"+original+"</"+key+">", "<"+key+">"+match+"</"+key+">")
|
||||||
|
if !success {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, resolution[2+len(key) : len(resolution)-3-len(key)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// getStringInBetween returns empty string if no start or end string found
|
||||||
|
func getStringInBetween(str string, start string, end string) (success bool, result string) {
|
||||||
|
s := strings.Index(str, start)
|
||||||
|
if s == -1 {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
s += len(start)
|
||||||
|
e := strings.Index(str[s:], end)
|
||||||
|
if e == -1 {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, str[s : s+e]
|
||||||
}
|
}
|
||||||
|
|
||||||
// isValidXHTML checks if the string obeys the XHTML format
|
// isValidXHTML checks if the string obeys the XHTML format
|
||||||
@@ -189,78 +309,9 @@ func isValidXHTML(s string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanForPrompt(s string) string {
|
|
||||||
r := strings.NewReader(s)
|
|
||||||
d := xml.NewDecoder(r)
|
|
||||||
|
|
||||||
prompt := ""
|
|
||||||
|
|
||||||
// Configure the decoder for HTML; leave off strict and autoclose for XHTML
|
|
||||||
d.Strict = true
|
|
||||||
d.AutoClose = xml.HTMLAutoClose
|
|
||||||
d.Entity = xml.HTMLEntity
|
|
||||||
for {
|
|
||||||
token, err := d.Token()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v := token.(type) {
|
|
||||||
case xml.StartElement:
|
|
||||||
prompt += "<" + AttrName(v.Name)
|
|
||||||
|
|
||||||
for _, attr := range v.Attr {
|
|
||||||
if v.Name.Local == "img" && attr.Name.Local == "alt" {
|
|
||||||
prompt += fmt.Sprintf(` %s="%s"`, AttrName(attr.Name), attr.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt += ">"
|
|
||||||
case xml.EndElement:
|
|
||||||
prompt += "</" + AttrName(v.Name) + ">"
|
|
||||||
case xml.CharData:
|
|
||||||
prompt += string(v)
|
|
||||||
case xml.Comment:
|
|
||||||
case xml.ProcInst:
|
|
||||||
case xml.Directive:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return prompt
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolveResponse(original string, response string, key string) (bool, string) {
|
|
||||||
success, match := GetStringInBetween(response, "<"+key+">", "</"+key+">")
|
|
||||||
if !success || !isValidXHTML(match) {
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
success, resolution := RebuildFromResponse("<"+key+">"+original+"</"+key+">", "<"+key+">"+match+"</"+key+">")
|
|
||||||
if !success {
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, resolution[2+len(key) : len(resolution)-3-len(key)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStringInBetween returns empty string if no start or end string found
|
|
||||||
func GetStringInBetween(str string, start string, end string) (success bool, result string) {
|
|
||||||
s := strings.Index(str, start)
|
|
||||||
if s == -1 {
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
s += len(start)
|
|
||||||
e := strings.Index(str[s:], end)
|
|
||||||
if e == -1 {
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, str[s : s+e]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rebuilds HTML using the original HTML as a template and the response as a source
|
// Rebuilds HTML using the original HTML as a template and the response as a source
|
||||||
// Assumes that both original and response have the exact same XML structure
|
// Assumes that both original and response have the exact same XML structure
|
||||||
func RebuildFromResponse(s_original string, s_response string) (bool, string) {
|
func rebuildFromResponse(s_original string, s_response string) (bool, string) {
|
||||||
|
|
||||||
r_original := strings.NewReader(s_original)
|
r_original := strings.NewReader(s_original)
|
||||||
d_original := xml.NewDecoder(r_original)
|
d_original := xml.NewDecoder(r_original)
|
||||||
@@ -299,17 +350,17 @@ func RebuildFromResponse(s_original string, s_response string) (bool, string) {
|
|||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
result += "<" + AttrName(v_original.Name)
|
result += "<" + attrName(v_original.Name)
|
||||||
|
|
||||||
for _, attr := range v_original.Attr {
|
for _, attr := range v_original.Attr {
|
||||||
if v_original.Name.Local != "img" || attr.Name.Local != "alt" {
|
if v_original.Name.Local != "img" || attr.Name.Local != "alt" {
|
||||||
result += fmt.Sprintf(` %s="%s"`, AttrName(attr.Name), attr.Value)
|
result += fmt.Sprintf(` %s="%s"`, attrName(attr.Name), attr.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, attr := range v_response.Attr {
|
for _, attr := range v_response.Attr {
|
||||||
if v_response.Name.Local == "img" && attr.Name.Local == "alt" {
|
if v_response.Name.Local == "img" && attr.Name.Local == "alt" {
|
||||||
result += fmt.Sprintf(` %s="%s"`, AttrName(attr.Name), attr.Value)
|
result += fmt.Sprintf(` %s="%s"`, attrName(attr.Name), attr.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result += ">"
|
result += ">"
|
||||||
@@ -331,7 +382,7 @@ func RebuildFromResponse(s_original string, s_response string) (bool, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if v_original.Name.Local != "img" {
|
if v_original.Name.Local != "img" {
|
||||||
result += "</" + AttrName(v_original.Name) + ">"
|
result += "</" + attrName(v_original.Name) + ">"
|
||||||
}
|
}
|
||||||
|
|
||||||
case xml.CharData:
|
case xml.CharData:
|
||||||
@@ -387,7 +438,7 @@ func RebuildFromResponse(s_original string, s_response string) (bool, string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AttrName(name xml.Name) string {
|
func attrName(name xml.Name) string {
|
||||||
if name.Space == "" {
|
if name.Space == "" {
|
||||||
return name.Local
|
return name.Local
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
Translate to en without changing the html structure.
|
||||||
|
|
||||||
|
<translation_of_product_description><p>Zastosowanie wałków rehabilitacyjnych w różnego rodzaju ćwiczeniach oraz zabiegach wpływa pozytywnie na łagodzenie urazów oraz zwiększa szanse na powrót pacjenta do pełnej sprawności fizycznej. Stosowane są w rehabilitacji ruchowej, podczas gimnastyki korekcyjnej, masaży tradycyjnych i sportowych, gdyż idealnie nadają się do unoszenia i separacji kończyn. Można je wykorzystać także do podpierania kolan, stóp, ramion, a także barków pacjenta. Wałki rehabilitacyjne polecane są także dla dzieci, wykorzystanie ich podczas zabawy znacznie wspiera rozwój dużej motoryki.</p>
|
||||||
|
<p>Dzięki szerokiej ofercie kolorystycznej oraz zróżnicowanym rozmiarom, możliwe jest skomponowanie zestawu do ćwiczeń niezbędnego w każdym gabinecie fizjoterapeutycznym, gabinecie masażu czy też szkole i przedszkolu. </p>
|
||||||
|
<p>Wałek rehabilitacyjny jest wyrobem medycznym zgodnie z wymaganiami zasadniczymi dla wyrobów medycznych i w rozumieniu ustawy o wyrobach medycznych, zgłoszonym do Rejestru Wyrobów Medycznych prowadzonego przez Urząd Rejestracji Produktów Leczniczych, Wyrobów Medycznych i Produktów Biobójczych, wyposażonym w deklarację zgodności producenta i opatrzonym znakiem CE.</p>
|
||||||
|
<p></p>
|
||||||
|
<p><img alt="Wyrób medyczny"></img></p>
|
||||||
|
<h4><strong>Polecane zastosowanie:</strong></h4>
|
||||||
|
<ul>
|
||||||
|
<li>w rehabilitacji</li>
|
||||||
|
<li>podczas masaży (tradycyjnych, sportowych)</li>
|
||||||
|
<li>w gimnastyce korekcyjnej (w tym zwłaszcza dzieci)</li>
|
||||||
|
<li>w łagodzeniu urazów poszczególnych części ciała</li>
|
||||||
|
<li>dla podparcia: kolan, kostek, głowy pacjenta</li>
|
||||||
|
<li>w ćwiczeniach rozwijających motorykę dzieci</li>
|
||||||
|
<li>w salonach kosmetycznych</li>
|
||||||
|
<li>w salach zabaw dla dzieci</li>
|
||||||
|
</ul>
|
||||||
|
<p></p>
|
||||||
|
<h4><strong>Specyfikacja materiału:</strong></h4>
|
||||||
|
<p><strong>Pokrowiec:</strong> materiał z powłoką PCV przeznaczony dla wyrobów medycznych, dzięki czemu jest bardzo łatwy w czyszczeniu oraz dezynfekcji:</p>
|
||||||
|
<ul>
|
||||||
|
<li>materiał zgodny z rozporządzeniem REACH, posiada atest Certyfikat STANDARD 100 by OEKO-TEX ®</li>
|
||||||
|
<li>nie zawiera ftalanów</li>
|
||||||
|
<li>ognioodporny</li>
|
||||||
|
<li>odporny na płyny fizjologiczne (krew, mocz, pot) oraz na alkohol</li>
|
||||||
|
<li>odporny na UV, przez co może być także używany na zewnątrz</li>
|
||||||
|
<li>odporny na zadrapania</li>
|
||||||
|
<li>olejoodporny</li>
|
||||||
|
</ul>
|
||||||
|
<p><img alt="REACH"></img><img alt="Certyfikat Oeko Tex Standard 100"></img><img alt="Nie zwiera ftalanów"></img><img alt="Ognioodporny"></img><img alt="Odporny na alkohol"></img><img alt="Odporny na UV"></img><img alt="Przeznaczony na zewnątrz"></img><img alt="Odporny na zadrapania"></img><img alt="Olejoodporny"></img></p>
|
||||||
|
<p><strong>Wypełnienie:</strong> średnio twarda pianka poliuretanowa o podwyższonej odporności na odkształcenia:</p>
|
||||||
|
<ul>
|
||||||
|
<li>posiada ATEST HIGIENICZNY wydany przez Instytut Medycyny Morskiej i Tropikalnej w Gdyni</li>
|
||||||
|
<li>posiada atest Certyfikat STANDARD 100 by OEKO-TEX ® – klasa produktów I wydany przez Instytut Włókiennictwa w Łodzi</li>
|
||||||
|
<li>produkowana z surowców o podwyższonej jakości, nie powodujących zubożenia warstwy ozonowej </li>
|
||||||
|
</ul>
|
||||||
|
<p><img alt="Certyfikat Oeko Tex Standard 100"></img><img alt="Atest higieniczny"></img><img alt="Atest higieniczny"></img></p>
|
||||||
|
<p></p>
|
||||||
|
<p></p></translation_of_product_description>
|
||||||
|
|
||||||
|
<translation_of_product_short_description><p>Wałki rehabilitacyjne znajdują swoje zastosowanie w różnego rodzaju ćwiczeniach. Stosowane są w rehabilitacji ruchowej, podczas gimnastyki korekcyjnej, masaży tradycyjnych i sportowych, gdyż idealnie nadają się do unoszenia i separacji kończyn. Można je wykorzystać także do podpierania kolan, stóp, ramion, a także barków pacjenta. Wałki rehabilitacyjne polecane są także dla dzieci, wykorzystanie ich podczas zabawy, znacznie wspiera rozwój dużej motoryki. Produkt posiada certyfikację jako wyrób medyczny. </p></translation_of_product_short_description>
|
||||||
|
|
||||||
|
<translation_of_product_meta_description></translation_of_product_meta_description>
|
||||||
|
|
||||||
|
<translation_of_product_meta_title></translation_of_product_meta_title>
|
||||||
|
|
||||||
|
<translation_of_product_name>Wałek rehabilitacyjny 10 x 30 cm</translation_of_product_name>
|
||||||
|
|
||||||
|
<translation_of_product_available_now>dostępny</translation_of_product_available_now>
|
||||||
|
|
||||||
|
<translation_of_product_available_later>na zamówienie</translation_of_product_available_later>
|
||||||
|
|
||||||
|
<translation_of_product_usage><p>I. Czyszczenie i konserwacja</p>
|
||||||
|
<p>Tapicerkę należy czyścić powierzchniowo stosując dozwolone środki:</p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><span><b>Rodzaj zabrudzenia</b></span></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span><span><b>Dozwolone środki</b></span></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span><span><b>Postępowanie</b></span></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Codzienne zabrudzenia<o:p></o:p></span></b></span></p>
|
||||||
|
<p><span> </span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Łagodny detergent najlepiej roztwór szarego mydła<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Czyścić regularnie z użyciem gąbki lub miękkiej szczotki. Na koniec przetrzeć czyszczone miejsce wilgotną szmatką po czym wytrzeć do sucha (w celu usunięcia pozostałości detergentu).<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Miejscowe, silniejsze zabrudzenia<o:p></o:p></span></b></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>25% roztwór alkoholu etylowego<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Delikatnie przecierać nasączonym tamponem z gazy. Na koniec przetrzeć czyszczone miejsce wilgotną szmatką po czym wytrzeć do sucha (w celu usunięcia pozostałości detergentu).<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Dezynfekcja<o:p></o:p></span></b></span></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Ogólnodostępne środki do dezynfekcji zawierające:</span></p>
|
||||||
|
<p><span>- aktywny chlor – dichloroizocyjanuran sodu, max stężenie 10000 ppm </span></p>
|
||||||
|
<p><span>- aktywny chlor - dwutlenek chloru w roztworze do 20 000 ppm </span></p>
|
||||||
|
<p><span>- alkohol izopropylowy max stężenie 70 %</span> </p>
|
||||||
|
<p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><span>Dezynfekować zgodnie z zaleceniami producenta używanego środka.<o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><span><b><span>Przed użyciem środka innego niż łagodny detergent trzeba sprawdzić efekt w niewidocznym miejscu, a samo czyszczenie wykonać bardzo ostrożnie.</span></b></span><span><o:p></o:p></span></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><br></br>II. Informacje</p>
|
||||||
|
<p></p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><img alt=""></img></td>
|
||||||
|
<td>
|
||||||
|
<p>Szamponować przy użyciu gąbki<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p> <img alt=""></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Nie prać!!! (delikatne wyroby) <o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p><img></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Nie chlorować!!! (nie stosować do bielenia związków wydzielających wolny chlor)<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p> <img alt=""></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Nie prasować!!! (nie dopuszczać do kontaktu z nagrzanymi powierzchniami np. kaloryfer)<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><o:p> <img alt=""></img></o:p></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Nie czyścić chemicznie!!!<o:p></o:p></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p></p>
|
||||||
|
<p>III. Warunki gwarancji</p>
|
||||||
|
<p>Gwarancji nie podlegają:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Trwałe przebarwienia powstałe wskutek kontaktu z odzieżą zawierającą aktywne, migrujące barwniki (np. jeans, zamsz itp.)</li>
|
||||||
|
<li>Ślady z długopisu, tuszu, mazaków itp. zawierające aktywne barwniki</li>
|
||||||
|
<li>Uszkodzenia wywołane przez wysoką temperaturę, płyny żrące, ogień</li>
|
||||||
|
<li>Uszkodzenia mechaniczne spowodowane przez zwierzęta domowe i innych użytkowników</li>
|
||||||
|
<li>Wady powstałe wskutek niewłaściwej konserwacji</li>
|
||||||
|
</ul></translation_of_product_usage>
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
<translation_of_product_description><p>The use of rehabilitation rollers in various exercises and treatments positively affects the alleviation of injuries and increases the chances of the patient returning to full physical fitness. They are used in motor rehabilitation, during corrective gymnastics, traditional and sports massages, as they are ideal for lifting and separating limbs. They can also be used to support knees, feet, arms, and the patient’s shoulders. Rehabilitation rollers are also recommended for children; using them during play greatly supports the development of gross motor skills.</p>
|
|
||||||
<p>Thanks to a wide color range and varied sizes, it is possible to compose an exercise set necessary in every physiotherapy office, massage room, as well as in schools and kindergartens.</p>
|
|
||||||
<p>The rehabilitation roller is a medical device in accordance with the essential requirements for medical devices and the understanding of the Medical Devices Act, registered in the Medical Devices Register maintained by the Office for Registration of Medicinal Products, Medical Devices and Biocidal Products, equipped with the manufacturer's declaration of conformity and marked with the CE mark.</p>
|
|
||||||
<p></p>
|
|
||||||
<p><img src="https://www.naluconcept.com/img/cms/Logotypy/images.jpg" alt="Medical device" style="margin-left:auto;margin-right:auto;" width="253" height="86" /></p>
|
|
||||||
<h4><strong>Recommended uses:</strong></h4>
|
|
||||||
<ul style="list-style-type:circle;">
|
|
||||||
<li>in rehabilitation</li>
|
|
||||||
<li>during massages (traditional, sports)</li>
|
|
||||||
<li>in corrective gymnastics (especially for children)</li>
|
|
||||||
<li>in alleviating injuries to specific parts of the body</li>
|
|
||||||
<li>for supporting: knees, ankles, the patient’s head</li>
|
|
||||||
<li>in exercises developing children’s motor skills</li>
|
|
||||||
<li>in beauty salons</li>
|
|
||||||
<li>in children’s playrooms</li>
|
|
||||||
</ul>
|
|
||||||
<p></p>
|
|
||||||
<h4><strong>Material specification:</strong></h4>
|
|
||||||
<p><strong>Cover:</strong> material with a PVC coating intended for medical devices, making it very easy to clean and disinfect:</p>
|
|
||||||
<ul style="list-style-type:circle;">
|
|
||||||
<li>material compliant with REACH regulation, certified STANDARD 100 by OEKO-TEX ®</li>
|
|
||||||
<li>phthalate-free</li>
|
|
||||||
<li>fire-resistant</li>
|
|
||||||
<li>resistant to physiological fluids (blood, urine, sweat) and alcohol</li>
|
|
||||||
<li>UV resistant, so it can also be used outdoors</li>
|
|
||||||
<li>scratch-resistant</li>
|
|
||||||
<li>oil-resistant</li>
|
|
||||||
</ul>
|
|
||||||
<p><img src="https://www.naluconcept.com/img/cms/Logotypy/reach.jpg" alt="REACH" width="115" height="115" /><img src="https://www.naluconcept.com/img/cms/Logotypy/oeko-tex.jpg" alt="OEKO-TEX Standard 100 Certificate" width="116" height="114" /><img src="https://www.naluconcept.com/img/cms/Logotypy/phthalate-free.jpg" alt="Phthalate-free" width="112" height="111" /><img src="https://www.naluconcept.com/img/cms/Logotypy/fireresistant.jpg" alt="Fire-resistant" width="114" height="113" /><img src="https://www.naluconcept.com/img/cms/Logotypy/odporny-na-alkohol.jpg" alt="Alcohol-resistant" width="114" height="114" /><img src="https://www.naluconcept.com/img/cms/Logotypy/odporny-na-uv.jpg" alt="UV-resistant" width="117" height="116" /><img src="https://www.naluconcept.com/img/cms/Logotypy/outdoor.jpg" alt="Suitable for outdoor use" width="116" height="116" /><img src="https://www.naluconcept.com/img/cms/Logotypy/odporny-na-zadrapania.jpg" alt="Scratch-resistant" width="97" height="96" /><img src="https://www.naluconcept.com/img/cms/Logotypy/olejoodporny.jpg" alt="Oil-resistant" width="99" height="98" /></p>
|
|
||||||
<p><strong>Filling:</strong> medium-hard polyurethane foam with increased resistance to deformation:</p>
|
|
||||||
<ul style="list-style-type:circle;">
|
|
||||||
<li>has a HYGIENIC CERTIFICATE issued by the Institute of Maritime and Tropical Medicine in Gdynia</li>
|
|
||||||
<li>has a STANDARD 100 by OEKO-TEX ® certificate – product class I, issued by the Textile Institute in Łódź</li>
|
|
||||||
<li>produced from high-quality raw materials that do not cause depletion of the ozone layer</li>
|
|
||||||
</ul>
|
|
||||||
<p><img src="https://www.naluconcept.com/img/cms/Logotypy/oeko-tex.jpg" alt="OEKO-TEX Standard 100 Certificate" width="95" height="95" /><img src="https://www.naluconcept.com/img/cms/Logotypy/Logo_GUMed_kolor-180x180.jpg" alt="Hygienic certificate" width="94" height="94" /><img src="https://www.naluconcept.com/img/cms/Logotypy/atest_higieniczny_kolor.jpg" alt="Hygienic certificate" width="79" height="94" /></p>
|
|
||||||
<p></p>
|
|
||||||
<p></p></translation_of_product_description>
|
|
||||||
<translation_of_product_short_description><p>Rehabilitation rollers are used in various types of exercises. They are used in motor rehabilitation, during corrective gymnastics, traditional and sports massages, as they are ideal for lifting and separating limbs. They can also be used to support knees, feet, arms, and the patient’s shoulders. Rehabilitation rollers are also recommended for children; using them during play significantly supports the development of gross motor skills. The product is certified as a medical device.</p></translation_of_product_short_description>
|
|
||||||
<translation_of_product_meta_description></translation_of_product_meta_description>
|
|
||||||
<translation_of_product_meta_title></translation_of_product_meta_title>
|
|
||||||
<translation_of_product_name>Rehabilitation roller 10 x 30 cm</translation_of_product_name>
|
|
||||||
<translation_of_display_text_available_now>available</translation_of_display_text_available_now>
|
|
||||||
<translation_of_display_text_available_later>on order</translation_of_display_text_available_later>
|
|
||||||
<translation_of_product_usage><p>I. Cleaning and maintenance</p>
|
|
||||||
<p>The upholstery should be cleaned superficially using permitted agents:</p>
|
|
||||||
<table class="MsoNormalTable" style="margin-left: -5.4pt; border-collapse: collapse; mso-table-layout-alt: fixed; border: none; mso-border-alt: solid #1F3864 .5pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid #1F3864; mso-border-insideh-themecolor: accent5; mso-border-insideh-themeshade: 128; mso-border-insidev: .5pt solid #1F3864; mso-border-insidev-themecolor: accent5; mso-border-insidev-themeshade: 128;" width="764" cellspacing="0" cellpadding="0" border="1">
|
|
||||||
<tbody>
|
|
||||||
<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; height: 36.5pt;">
|
|
||||||
<td style="width: 111.5pt; border: solid #1F3864 1.0pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.5pt;" width="186" valign="top">
|
|
||||||
<p class="Default"><span color="#002e59" face="Verdana, sans-serif" style="color: #002e59; font-family: Verdana, sans-serif;"><span style="font-size: 11.3333px;"><b>Type of dirt</b></span></span></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 155.4pt; border: solid #1F3864 1.0pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; border-left: none; mso-border-left-alt: solid #1F3864 .5pt; mso-border-left-themecolor: accent5; mso-border-left-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.5pt;" width="259" valign="top">
|
|
||||||
<p class="Default"><span color="#002e59" face="Verdana, sans-serif" style="color: #002e59; font-family: Verdana, sans-serif;"><span style="font-size: 11.3333px;"><b>Permitted agents</b></span></span></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 191.35pt; border: solid #1F3864 1.0pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; border-left: none; mso-border-left-alt: solid #1F3864 .5pt; mso-border-left-themecolor: accent5; mso-border-left-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.5pt;" width="319" valign="top">
|
|
||||||
<p class="Default"><span color="#002e59" face="Verdana, sans-serif" style="color: #002e59; font-family: Verdana, sans-serif;"><span style="font-size: 11.3333px;"><b>Procedure</b></span></span></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr style="mso-yfti-irow: 1; height: 36.5pt;">
|
|
||||||
<td style="width: 111.5pt; border: solid #1F3864 1.0pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; border-top: none; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.5pt;" width="186" valign="top">
|
|
||||||
<p class="Default"><span style="color: #002e59;"><b><span style="font-size: 8.5pt; font-family: Verdana, sans-serif;">Everyday dirt<o:p></o:p></span></b></span></p>
|
|
||||||
<p class="Default"><span style="font-size: 8.5pt; font-family: Verdana, sans-serif; color: #002e59;"> </span></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 155.4pt; border-top: none; border-left: none; border-bottom: solid #1F3864 1.0pt; mso-border-bottom-themecolor: accent5; mso-border-bottom-themeshade: 128; border-right: solid #1F3864 1.0pt; mso-border-right-themecolor: accent5; mso-border-right-themeshade: 128; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-left-alt: solid #1F3864 .5pt; mso-border-left-themecolor: accent5; mso-border-left-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.5pt;" width="259" valign="top">
|
|
||||||
<p class="Default"><span style="font-size: 8.5pt; font-family: Verdana, sans-serif; color: #002e59;">Mild detergent, preferably a solution of gray soap<o:p></o:p></span></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 191.35pt; border-top: none; border-left: none; border-bottom: solid #1F3864 1.0pt; mso-border-bottom-themecolor: accent5; mso-border-bottom-themeshade: 128; border-right: solid #1F3864 1.0pt; mso-border-right-themecolor: accent5; mso-border-right-themeshade: 128; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-left-alt: solid #1F3864 .5pt; mso-border-left-themecolor: accent5; mso-border-left-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.5pt;" width="319" valign="top">
|
|
||||||
<p class="Default"><span style="font-size: 8.5pt; font-family: Verdana, sans-serif; color: #002e59;">Clean regularly using a sponge or soft brush. Finally, wipe the cleaned area with a damp cloth and then dry it (to remove detergent residues).<o:p></o:p></span></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr style="mso-yfti-irow: 2; height: 40.65pt;">
|
|
||||||
<td style="width: 111.5pt; border: solid #1F3864 1.0pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; border-top: none; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; padding: 0cm 5.4pt 0cm 5.4pt; height: 40.65pt;" width="186" valign="top">
|
|
||||||
<p class="Default"><span style="color: #002e59;"><b><span style="font-size: 8.5pt; font-family: Verdana, sans-serif;">Local, stronger dirt<o:p></o:p></span></b></span></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 155.4pt; border-top: none; border-left: none; border-bottom: solid #1F3864 1.0pt; mso-border-bottom-themecolor: accent5; mso-border-bottom-themeshade: 128; border-right: solid #1F3864 1.0pt; mso-border-right-themecolor: accent5; mso-border-right-themeshade: 128; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-left-alt: solid #1F3864 .5pt; mso-border-left-themecolor: accent5; mso-border-left-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; padding: 0cm 5.4pt 0cm 5.4pt; height: 40.65pt;" width="259" valign="top">
|
|
||||||
<p class="Default"><span style="font-size: 8.5pt; font-family: Verdana, sans-serif; color: #002e59;">25% ethyl alcohol solution<o:p></o:p></span></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 191.35pt; border-top: none; border-left: none; border-bottom: solid #1F3864 1.0pt; mso-border-bottom-themecolor: accent5; mso-border-bottom-themeshade: 128; border-right: solid #1F3864 1.0pt; mso-border-right-themecolor: accent5; mso-border-right-themeshade: 128; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-left-alt: solid #1F3864 .5pt; mso-border-left-themecolor: accent5; mso-border-left-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; padding: 0cm 5.4pt 0cm 5.4pt; height: 40.65pt;" width="319" valign="top">
|
|
||||||
<p class="Default"><span style="font-size: 8.5pt; font-family: Verdana, sans-serif; color: #002e59;">Gently wipe with a gauze tampon soaked with the solution. Finally, wipe the cleaned area with a damp cloth and then dry it (to remove detergent residues).<o:p></o:p></span></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr style="mso-yfti-irow: 3; height: 36.35pt;">
|
|
||||||
<td style="width: 111.5pt; border: solid #1F3864 1.0pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; border-top: none; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.35pt;" width="186" valign="top">
|
|
||||||
<p class="Default"><span style="color: #002e59;"><b><span style="font-size: 8.5pt; font-family: Verdana, sans-serif;">Disinfection<o:p></o:p></span></b></span></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 155.4pt; border-top: none; border-left: none; border-bottom: solid #1F3864 1.0pt; mso-border-bottom-themecolor: accent5; mso-border-bottom-themeshade: 128; border-right: solid #1F3864 1.0pt; mso-border-right-themecolor: accent5; mso-border-right-themeshade: 128; mso-border-top-alt: solid #1F3864 .5pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.35pt;" width="259" valign="top">
|
|
||||||
<p class="Default"><span style="font-size: 8.5pt; font-family: Verdana, sans-serif; color: #002e59;">Commercially available disinfectants containing:</span></p>
|
|
||||||
<p class="Default"><span style="color: #002e59;">- active chlorine – sodium dichloroisocyanurate, max concentration 10000 ppm </span></p>
|
|
||||||
<p><span style="color: #002e59;">- active chlorine - chlorine dioxide in a solution up to 20000 ppm </span></p>
|
|
||||||
<p><span style="color: #002e59;">- isopropyl alcohol max concentration 70%</span> </p>
|
|
||||||
<p></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 191.35pt; border-top: none; border-left: none; border-bottom: solid #1F3864 1.0pt; mso-border-bottom-themecolor: accent5; mso-border-bottom-themeshade: 128; border-right: solid #1F3864 1.0pt; mso-border-right-themecolor: accent5; mso-border-right-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; padding: 0cm 5.4pt 0cm 5.4pt; height: 36.35pt;" width="319" valign="top">
|
|
||||||
<p class="Default"><span style="font-size: 8.5pt; font-family: Verdana, sans-serif; color: #002e59;">Disinfect according to the recommendations of the product manufacturer.<o:p></o:p></span></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr style="mso-yfti-irow: 4; mso-yfti-lastrow: yes; height: 11.05pt;">
|
|
||||||
<td colspan="3" style="width: 458.25pt; border: solid #1F3864 1.0pt; mso-border-themecolor: accent5; mso-border-themeshade: 128; border-top: none; mso-border-top-alt: solid #1F3864 .5pt; mso-border-top-themecolor: accent5; mso-border-top-themeshade: 128; mso-border-alt: solid #1F3864 .5pt; padding: 0cm 5.4pt 0cm 5.4pt; height: 11.05pt;" width="764" valign="top">
|
|
||||||
<p class="Default"><span style="color: #002e59;"><b><span style="font-size: 8.5pt; font-family: 'Verdana',sans-serif;">Before using any agent other than a mild detergent, test the effect in an inconspicuous area, and perform cleaning very carefully.</span></b></span><span style="font-size: 8.5pt; font-family: 'Verdana',sans-serif;"><o:p></o:p></span></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p><br />II. Information</p>
|
|
||||||
<p></p>
|
|
||||||
<table class="MsoTableGrid" style="width: 767px; margin-left: -7.35pt; border-collapse: collapse; border: none;" width="768" height="156" cellspacing="0" cellpadding="0" border="1">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 113.45pt; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="189" valign="top"><img src="https://www.naluconcept.com/img/cms/Konserwacja/2.jpg" alt="" width="74" height="37" /></td>
|
|
||||||
<td style="width: 347.25pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="579" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;">Shampoo using a sponge<o:p></o:p></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 113.45pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="189" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;"><o:p> <img src="https://www.naluconcept.com/img/cms/Konserwacja/3.jpg" alt="" width="68" height="43" /></o:p></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 347.25pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="579" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;">Do not wash!!! (delicate products) <o:p></o:p></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 113.45pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="189" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: 0.0001pt; line-height: normal; text-align: left;"><o:p><img src="https://www.naluconcept.com/img/cms/Konserwacja/1.jpg" width="68" height="50" /></o:p></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 347.25pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="579" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;">Do not bleach!!! (do not use bleaching agents that release free chlorine)<o:p></o:p></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 113.45pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="189" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;"><o:p> <img src="https://www.naluconcept.com/img/cms/Konserwacja/4.jpg" alt="" width="67" height="46" /></o:p></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 347.25pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="579" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;">Do not iron!!! (avoid contact with hot surfaces such as radiators)<o:p></o:p></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width: 113.45pt; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="189" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;"><o:p> <img src="https://www.naluconcept.com/img/cms/Konserwacja/5.jpg" alt="" width="63" height="50" /></o:p></p>
|
|
||||||
</td>
|
|
||||||
<td style="width: 347.25pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt;" width="579" valign="top">
|
|
||||||
<p class="MsoNormal" style="margin-bottom: .0001pt; line-height: normal;">Do not dry clean!!!<o:p></o:p></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p></p>
|
|
||||||
<p>III. Warranty conditions</p>
|
|
||||||
<p>The warranty does not cover:</p>
|
|
||||||
<ul style="list-style-type: circle;">
|
|
||||||
<li>Permanent discoloration caused by contact with clothing containing active, migrating dyes (e.g., jeans, suede, etc.)</li>
|
|
||||||
<li>Marks from pens, ink, markers, etc., containing active dyes</li>
|
|
||||||
<li>Damage caused by high temperature, corrosive liquids, fire</li>
|
|
||||||
<li>Mechanical damage caused by pets and other users</li>
|
|
||||||
<li>Defects caused by improper maintenance</li>
|
|
||||||
</ul></translation_of_product_usage>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1001
|
|
||||||
package emails
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/templ/layout"
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/view"
|
|
||||||
)
|
|
||||||
|
|
||||||
func EmailAdminNotificationWrapper(data view.EmailLayout[view.EmailAdminNotificationData]) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"container\"><div class=\"email-wrapper\"><div class=\"email-header\"><h1>New User Registration</h1></div><div class=\"email-body\"><p>Hello Administrator,</p><p>A new user has completed their registration and requires repository access.</p><div class=\"info-box\"><strong>User Details:</strong><p><strong>Name:</strong> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.Data.UserName)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailAdminNotification.templ`, Line: 21, Col: 70}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</p><p><strong>Email:</strong> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.Data.UserEmail)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailAdminNotification.templ`, Line: 22, Col: 72}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p></div><p>Please assign the appropriate repositories to this user in the admin panel.</p><div style=\"text-align: center;\"><a href=\"{ data.Data.BaseURL }/admin/users\" class=\"button\">Go to Admin Panel</a></div></div><div class=\"email-footer\"><p>© 2024 Gitea Manager. All rights reserved.</p></div></div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
templ_7745c5c3_Err = layout.Base(i18n.T___(data.LangID, "email.email_admin_notification_title")).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1001
|
|
||||||
package emails
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/templ/layout"
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/view"
|
|
||||||
)
|
|
||||||
|
|
||||||
func EmailPasswordResetWrapper(data view.EmailLayout[view.EmailPasswordResetData]) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"container\"><div class=\"email-wrapper\"><div class=\"email-header\"><h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_greeting"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 14, Col: 73}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1></div><div class=\"email-body\"><p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_password_reset_message1"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 17, Col: 87}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p><div style=\"text-align: center;\"><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(data.Data.ResetURL)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 19, Col: 53}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" class=\"button\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 string
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_reset_button"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 19, Col: 124}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</a></div><p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_or_copy"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 21, Col: 71}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</p><div class=\"link-container\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(data.Data.ResetURL)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 22, Col: 69}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div><div class=\"warning\"><strong>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var9 string
|
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_warning_title"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 24, Col: 86}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</strong> ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var10 string
|
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_password_reset_warning"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 24, Col: 161}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div><p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var11 string
|
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_ignore_reset"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 26, Col: 76}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</p></div><div class=\"email-footer\"><p>© 2024 Gitea Manager. ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var12 string
|
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_footer"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailPasswordReset.templ`, Line: 29, Col: 96}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</p></div></div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
templ_7745c5c3_Err = layout.Base(i18n.T___(data.LangID, "email.email_password_reset_title")).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1001
|
|
||||||
package emails
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/templ/layout"
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/view"
|
|
||||||
)
|
|
||||||
|
|
||||||
func EmailVerificationWrapper(data view.EmailLayout[view.EmailVerificationData]) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"container\"><div class=\"email-wrapper\"><div class=\"email-header\"><h1>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_verification_title"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 14, Col: 67}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1></div><div class=\"email-body\"><p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 string
|
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_greeting"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 17, Col: 56}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</p><p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_verification_message1"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 18, Col: 69}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p><div style=\"text-align: center;\"><a href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var6 templ.SafeURL
|
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(data.Data.VerificationURL)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 20, Col: 41}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" class=\"button\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var7 string
|
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_verify_button"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 20, Col: 112}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</a></div><p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_or_copy"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 22, Col: 55}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</p><div class=\"link-container\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var9 string
|
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(data.Data.VerificationURL)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 23, Col: 60}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div><p><strong>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var10 string
|
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_verification_note"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 24, Col: 73}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</strong></p><p>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var11 string
|
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_ignore"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 25, Col: 54}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</p></div><div class=\"email-footer\"><p>© 2024 Gitea Manager. ")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var12 string
|
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(i18n.T___(data.LangID, "email.email_footer"))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/emails/emailVerification.templ`, Line: 28, Col: 81}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</p></div></div></div>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
templ_7745c5c3_Err = layout.Base(i18n.T___(data.LangID, "email.email_verification_title")).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.3.1001
|
|
||||||
package layout
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
|
||||||
|
|
||||||
func Base(title string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = head(title).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body style=\"margin:0;padding:0;background:#f4f4f4;\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func head(title string) templ.Component {
|
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
|
||||||
return templ_7745c5c3_CtxErr
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
defer func() {
|
|
||||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err == nil {
|
|
||||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var2 == nil {
|
|
||||||
templ_7745c5c3_Var2 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templ/layout/base.templ`, Line: 17, Col: 16}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</title><style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n line-height: 1.6;\n color: #333333;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n }\n .container {\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n }\n .email-wrapper {\n background-color: #ffffff;\n border-radius: 8px;\n border: 2px solid #dddddd;\n overflow: hidden;\n }\n .email-header {\n background-color: #4A90E2;\n color: #ffffff;\n padding: 30px;\n text-align: center;\n }\n .email-header h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n }\n .email-body {\n padding: 30px;\n }\n .email-body p {\n margin: 0 0 16px 0;\n }\n .button {\n display: inline-block;\n background-color: #4A90E2;\n color: #ffffff;\n padding: 14px 28px;\n text-decoration: none;\n border-radius: 6px;\n font-weight: 500;\n margin: 20px 0;\n }\n .email-footer {\n background-color: #f8f8f8;\n padding: 20px 30px;\n text-align: center;\n font-size: 12px;\n color: #666666;\n }\n .link-container {\n word-break: break-all;\n font-size: 12px;\n color: #666666;\n background-color: #f8f8f8;\n padding: 10px;\n border-radius: 4px;\n margin: 10px 0;\n }\n </style></head>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = templruntime.GeneratedTemplate
|
|
||||||
@@ -2,3 +2,4 @@ package constdata
|
|||||||
|
|
||||||
// PASSWORD_VALIDATION_REGEX is used by the frontend (JavaScript supports lookaheads).
|
// PASSWORD_VALIDATION_REGEX is used by the frontend (JavaScript supports lookaheads).
|
||||||
const PASSWORD_VALIDATION_REGEX = `^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{10,}$`
|
const PASSWORD_VALIDATION_REGEX = `^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{10,}$`
|
||||||
|
const SHOP_ID = 1
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
package pagination
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Paging struct {
|
|
||||||
Page uint `json:"page_number" example:"5"`
|
|
||||||
Elements uint `json:"elements_per_page" example:"30"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Paging) Offset() int {
|
|
||||||
return int(p.Elements) * int(p.Page-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Paging) Limit() int {
|
|
||||||
return int(p.Elements)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Found[T any] struct {
|
|
||||||
Items []T `json:"items,omitempty"`
|
|
||||||
Count uint `json:"items_count" example:"56"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func Paginate[T any](paging Paging, stmt *gorm.DB) (Found[T], error) {
|
|
||||||
var items []T
|
|
||||||
var count int64
|
|
||||||
|
|
||||||
base := stmt.Session(&gorm.Session{})
|
|
||||||
|
|
||||||
countDB := stmt.Session(&gorm.Session{
|
|
||||||
NewDB: true, // critical: do NOT reuse statement
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := countDB.
|
|
||||||
Table("(?) as sub", base).
|
|
||||||
Count(&count).Error; err != nil {
|
|
||||||
return Found[T]{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err := base.
|
|
||||||
Offset(paging.Offset()).
|
|
||||||
Limit(paging.Limit()).
|
|
||||||
Find(&items).
|
|
||||||
Error
|
|
||||||
if err != nil {
|
|
||||||
return Found[T]{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return Found[T]{
|
|
||||||
Items: items,
|
|
||||||
Count: uint(count),
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
150
app/utils/query/filters/filters.go
Normal file
150
app/utils/query/filters/filters.go
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FilterFunction = func(*gorm.DB) *gorm.DB
|
||||||
|
|
||||||
|
func Where(statement string, args ...interface{}) Filter {
|
||||||
|
filt := func(db *gorm.DB) *gorm.DB {
|
||||||
|
return db.Where(statement, args...)
|
||||||
|
}
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StructToWhereScope[T any](model T) Filter {
|
||||||
|
filt := func(db *gorm.DB) *gorm.DB {
|
||||||
|
return db.Where(model)
|
||||||
|
}
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Order(field string, desc bool) Filter {
|
||||||
|
var filt FilterFunction
|
||||||
|
if desc {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Order(field + " DESC")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Order(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Filter{
|
||||||
|
category: ORDER_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WhereFromStrings(column, conditionOperator, value string) Filter {
|
||||||
|
var filt func(*gorm.DB) *gorm.DB
|
||||||
|
|
||||||
|
if strings.HasPrefix(value, "~") {
|
||||||
|
value = strings.ReplaceAll(value, "~", "")
|
||||||
|
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Where("lower("+column+`) LIKE lower(?)`, "%"+value+"%")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Filter{
|
||||||
|
category: LIKE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(value, "]") && strings.Contains(value, "[") {
|
||||||
|
period := strings.ReplaceAll(value, "[", "")
|
||||||
|
period = strings.ReplaceAll(period, "]", "")
|
||||||
|
vals := strings.Split(period, ",")
|
||||||
|
if len(vals) == 2 {
|
||||||
|
from, errA := time.Parse("2006-01-02", vals[0])
|
||||||
|
to, errB := time.Parse("2006-01-02", vals[1])
|
||||||
|
if errA == nil && errB == nil {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Where(column+` BETWEEN ? AND ?`, from.Format("2006-01-02"), to.Format("2006-01-02"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Where(column+` BETWEEN ? AND ?`, vals[0], vals[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if conditionOperator == "LIKE" {
|
||||||
|
value = fmt.Sprintf("%%%s%%", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// in future add more grouping functions
|
||||||
|
if strings.Contains(strings.ToLower(column), "count(") {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Having(column+` `+conditionOperator+` ?`, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, err := strconv.ParseInt(value, 10, 64); err == nil {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Where(column+` `+conditionOperator+` ?`, i)
|
||||||
|
}
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f, err := strconv.ParseFloat(value, 64); err == nil {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Where(column+` `+conditionOperator+` ?`, f)
|
||||||
|
}
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b, err := strconv.ParseBool(value); err == nil {
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Where(column+` `+conditionOperator+` ?`, b)
|
||||||
|
}
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filt = func(d *gorm.DB) *gorm.DB {
|
||||||
|
return d.Where(column+` `+conditionOperator+` ?`, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Filter{
|
||||||
|
category: WHERE_FILTER,
|
||||||
|
filter: filt,
|
||||||
|
}
|
||||||
|
}
|
||||||
107
app/utils/query/filters/filters_list.go
Normal file
107
app/utils/query/filters/filters_list.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package filters
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Use one of declared in the package constants to instantiate the type.
|
||||||
|
type filterCategory = string
|
||||||
|
|
||||||
|
// Enumaration of known types of filters. The assumption is that all filters
|
||||||
|
// belonging to a single category (type) can be used together at a particular
|
||||||
|
// step in the query process.
|
||||||
|
const (
|
||||||
|
// Should be safe to use at any step of longer query series to reduce the
|
||||||
|
// number of results. If it is not, choose a different filter type
|
||||||
|
WHERE_FILTER filterCategory = "where"
|
||||||
|
|
||||||
|
// An like filter
|
||||||
|
LIKE_FILTER filterCategory = "where"
|
||||||
|
|
||||||
|
// An order by clause which can be used at any final step of a complex query
|
||||||
|
// to change the order of results.
|
||||||
|
ORDER_FILTER filterCategory = "order"
|
||||||
|
// TODO: document the special case of filters on products
|
||||||
|
FEAT_VAL_PRODUCT_FILTER filterCategory = "featval_product"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Filter struct {
|
||||||
|
category filterCategory
|
||||||
|
filter func(*gorm.DB) *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFilter(category filterCategory, filter func(*gorm.DB) *gorm.DB) Filter {
|
||||||
|
return Filter{
|
||||||
|
category: category,
|
||||||
|
filter: filter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FiltersList struct {
|
||||||
|
filters []Filter
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFiltersList() FiltersList {
|
||||||
|
return FiltersList{
|
||||||
|
// we allocate some extra space beforehand to reduce the overhead of resizing
|
||||||
|
filters: make([]Filter, 0, 3),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListWithFilter(filt Filter) FiltersList {
|
||||||
|
l := NewFiltersList()
|
||||||
|
l.filters = append(l.filters, filt)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FiltersList) NewFilter(category filterCategory, filter func(*gorm.DB) *gorm.DB) {
|
||||||
|
f.filters = append(f.filters, NewFilter(category, filter))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FiltersList) Append(filter ...Filter) {
|
||||||
|
f.filters = append(f.filters, filter...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return all stored filters as []func(*gorm.DB)*gorm.DB
|
||||||
|
func (f *FiltersList) All() []func(*gorm.DB) *gorm.DB {
|
||||||
|
return lo.Map(f.filters, func(filt Filter, _ int) func(*gorm.DB) *gorm.DB {
|
||||||
|
return filt.filter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FiltersList) OfCategory(cat filterCategory) []func(*gorm.DB) *gorm.DB {
|
||||||
|
return lo.Map(lo.Filter(f.filters, func(v Filter, _ int) bool {
|
||||||
|
return v.category == cat
|
||||||
|
}), func(el Filter, _ int) func(*gorm.DB) *gorm.DB {
|
||||||
|
return el.filter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FiltersList) ApplyAll(d *gorm.DB) {
|
||||||
|
d.Scopes(f.All()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FiltersList) Apply(d *gorm.DB, cat filterCategory) {
|
||||||
|
d.Scopes(f.OfCategory(cat)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FiltersList) Merge(another FiltersList) {
|
||||||
|
f.filters = append(f.filters, another.filters...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An implementation of stringer on FiltersList that is meant rather to be used
|
||||||
|
// for debug display
|
||||||
|
func (f FiltersList) String() string {
|
||||||
|
groupMap := lo.GroupBy(f.filters, func(t Filter) string {
|
||||||
|
return t.category
|
||||||
|
})
|
||||||
|
res := "FiltersList{"
|
||||||
|
for key := range groupMap {
|
||||||
|
res += fmt.Sprintf(" \"%s\": %d filters", key, len(groupMap[key]))
|
||||||
|
}
|
||||||
|
res += " }"
|
||||||
|
return res
|
||||||
|
}
|
||||||
159
app/utils/query/find/find.go
Normal file
159
app/utils/query/find/find.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
package find
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Paging struct {
|
||||||
|
Page uint `json:"page_number" example:"5"`
|
||||||
|
Elements uint `json:"elements_per_page" example:"30"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Paging) Offset() int {
|
||||||
|
return int(p.Elements) * int(p.Page-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Paging) Limit() int {
|
||||||
|
return int(p.Elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Found[T any] struct {
|
||||||
|
Items []T `json:"items,omitempty"`
|
||||||
|
Count uint `json:"items_count" example:"56"`
|
||||||
|
Spec map[string]interface{} `json:"spec,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps given query adding limit, offset clauses and SQL_CALC_FOUND_ROWS to it
|
||||||
|
// and running SELECT FOUND_ROWS() afterwards to fetch the total number
|
||||||
|
// (ignoring LIMIT) of results. The final results are wrapped into the
|
||||||
|
// [find.Found] type.
|
||||||
|
func Paginate[T any](langID uint, paging Paging, stmt *gorm.DB) (Found[T], error) {
|
||||||
|
var items []T
|
||||||
|
var count uint64
|
||||||
|
|
||||||
|
// stmt.Debug()
|
||||||
|
|
||||||
|
err := stmt.
|
||||||
|
Clauses(SqlCalcFound()).
|
||||||
|
Offset(paging.Offset()).
|
||||||
|
Limit(paging.Limit()).
|
||||||
|
Find(&items).
|
||||||
|
Error
|
||||||
|
if err != nil {
|
||||||
|
return Found[T]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
countInterface, ok := stmt.Get(FOUND_ROWS_CTX_KEY)
|
||||||
|
if !ok {
|
||||||
|
return Found[T]{}, errors.New(FOUND_ROWS_CTX_KEY + " value was not found in the gorm db context")
|
||||||
|
}
|
||||||
|
if count, ok = countInterface.(uint64); !ok {
|
||||||
|
return Found[T]{}, errors.New("failed to cast value under " + FOUND_ROWS_CTX_KEY + " to uint64")
|
||||||
|
}
|
||||||
|
|
||||||
|
columnsSpec := GetColumnsSpec[T](langID)
|
||||||
|
|
||||||
|
return Found[T]{
|
||||||
|
Items: items,
|
||||||
|
Count: uint(count),
|
||||||
|
Spec: map[string]interface{}{
|
||||||
|
"columns": columnsSpec,
|
||||||
|
},
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetColumnsSpec[T any] generates a column specification map for a given struct type T.
|
||||||
|
// Each key is the JSON property name, and the value is a map containing:
|
||||||
|
// - "filter_type": suggested filter type based on field type or `filt` tag
|
||||||
|
// - To disable filtering for a field, set `filt:"none"` in the struct tag
|
||||||
|
// - "sortable": currently hardcoded to true
|
||||||
|
// - "order": order of fields as they appear
|
||||||
|
//
|
||||||
|
// Returns nil if T is not a struct.
|
||||||
|
func GetColumnsSpec[T any](langID uint) map[string]map[string]interface{} {
|
||||||
|
result := make(map[string]map[string]interface{})
|
||||||
|
typ := reflect.TypeOf((*T)(nil)).Elem()
|
||||||
|
if typ.Kind() != reflect.Struct {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
order := 1
|
||||||
|
processStructFields(langID, typ, result, &order)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
type FilterType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
FilterTypeRange FilterType = "range"
|
||||||
|
FilterTypeTimerange FilterType = "timerange"
|
||||||
|
FilterTypeLike FilterType = "like"
|
||||||
|
FilterTypeSwitch FilterType = "switch"
|
||||||
|
FilterTypeNone FilterType = "none"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isValidFilterType(ft string) bool {
|
||||||
|
switch FilterType(ft) {
|
||||||
|
case FilterTypeRange, FilterTypeTimerange, FilterTypeLike, FilterTypeSwitch:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// processStructFields recursively processes struct fields to populate the result map.
|
||||||
|
// It handles inline structs, reads `json` and `filt` tags, and determines filter types
|
||||||
|
// based on the field type when `filt` tag is absent.
|
||||||
|
// `order` is incremented for each field to track field ordering.
|
||||||
|
func processStructFields(langID uint, typ reflect.Type, result map[string]map[string]interface{}, order *int) {
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
field := typ.Field(i)
|
||||||
|
jsonTag := field.Tag.Get("json")
|
||||||
|
if jsonTag == "" || jsonTag == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
propName := strings.Split(jsonTag, ",")[0]
|
||||||
|
if propName == "" {
|
||||||
|
propName = field.Name
|
||||||
|
}
|
||||||
|
if strings.Contains(jsonTag, ",inline") && field.Type.Kind() == reflect.Struct {
|
||||||
|
processStructFields(langID, field.Type, result, order)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
filterType := field.Tag.Get("filt")
|
||||||
|
if filterType != "" {
|
||||||
|
if !isValidFilterType(filterType) {
|
||||||
|
filterType = string(FilterTypeNone)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fieldType := field.Type.String()
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(fieldType, "int"), strings.HasPrefix(fieldType, "uint"), strings.HasPrefix(fieldType, "float"), strings.HasPrefix(fieldType, "decimal.Decimal"):
|
||||||
|
filterType = string(FilterTypeRange)
|
||||||
|
case strings.Contains(fieldType, "Time"):
|
||||||
|
filterType = string(FilterTypeTimerange)
|
||||||
|
case fieldType == "string":
|
||||||
|
filterType = string(FilterTypeLike)
|
||||||
|
case fieldType == "bool":
|
||||||
|
filterType = string(FilterTypeSwitch)
|
||||||
|
default:
|
||||||
|
filterType = string(FilterTypeNone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result[propName] = map[string]interface{}{
|
||||||
|
"filter_type": filterType,
|
||||||
|
"sortable": func() bool { val, ok := field.Tag.Lookup("sortable"); return !ok || val == "true" }(),
|
||||||
|
"order": *order,
|
||||||
|
"title": i18n.T___(langID, field.Tag.Get("title")),
|
||||||
|
"display": func() bool { val, ok := field.Tag.Lookup("display"); return !ok || val == "true" }(),
|
||||||
|
"hidden": field.Tag.Get("hidden") == "true",
|
||||||
|
}
|
||||||
|
*order++
|
||||||
|
}
|
||||||
|
}
|
||||||
46
app/utils/query/find/found_rows_callback.go
Normal file
46
app/utils/query/find/found_rows_callback.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package find
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Key under which result of `SELECT FOUND_ROWS()` should be stored in the
|
||||||
|
// driver context.
|
||||||
|
FOUND_ROWS_CTX_KEY = "maal:found_rows"
|
||||||
|
// Suggested name under which [find.FoundRowsCallback] can be registered.
|
||||||
|
FOUND_ROWS_CALLBACK = "maal:found_rows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Searches query clauses for presence of `SQL_CALC_FOUND_ROWS` and runs `SELECT
|
||||||
|
// FOUND_ROWS();` right after the query containing such clause. The result is
|
||||||
|
// put in the driver context under key [find.FOUND_ROWS_CTX_KEY]. For the
|
||||||
|
// callback to work correctly it must be registered and executed before the
|
||||||
|
// `gorm:preload` callback.
|
||||||
|
func FoundRowsCallback(d *gorm.DB) {
|
||||||
|
if _, ok := d.Statement.Clauses["SELECT"].AfterNameExpression.(sqlCalcFound); ok {
|
||||||
|
var count uint64
|
||||||
|
sqlDB, err := d.DB()
|
||||||
|
if err != nil {
|
||||||
|
_ = d.AddError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res := sqlDB.QueryRowContext(d.Statement.Context, "SELECT FOUND_ROWS();")
|
||||||
|
if res == nil {
|
||||||
|
_ = d.AddError(errors.New(`fialed to issue SELECT FOUND_ROWS() query`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if res.Err() != nil {
|
||||||
|
_ = d.AddError(res.Err())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = res.Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
_ = d.AddError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.Set(FOUND_ROWS_CTX_KEY, count)
|
||||||
|
}
|
||||||
|
}
|
||||||
51
app/utils/query/find/sql_calc_rows.go
Normal file
51
app/utils/query/find/sql_calc_rows.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package find
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sqlCalcFound struct{}
|
||||||
|
|
||||||
|
// Creates a new Clause which adds `SQL_CALC_FOUND_ROWS` right after `SELECT`.
|
||||||
|
// If [find.FoundRowsCallback] is registered the presence of this clause will
|
||||||
|
// cause `FOUND_ROWS()` result to be available in the driver context.
|
||||||
|
func SqlCalcFound() sqlCalcFound {
|
||||||
|
return sqlCalcFound{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements gorm's [clause.Clause]
|
||||||
|
func (sqlCalcFound) Name() string {
|
||||||
|
return "SQL_CALC_FOUND_ROWS"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements gorm's [clause.Clause]
|
||||||
|
func (sqlCalcFound) Build(builder clause.Builder) {
|
||||||
|
_, _ = builder.WriteString("SQL_CALC_FOUND_ROWS")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements gorm's [clause.Clause]
|
||||||
|
func (sqlCalcFound) MergeClause(cl *clause.Clause) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements [gorm.StatementModifier]
|
||||||
|
func (calc sqlCalcFound) ModifyStatement(stmt *gorm.Statement) {
|
||||||
|
selectClause := stmt.Clauses["SELECT"]
|
||||||
|
if selectClause.AfterNameExpression == nil {
|
||||||
|
selectClause.AfterNameExpression = calc
|
||||||
|
} else if _, ok := selectClause.AfterNameExpression.(sqlCalcFound); !ok {
|
||||||
|
selectClause.AfterNameExpression = exprs{selectClause.AfterNameExpression, calc}
|
||||||
|
}
|
||||||
|
stmt.Clauses["SELECT"] = selectClause
|
||||||
|
}
|
||||||
|
|
||||||
|
type exprs []clause.Expression
|
||||||
|
|
||||||
|
func (exprs exprs) Build(builder clause.Builder) {
|
||||||
|
for idx, expr := range exprs {
|
||||||
|
if idx > 0 {
|
||||||
|
_ = builder.WriteByte(' ')
|
||||||
|
}
|
||||||
|
expr.Build(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
43
app/utils/query/query_params/key_mapping.go
Normal file
43
app/utils/query/query_params/key_mapping.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package query_params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
mreflect "git.ma-al.com/goc_daniel/b2b/app/utils/reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MapParamsKeyToDbColumn will attempt to map provided key into unique (prefixed
|
||||||
|
// with table) column name. It will do so using following priority of sources of
|
||||||
|
// mapping:
|
||||||
|
// 1. `formColumnMapping` argument. If the mapped values contain a dot, the part
|
||||||
|
// before the dot will be used for the table name. Otherwise the table name will
|
||||||
|
// be derived from the generic parameter `T`.
|
||||||
|
// 2. json tags of provided as generic `T` struct. The table name will be also
|
||||||
|
// derived from the generic if not provided as dot prefix.
|
||||||
|
func MapParamsKeyToDbColumn[DEFAULT_TABLE_MODEL any](key string, mapping ...map[string]string) (string, error) {
|
||||||
|
ERR := "Failed to find appropiate mapping from form field to database column for key: '%s', and default table name: '%s'"
|
||||||
|
|
||||||
|
if len(mapping) > 0 {
|
||||||
|
if field, ok := (mapping[0])[key]; ok {
|
||||||
|
return field, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var t DEFAULT_TABLE_MODEL
|
||||||
|
if table, field, ok := strings.Cut(key, "."); ok {
|
||||||
|
if column, err := mreflect.GetGormColumnFromJsonField(field, reflect.TypeOf(t)); err == nil {
|
||||||
|
return table + "." + column, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf(ERR, key, table)
|
||||||
|
} else {
|
||||||
|
table := mreflect.GetTableName[DEFAULT_TABLE_MODEL]()
|
||||||
|
if column, err := mreflect.GetGormColumnFromJsonField(key, reflect.TypeOf(t)); err == nil {
|
||||||
|
return table + "." + column, nil
|
||||||
|
} else {
|
||||||
|
return "", fmt.Errorf(ERR, key, table)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf(ERR, key, mreflect.GetTableName[DEFAULT_TABLE_MODEL]())
|
||||||
|
}
|
||||||
63
app/utils/query/query_params/params_query.go
Normal file
63
app/utils/query/query_params/params_query.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package query_params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var FunctionalQueryParams = []string{
|
||||||
|
// Used to specidy order of results
|
||||||
|
"sort",
|
||||||
|
// Used to specify page of search resulst
|
||||||
|
"p",
|
||||||
|
// Used to specify number of elements on a page
|
||||||
|
"elems",
|
||||||
|
// Used to specify allowed values of features on products
|
||||||
|
"values",
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseFilters[T any](c fiber.Ctx, formColumnMappimg ...map[string]string) (find.Paging, *filters.FiltersList, error) {
|
||||||
|
// field/column based filters
|
||||||
|
filters, err := ParseFieldFilters[T](c, formColumnMappimg...)
|
||||||
|
if err != nil {
|
||||||
|
return find.Paging{}, filters, err
|
||||||
|
}
|
||||||
|
// pagination
|
||||||
|
pageNum, pageSize := ParsePagination(c)
|
||||||
|
|
||||||
|
// ret
|
||||||
|
return find.Paging{Page: pageNum, Elements: pageSize}, filters, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse field related filters from params query. Produces where clauses and
|
||||||
|
// order rules.
|
||||||
|
func ParseFieldFilters[T any](c fiber.Ctx, formColumnMapping ...map[string]string) (*filters.FiltersList, error) {
|
||||||
|
// var model T
|
||||||
|
list := filters.NewFiltersList()
|
||||||
|
|
||||||
|
whereScopefilters := ParseWhereScopes[T](c, []string{}, formColumnMapping...)
|
||||||
|
list.Append(whereScopefilters...)
|
||||||
|
|
||||||
|
ord, err := ParseOrdering[T](c, formColumnMapping...)
|
||||||
|
if err != nil {
|
||||||
|
return &list, err
|
||||||
|
}
|
||||||
|
// addDefaultOrderingIfNeeded(&ord, model)
|
||||||
|
for i := range ord {
|
||||||
|
if err == nil {
|
||||||
|
list.Append(filters.Order(ord[i].Column, ord[i].IsDesc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add some source of defaults for pagination size here
|
||||||
|
func ParsePagination(c fiber.Ctx) (uint, uint) {
|
||||||
|
pageNum, _ := strconv.ParseInt(c.Query("p", "1"), 10, 64)
|
||||||
|
pageSize, _ := strconv.ParseInt(c.Query("elems", "30"), 10, 64)
|
||||||
|
return uint(pageNum), uint(pageSize)
|
||||||
|
}
|
||||||
82
app/utils/query/query_params/parse_sort.go
Normal file
82
app/utils/query/query_params/parse_sort.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package query_params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Ordering struct {
|
||||||
|
Column string
|
||||||
|
IsDesc bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseOrdering[T any](c fiber.Ctx, columnMapping ...map[string]string) ([]Ordering, error) {
|
||||||
|
param := c.Query("sort")
|
||||||
|
if len(param) < 1 {
|
||||||
|
return []Ordering{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := strings.Split(param, ";")
|
||||||
|
var orderings []Ordering
|
||||||
|
for _, r := range rules {
|
||||||
|
ord, err := parseOrderingRule[T](r, columnMapping...)
|
||||||
|
if err != nil {
|
||||||
|
return orderings, err
|
||||||
|
}
|
||||||
|
orderings = append(orderings, ord)
|
||||||
|
}
|
||||||
|
return orderings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseOrderingRule[T any](rule string, columnMapping ...map[string]string) (Ordering, error) {
|
||||||
|
var desc bool
|
||||||
|
if key, descStr, ok := strings.Cut(rule, ","); ok {
|
||||||
|
switch {
|
||||||
|
case strings.Compare(descStr, "desc") == 0:
|
||||||
|
desc = true
|
||||||
|
case strings.Compare(descStr, "asc") == 0:
|
||||||
|
desc = false
|
||||||
|
default:
|
||||||
|
desc = true
|
||||||
|
}
|
||||||
|
if col, err := MapParamsKeyToDbColumn[T](key, columnMapping...); err == nil {
|
||||||
|
return Ordering{
|
||||||
|
Column: col,
|
||||||
|
IsDesc: desc,
|
||||||
|
}, nil
|
||||||
|
} else {
|
||||||
|
return Ordering{}, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if col, err := MapParamsKeyToDbColumn[T](key, columnMapping...); err == nil {
|
||||||
|
return Ordering{
|
||||||
|
Column: col,
|
||||||
|
IsDesc: true,
|
||||||
|
}, nil
|
||||||
|
} else {
|
||||||
|
return Ordering{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// func addDefaultOrderingIfNeeded[T any](previousOrderings *[]Ordering, model T) {
|
||||||
|
// newOrderings := new([]Ordering)
|
||||||
|
// var t T
|
||||||
|
// if len(*previousOrderings) < 1 {
|
||||||
|
// if col, err := mreflect.GetGormColumnFromJsonField("id", reflect.TypeOf(t)); err == nil {
|
||||||
|
// *newOrderings = append(*newOrderings, Ordering{
|
||||||
|
// Column: mreflect.GetTableName[T]() + "." + col,
|
||||||
|
// IsDesc: true,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// if col, err := mreflect.GetGormColumnFromJsonField("iso_code", reflect.TypeOf(t)); err == nil {
|
||||||
|
// *newOrderings = append(*newOrderings, Ordering{
|
||||||
|
// Column: mreflect.GetTableName[T]() + "." + col,
|
||||||
|
// IsDesc: false,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// *newOrderings = append(*newOrderings, *previousOrderings...)
|
||||||
|
// *previousOrderings = *newOrderings
|
||||||
|
// }
|
||||||
|
// }
|
||||||
75
app/utils/query/query_params/where_scope_from_query.go
Normal file
75
app/utils/query/query_params/where_scope_from_query.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package query_params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseWhereScopes will attempt to create where scope query filters from url
|
||||||
|
// query params. It will map form fields to a database column name using
|
||||||
|
// `MapParamsKeyToDbColumn` function.
|
||||||
|
func ParseWhereScopes[T any](c fiber.Ctx, ignoredKeys []string, formColumnMapping ...map[string]string) []filters.Filter {
|
||||||
|
var parsedFilters []filters.Filter
|
||||||
|
//nolint
|
||||||
|
for key, value := range c.Request().URI().QueryArgs().All() {
|
||||||
|
keyStr := string(key)
|
||||||
|
valStr := string(value)
|
||||||
|
|
||||||
|
isIgnored := false
|
||||||
|
for _, ignoredKey := range ignoredKeys {
|
||||||
|
if keyStr == ignoredKey {
|
||||||
|
isIgnored = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isIgnored {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
baseKey, operator := extractOperator(keyStr)
|
||||||
|
|
||||||
|
if col, err := MapParamsKeyToDbColumn[T](baseKey, formColumnMapping...); err == nil {
|
||||||
|
if strings.HasPrefix(valStr, "~") {
|
||||||
|
parsedFilters = append(parsedFilters, filters.WhereFromStrings(col, "LIKE", valStr))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
op := resolveOperator(operator)
|
||||||
|
|
||||||
|
parsedFilters = append(parsedFilters, filters.WhereFromStrings(col, op, valStr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedFilters
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractOperator(key string) (base string, operatorSuffix string) {
|
||||||
|
suffixes := []string{"_gt", "_gte", "_lt", "_lte", "_eq", "_neq"}
|
||||||
|
for _, suf := range suffixes {
|
||||||
|
if strings.HasSuffix(key, suf) {
|
||||||
|
return strings.TrimSuffix(key, suf), suf[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return key, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveOperator(suffix string) string {
|
||||||
|
switch suffix {
|
||||||
|
case "gt":
|
||||||
|
return ">"
|
||||||
|
case "gte":
|
||||||
|
return ">="
|
||||||
|
case "lt":
|
||||||
|
return "<"
|
||||||
|
case "lte":
|
||||||
|
return "<="
|
||||||
|
case "neq":
|
||||||
|
return "!="
|
||||||
|
case "eq":
|
||||||
|
return "="
|
||||||
|
default:
|
||||||
|
return "LIKE"
|
||||||
|
}
|
||||||
|
}
|
||||||
37
app/utils/query/queryparser/queryparser.go
Normal file
37
app/utils/query/queryparser/queryparser.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package queryparser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseQuery(c fiber.Ctx) map[string]interface{} {
|
||||||
|
queryParams := map[string]interface{}{}
|
||||||
|
re := regexp.MustCompile(`\?(\w.+)$`)
|
||||||
|
xx := re.FindAllStringSubmatch(c.Request().URI().String(), -1)
|
||||||
|
|
||||||
|
if len(xx) > 0 {
|
||||||
|
if len(xx[0]) == 2 {
|
||||||
|
queryParts := strings.Split(xx[0][1], "&")
|
||||||
|
for _, q := range queryParts {
|
||||||
|
qq := strings.Split(q, "=")
|
||||||
|
if len(qq) == 2 {
|
||||||
|
if num, err := strconv.ParseInt(qq[1], 10, 64); err == nil {
|
||||||
|
queryParams[qq[0]] = num
|
||||||
|
} else if float, err := strconv.ParseFloat(qq[1], 64); err == nil {
|
||||||
|
queryParams[qq[0]] = float
|
||||||
|
} else {
|
||||||
|
queryParams[qq[0]] = qq[1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
queryParams[qq[0]] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryParams
|
||||||
|
}
|
||||||
90
app/utils/reflect/reflect.go
Normal file
90
app/utils/reflect/reflect.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package reflect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: instead of matching with string.Contains use something less error-prone
|
||||||
|
func checkIfContainsJSON(i int, t reflect.Type, name string) string {
|
||||||
|
if wholeTag, ok := t.Field(i).Tag.Lookup("json"); ok {
|
||||||
|
tags := strings.Split(wholeTag, ",")
|
||||||
|
for _, tag := range tags {
|
||||||
|
if name == strings.TrimSpace(tag) {
|
||||||
|
return db.DB.NamingStrategy.ColumnName(t.Name(), t.Field(i).Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not tail recursive but should do fine. Goes only as deep as the hierarchy of
|
||||||
|
// inlined structs.
|
||||||
|
// TODO: improve used internally checkIfContainsJSON
|
||||||
|
func GetGormColumnFromJsonField(jsonName string, t reflect.Type) (string, error) {
|
||||||
|
var res string
|
||||||
|
for i := range make([]bool, t.NumField()) {
|
||||||
|
if tag, ok := t.Field(i).Tag.Lookup("json"); ok && strings.Contains(tag, "inline") {
|
||||||
|
var err error
|
||||||
|
res, err = GetGormColumnFromJsonField(jsonName, t.Field(i).Type)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("no field of struct %q has a name %q in its json form", t.Name(), jsonName)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
res = checkIfContainsJSON(i, t, jsonName)
|
||||||
|
}
|
||||||
|
if res != "" {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("no field of struct %q has a name %q in its json form", t.Name(), jsonName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTableName[T any]() string {
|
||||||
|
var model T
|
||||||
|
typ := reflect.TypeOf(model).Name()
|
||||||
|
return db.DB.NamingStrategy.TableName(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetParamFromFieldTag[T any](object T, fieldname string, tagname string, paramname string) string {
|
||||||
|
if table, ok := reflect.TypeOf(object).FieldByName(fieldname); ok {
|
||||||
|
if t, ok := table.Tag.Lookup(tagname); ok {
|
||||||
|
if paramname == "" {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
re := regexp.MustCompile(`(?m)` + paramname + `:(\w*)`)
|
||||||
|
f := re.FindAllStringSubmatch(t, -1)
|
||||||
|
if len(re.FindAllStringSubmatch(t, -1)) > 0 {
|
||||||
|
return f[0][1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPrimaryKey[T any](item T) string {
|
||||||
|
var search func(T) string = func(item T) string {
|
||||||
|
val := reflect.ValueOf(item)
|
||||||
|
typ := reflect.TypeOf(item)
|
||||||
|
for i := 0; i < val.NumField(); i++ {
|
||||||
|
if gg, ok := typ.Field(i).Tag.Lookup("gorm"); ok {
|
||||||
|
xx := strings.Split(gg, ";")
|
||||||
|
for _, t := range xx {
|
||||||
|
if strings.HasPrefix(strings.ToLower(t), "primarykey") {
|
||||||
|
return db.DB.NamingStrategy.TableName(typ.Field(i).Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val.Field(i).Type().String() == "db.Model" {
|
||||||
|
return db.DB.NamingStrategy.TableName("ID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return search(item)
|
||||||
|
}
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
package response
|
package response
|
||||||
|
|
||||||
import "github.com/gofiber/fiber/v3"
|
|
||||||
|
|
||||||
type Response[T any] struct {
|
type Response[T any] struct {
|
||||||
Message string `json:"message,omitempty"`
|
Message string `json:"message"`
|
||||||
Items *T `json:"items,omitempty"`
|
Items *T `json:"items"`
|
||||||
Count *int `json:"count,omitempty"`
|
Count int `json:"count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Make[T any](c fiber.Ctx, status int, items *T, count *int, message string) Response[T] {
|
func Make[T any](items *T, count int, message string) Response[T] {
|
||||||
c.Status(status)
|
|
||||||
return Response[T]{
|
return Response[T]{
|
||||||
Message: message,
|
Message: message,
|
||||||
Items: items,
|
Items: items,
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ var (
|
|||||||
ErrEmailRequired = errors.New("email is required")
|
ErrEmailRequired = errors.New("email is required")
|
||||||
ErrEmailPasswordRequired = errors.New("email and password are required")
|
ErrEmailPasswordRequired = errors.New("email and password are required")
|
||||||
ErrRefreshTokenRequired = errors.New("refresh token is required")
|
ErrRefreshTokenRequired = errors.New("refresh token is required")
|
||||||
|
ErrBadLangID = errors.New("bad language id")
|
||||||
|
ErrBadCountryID = errors.New("bad country id")
|
||||||
|
|
||||||
// Typed errors for password reset
|
// Typed errors for password reset
|
||||||
ErrInvalidResetToken = errors.New("invalid reset token")
|
ErrInvalidResetToken = errors.New("invalid reset token")
|
||||||
@@ -38,11 +40,17 @@ var (
|
|||||||
ErrVerificationTokenExpired = errors.New("verification token has expired")
|
ErrVerificationTokenExpired = errors.New("verification token has expired")
|
||||||
|
|
||||||
// Typed errors for product description handler
|
// Typed errors for product description handler
|
||||||
ErrBadAttribute = errors.New("bad attribute")
|
ErrBadAttribute = errors.New("bad or missing attribute value in header")
|
||||||
ErrBadField = errors.New("this field can not be updated")
|
ErrBadField = errors.New("this field can not be updated")
|
||||||
ErrInvalidXHTML = errors.New("text is not in xhtml format")
|
ErrInvalidXHTML = errors.New("text is not in xhtml format")
|
||||||
ErrOpenAIResponseFail = errors.New("OpenAI responded with failure")
|
ErrAIResponseFail = errors.New("AI responded with failure")
|
||||||
ErrOpenAIBadOutput = errors.New("OpenAI response does not obey the format")
|
ErrAIBadOutput = errors.New("AI response does not obey the format")
|
||||||
|
|
||||||
|
// Typed errors for product list handler
|
||||||
|
ErrBadPaging = errors.New("bad or missing paging attribute value in header")
|
||||||
|
|
||||||
|
// Typed errors for menu handler
|
||||||
|
ErrNoRootFound = errors.New("no root found in categories table")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error represents an error with HTTP status code
|
// Error represents an error with HTTP status code
|
||||||
@@ -95,6 +103,10 @@ func GetErrorCode(c fiber.Ctx, err error) string {
|
|||||||
return i18n.T_(c, "error.err_token_required")
|
return i18n.T_(c, "error.err_token_required")
|
||||||
case errors.Is(err, ErrRefreshTokenRequired):
|
case errors.Is(err, ErrRefreshTokenRequired):
|
||||||
return i18n.T_(c, "error.err_refresh_token_required")
|
return i18n.T_(c, "error.err_refresh_token_required")
|
||||||
|
case errors.Is(err, ErrBadLangID):
|
||||||
|
return i18n.T_(c, "error.err_bad_lang_id")
|
||||||
|
case errors.Is(err, ErrBadCountryID):
|
||||||
|
return i18n.T_(c, "error.err_bad_country_id")
|
||||||
|
|
||||||
case errors.Is(err, ErrInvalidResetToken):
|
case errors.Is(err, ErrInvalidResetToken):
|
||||||
return i18n.T_(c, "error.err_invalid_reset_token")
|
return i18n.T_(c, "error.err_invalid_reset_token")
|
||||||
@@ -118,10 +130,16 @@ func GetErrorCode(c fiber.Ctx, err error) string {
|
|||||||
return i18n.T_(c, "error.err_bad_field")
|
return i18n.T_(c, "error.err_bad_field")
|
||||||
case errors.Is(err, ErrInvalidXHTML):
|
case errors.Is(err, ErrInvalidXHTML):
|
||||||
return i18n.T_(c, "error.err_invalid_html")
|
return i18n.T_(c, "error.err_invalid_html")
|
||||||
case errors.Is(err, ErrOpenAIResponseFail):
|
case errors.Is(err, ErrAIResponseFail):
|
||||||
return i18n.T_(c, "error.err_openai_response_fail")
|
return i18n.T_(c, "error.err_ai_response_fail")
|
||||||
case errors.Is(err, ErrOpenAIBadOutput):
|
case errors.Is(err, ErrAIBadOutput):
|
||||||
return i18n.T_(c, "error.err_openai_bad_output")
|
return i18n.T_(c, "error.err_ai_bad_output")
|
||||||
|
|
||||||
|
case errors.Is(err, ErrBadPaging):
|
||||||
|
return i18n.T_(c, "error.err_bad_paging")
|
||||||
|
|
||||||
|
case errors.Is(err, ErrNoRootFound):
|
||||||
|
return i18n.T_(c, "error.no_root_found")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return i18n.T_(c, "error.err_internal_server_error")
|
return i18n.T_(c, "error.err_internal_server_error")
|
||||||
@@ -145,6 +163,8 @@ func GetErrorStatus(err error) int {
|
|||||||
errors.Is(err, ErrEmailPasswordRequired),
|
errors.Is(err, ErrEmailPasswordRequired),
|
||||||
errors.Is(err, ErrTokenRequired),
|
errors.Is(err, ErrTokenRequired),
|
||||||
errors.Is(err, ErrRefreshTokenRequired),
|
errors.Is(err, ErrRefreshTokenRequired),
|
||||||
|
errors.Is(err, ErrBadLangID),
|
||||||
|
errors.Is(err, ErrBadCountryID),
|
||||||
errors.Is(err, ErrPasswordsDoNotMatch),
|
errors.Is(err, ErrPasswordsDoNotMatch),
|
||||||
errors.Is(err, ErrTokenPasswordRequired),
|
errors.Is(err, ErrTokenPasswordRequired),
|
||||||
errors.Is(err, ErrInvalidResetToken),
|
errors.Is(err, ErrInvalidResetToken),
|
||||||
@@ -154,12 +174,14 @@ func GetErrorStatus(err error) int {
|
|||||||
errors.Is(err, ErrInvalidPassword),
|
errors.Is(err, ErrInvalidPassword),
|
||||||
errors.Is(err, ErrBadAttribute),
|
errors.Is(err, ErrBadAttribute),
|
||||||
errors.Is(err, ErrBadField),
|
errors.Is(err, ErrBadField),
|
||||||
errors.Is(err, ErrInvalidXHTML):
|
errors.Is(err, ErrInvalidXHTML),
|
||||||
|
errors.Is(err, ErrBadPaging),
|
||||||
|
errors.Is(err, ErrNoRootFound):
|
||||||
return fiber.StatusBadRequest
|
return fiber.StatusBadRequest
|
||||||
case errors.Is(err, ErrEmailExists):
|
case errors.Is(err, ErrEmailExists):
|
||||||
return fiber.StatusConflict
|
return fiber.StatusConflict
|
||||||
case errors.Is(err, ErrOpenAIResponseFail),
|
case errors.Is(err, ErrAIResponseFail),
|
||||||
errors.Is(err, ErrOpenAIBadOutput):
|
errors.Is(err, ErrAIBadOutput):
|
||||||
return fiber.StatusServiceUnavailable
|
return fiber.StatusServiceUnavailable
|
||||||
default:
|
default:
|
||||||
return fiber.StatusInternalServerError
|
return fiber.StatusInternalServerError
|
||||||
1
assets/public/dist/assets/Card-DJGrWflS.js
vendored
1
assets/public/dist/assets/Card-DJGrWflS.js
vendored
@@ -1 +0,0 @@
|
|||||||
import{F as e,G as t,Q as n,R as r,d as i,h as a,m as o,p as s,xt as c,yt as l}from"./vue.runtime.esm-bundler-BM5WPBHd.js";import{S as u,n as d,r as f,t as p}from"./tv-uB0-NqWK.js";var m={slots:{root:`rounded-lg overflow-hidden`,header:`p-4 sm:px-6`,body:`p-4 sm:p-6`,footer:`p-4 sm:px-6`},variants:{variant:{solid:{root:`bg-inverted text-inverted`},outline:{root:`bg-default ring ring-default divide-y divide-default`},soft:{root:`bg-elevated/50 divide-y divide-default`},subtle:{root:`bg-elevated/50 ring ring-default divide-y divide-default`}}},defaultVariants:{variant:`outline`}},h={__name:`Card`,props:{as:{type:null,required:!1},variant:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(h){let g=h,_=t(),v=u(),y=d(`card`,g),b=i(()=>p({extend:p(m),...v.ui?.card||{}})({variant:g.variant}));return(t,i)=>(e(),s(l(f),{as:h.as,"data-slot":`root`,class:c(b.value.root({class:[l(y)?.root,g.class]}))},{default:n(()=>[_.header?(e(),a(`div`,{key:0,"data-slot":`header`,class:c(b.value.header({class:l(y)?.header}))},[r(t.$slots,`header`)],2)):o(``,!0),_.default?(e(),a(`div`,{key:1,"data-slot":`body`,class:c(b.value.body({class:l(y)?.body}))},[r(t.$slots,`default`)],2)):o(``,!0),_.footer?(e(),a(`div`,{key:2,"data-slot":`footer`,class:c(b.value.footer({class:l(y)?.footer}))},[r(t.$slots,`footer`)],2)):o(``,!0)]),_:3},8,[`as`,`class`]))}};export{h as t};
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{F as e,Q as t,_ as n,f as r,h as i,y as a}from"./vue.runtime.esm-bundler-BM5WPBHd.js";import{$ as o,s}from"./tv-uB0-NqWK.js";import{t as c}from"./Card-DJGrWflS.js";var l={class:`min-h-screen bg-gradient-to-br from-primary-50 via-white to-primary-100 dark:from-gray-900 dark:via-gray-800 dark:to-gray-900 py-12 px-4 sm:px-6 lg:px-8`},u={class:`max-w-4xl mx-auto`},d={class:`text-center mb-12`},f={class:`inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30`},p=a({__name:`cs_TermsAndConditionsView`,setup(a){let{t:p}=o();return(a,o)=>{let p=s,m=c;return e(),i(`div`,l,[r(`div`,u,[r(`div`,d,[r(`div`,f,[n(p,{name:`i-heroicons-document-text`,class:`w-8 h-8`})]),o[0]||=r(`h1`,{class:`text-3xl font-bold text-gray-900 dark:text-white`},`Podmínky použití`,-1),o[1]||=r(`p`,{class:`mt-2 text-sm text-gray-600 dark:text-gray-400`},`Poslední aktualizace: březen 2026`,-1)]),n(m,{class:`shadow-xl shadow-gray-200/50 dark:shadow-gray-900/50`},{footer:t(()=>[...o[2]||=[r(`div`,{class:`flex justify-center`},null,-1)]]),default:t(()=>[o[3]||=r(`div`,{class:`prose prose-sm sm:prose dark:prose-invert max-w-none space-y-6`},[r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`1. Přijetí podmínek`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Používáním aplikace TimeTracker souhlasíte a zavazujete se dodržovat podmínky a ustanovení této dohody. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`2. Popis služby`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` TimeTracker je aplikace pro sledování času, která uživatelům umožňuje sledovat pracovní hodiny, spravovat projekty a generovat reporty. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`3. Odpovědnosti uživatele`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},`Souhlasíte s:`),r(`ul`,{class:`list-disc list-inside space-y-2 text-gray-600 dark:text-gray-400 ml-4`},[r(`li`,null,`Poskytováním přesných a úplných informací`),r(`li`,null,`Udržováním bezpečnosti svého účtu`),r(`li`,null,`Nesdílením přihlašovacích údajů s ostatními`),r(`li`,null,`Používáním služby v souladu s platnými zákony`)])]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`4. Ochrana osobních údajů`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Jsme odhodláni chránit vaše soukromí. Vaše osobní údaje budou zpracovány v souladu s naší Zásadami ochrany osobních údajů a příslušnými zákony o ochraně dat. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`5. Duševní vlastnictví`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Služba TimeTracker a veškerý její obsah, včetně mimo jiné textů, grafiky, loga a softwaru, je majetkem TimeTracker a je chráněn zákony o duševním vlastnictví. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`6. Omezení odpovědnosti`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` TimeTracker neodpovídá za jakékoli nepřímé, náhodné, zvláštní, následné nebo trestné škody vzniklé v důsledku vašeho používání nebo neschopnosti používat službu. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`7. Ukončení`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Vyhrazujeme si právo ukončit nebo pozastavit váš účet kdykoli, bez předchozího upozornění, za chování, které por tyto Podmušujeínky použití nebo je škodlivé pro ostatní uživatele nebo službu. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`8. Změny podmínek`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Vyhrazujeme si právo kdykoli upravit tyto Podmínky použití. Vaše další používání TimeTracker po jakýchkoli změnách znamená přijetí nových podmínek. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`9. Kontaktní informace`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Máte-li jakékoli dotazy ohledně těchto Podmínek použití, kontaktujte nás na adrese support@timetracker.com. `)])],-1)]),_:1})])])}}});export{p as default};
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{F as e,Q as t,_ as n,f as r,h as i,y as a}from"./vue.runtime.esm-bundler-BM5WPBHd.js";import{$ as o,s}from"./tv-uB0-NqWK.js";import{t as c}from"./Card-DJGrWflS.js";var l={class:`min-h-screen bg-gradient-to-br from-primary-50 via-white to-primary-100 dark:from-gray-900 dark:via-gray-800 dark:to-gray-900 py-12 px-4 sm:px-6 lg:px-8`},u={class:`max-w-4xl mx-auto`},d={class:`text-center mb-12`},f={class:`inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30`},p=a({__name:`en_TermsAndConditionsView`,setup(a){let{t:p}=o();return(a,o)=>{let p=s,m=c;return e(),i(`div`,l,[r(`div`,u,[r(`div`,d,[r(`div`,f,[n(p,{name:`i-heroicons-document-text`,class:`w-8 h-8`})]),o[0]||=r(`h1`,{class:`text-3xl font-bold text-gray-900 dark:text-white`},`Terms and Conditions`,-1),o[1]||=r(`p`,{class:`mt-2 text-sm text-gray-600 dark:text-gray-400`},`Last updated: March 2026`,-1)]),n(m,{class:`shadow-xl shadow-gray-200/50 dark:shadow-gray-900/50`},{footer:t(()=>[...o[2]||=[r(`div`,{class:`flex justify-center`},null,-1)]]),default:t(()=>[o[3]||=r(`div`,{class:`prose prose-sm sm:prose dark:prose-invert max-w-none space-y-6`},[r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`1. Acceptance of Terms`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` By accessing and using TimeTracker, you accept and agree to be bound by the terms and provision of this agreement. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`2. Description of Service`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` TimeTracker is a time tracking application that allows users to track their working hours, manage projects, and generate reports. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`3. User Responsibilities`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},`You agree to:`),r(`ul`,{class:`list-disc list-inside space-y-2 text-gray-600 dark:text-gray-400 ml-4`},[r(`li`,null,`Provide accurate and complete information`),r(`li`,null,`Maintain the security of your account`),r(`li`,null,`Not share your login credentials with others`),r(`li`,null,`Use the service in compliance with applicable laws`)])]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`4. Privacy and Data Protection`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` We are committed to protecting your privacy. Your personal data will be processed in accordance with our Privacy Policy and applicable data protection laws. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`5. Intellectual Property`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` The TimeTracker service and all its contents, including but not limited to text, graphics, logos, and software, are the property of TimeTracker and are protected by intellectual property laws. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`6. Limitation of Liability`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` TimeTracker shall not be liable for any indirect, incidental, special, consequential, or punitive damages resulting from your use of or inability to use the service. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`7. Termination`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` We reserve the right to terminate or suspend your account at any time, without prior notice, for conduct that we believe violates these Terms and Conditions or is harmful to other users or the service. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`8. Changes to Terms`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` We reserve the right to modify these Terms and Conditions at any time. Your continued use of TimeTracker after any changes indicates your acceptance of the new terms. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`9. Contact Information`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` If you have any questions about these Terms and Conditions, please contact us at support@timetracker.com. `)])],-1)]),_:1})])])}}});export{p as default};
|
|
||||||
2
assets/public/dist/assets/index-DLyy94LM.css
vendored
2
assets/public/dist/assets/index-DLyy94LM.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{F as e,Q as t,_ as n,f as r,h as i,y as a}from"./vue.runtime.esm-bundler-BM5WPBHd.js";import{$ as o,s}from"./tv-uB0-NqWK.js";import{t as c}from"./Card-DJGrWflS.js";var l={class:`min-h-screen bg-gradient-to-br from-primary-50 via-white to-primary-100 dark:from-gray-900 dark:via-gray-800 dark:to-gray-900 py-12 px-4 sm:px-6 lg:px-8`},u={class:`max-w-4xl mx-auto`},d={class:`text-center mb-12`},f={class:`inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30`},p=a({__name:`pl_TermsAndConditionsView`,setup(a){let{t:p}=o();return(a,o)=>{let p=s,m=c;return e(),i(`div`,l,[r(`div`,u,[r(`div`,d,[r(`div`,f,[n(p,{name:`i-heroicons-document-text`,class:`w-8 h-8`})]),o[0]||=r(`h1`,{class:`text-3xl font-bold text-gray-900 dark:text-white`},`Regulamin`,-1),o[1]||=r(`p`,{class:`mt-2 text-sm text-gray-600 dark:text-gray-400`},`Ostatnia aktualizacja: marzec 2026`,-1)]),n(m,{class:`shadow-xl shadow-gray-200/50 dark:shadow-gray-900/50`},{footer:t(()=>[...o[2]||=[r(`div`,{class:`flex justify-center`},null,-1)]]),default:t(()=>[o[3]||=r(`div`,{class:`prose prose-sm sm:prose dark:prose-invert max-w-none space-y-6`},[r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`1. Akceptacja Regulaminu`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Korzystając z aplikacji TimeTracker, akceptujesz i zgadzasz się na przestrzeganie warunków i postanowień niniejszej umowy. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`2. Opis Usługi`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` TimeTracker to aplikacja do śledzenia czasu pracy, która umożliwia użytkownikom śledzenie godzin pracy, zarządzanie projektami oraz generowanie raportów. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`3. Obowiązki Użytkownika`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},`Zgadzasz się na:`),r(`ul`,{class:`list-disc list-inside space-y-2 text-gray-600 dark:text-gray-400 ml-4`},[r(`li`,null,`Podawanie dokładnych i kompletnych informacji`),r(`li`,null,`Utrzymywanie bezpieczeństwa swojego konta`),r(`li`,null,`Nieudostępnianie danych logowania innym osobom`),r(`li`,null,`Korzystanie z usługi zgodnie z obowiązującymi przepisami prawa`)])]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`4. Prywatność i Ochrona Danych`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Jesteśmy zobowiązani do ochrony Twojej prywatności. Twoje dane osobowe będą przetwarzane zgodnie z naszą Polityką Prywatności oraz obowiązującymi przepisami o ochronie danych. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`5. Własność Intelektualna`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Usługa TimeTracker oraz wszystkie jej treści, w tym między innymi teksty, grafika, logo i oprogramowanie, stanowią własność TimeTracker i są chronione przepisami o własności intelektualnej. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`6. Ograniczenie Odpowiedzialności`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` TimeTracker nie ponosi odpowiedzialności za jakiekolwiek pośrednie, przypadkowe, specjalne, następcze lub karne szkody wynikające z korzystania lub niemożności korzystania z usługi. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`7. Rozwiązanie Umowy`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` zastrzegamy sobie prawo do rozwiązania lub zawieszenia Twojego konta w dowolnym momencie, bez wcześniejszego powiadomienia, za zachowanie, które narusza niniejszy Regulamin lub jest szkodliwe dla innych użytkowników lub usługi. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`8. Zmiany w Regulaminie`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` zastrzegamy sobie prawo do modyfikacji niniejszego Regulaminu w dowolnym momencie. Dalsze korzystanie z TimeTracker po wprowadzeniu zmian oznacza akceptację nowych warunków. `)]),r(`section`,null,[r(`h2`,{class:`text-xl font-semibold text-gray-900 dark:text-white`},`9. Informacje Kontaktowe`),r(`p`,{class:`text-gray-600 dark:text-gray-400`},` Jeśli masz jakiekolwiek pytania dotyczące niniejszego Regulaminu, skontaktuj się z nami pod adresem support@timetracker.com. `)])],-1)]),_:1})])])}}});export{p as default};
|
|
||||||
3
assets/public/dist/assets/tv-uB0-NqWK.js
vendored
3
assets/public/dist/assets/tv-uB0-NqWK.js
vendored
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{b as e,d as t,ut as n}from"./vue.runtime.esm-bundler-BM5WPBHd.js";import{E as r}from"./tv-uB0-NqWK.js";function i(){let i=e(),a=n(),o=t(()=>[`#text`,`#comment`].includes(a.value?.$el.nodeName)?a.value?.$el.nextElementSibling:r(a)),s=Object.assign({},i.exposed),c={};for(let e in i.props)Object.defineProperty(c,e,{enumerable:!0,configurable:!0,get:()=>i.props[e]});if(Object.keys(s).length>0)for(let e in s)Object.defineProperty(c,e,{enumerable:!0,configurable:!0,get:()=>s[e]});Object.defineProperty(c,`$el`,{enumerable:!0,configurable:!0,get:()=>i.vnode.el}),i.exposed=c;function l(e){if(a.value=e,e&&(Object.defineProperty(c,`$el`,{enumerable:!0,configurable:!0,get:()=>e instanceof Element?e:e.$el}),!(e instanceof Element)&&!Object.prototype.hasOwnProperty.call(e,`$el`))){let t=e.$.exposed,n=Object.assign({},c);for(let e in t)Object.defineProperty(n,e,{enumerable:!0,configurable:!0,get:()=>t[e]});i.exposed=n}}return{forwardRef:l,currentRef:a,currentElement:o}}export{i as t};
|
|
||||||
File diff suppressed because one or more lines are too long
BIN
assets/public/dist/favicon.ico
vendored
BIN
assets/public/dist/favicon.ico
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
37
assets/public/dist/index.html
vendored
37
assets/public/dist/index.html
vendored
@@ -1,37 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<link rel="icon" href="/img/favicon.png">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>TimeTracker</title>
|
|
||||||
<script>
|
|
||||||
if (localStorage.getItem('vueuse-color-scheme') === 'dark' || (!('vueuse-color-scheme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
var theme = 'dark'
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
var theme = 'light'
|
|
||||||
}
|
|
||||||
var pageName = "default";
|
|
||||||
globalThis.appInit = [];
|
|
||||||
</script>
|
|
||||||
<script type="module" crossorigin src="/assets/index-DkQbBNTz.js"></script>
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/vue.runtime.esm-bundler-BM5WPBHd.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/useFetchJson-jOnQsk3s.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/tv-uB0-NqWK.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/Button-BXAyuyRY.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/useForwardExpose-CEpqU5vT.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/usePortal-BN0HgbYf.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/esm-BOSevWwL.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/settings-CuKZNbpU.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/auth-nMJSXbCC.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/Collection-Dntc3bmH.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/VisuallyHiddenInput-B1GXqDS_.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/assets/router-BBH257zw.js">
|
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-DLyy94LM.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
308
bo/bun.lock
308
bo/bun.lock
@@ -176,23 +176,23 @@
|
|||||||
|
|
||||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
|
||||||
|
|
||||||
"@eslint/config-array": ["@eslint/config-array@0.23.2", "", { "dependencies": { "@eslint/object-schema": "^3.0.2", "debug": "^4.3.1", "minimatch": "^10.2.1" } }, "sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A=="],
|
"@eslint/config-array": ["@eslint/config-array@0.23.3", "", { "dependencies": { "@eslint/object-schema": "^3.0.3", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw=="],
|
||||||
|
|
||||||
"@eslint/config-helpers": ["@eslint/config-helpers@0.5.2", "", { "dependencies": { "@eslint/core": "^1.1.0" } }, "sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ=="],
|
"@eslint/config-helpers": ["@eslint/config-helpers@0.5.3", "", { "dependencies": { "@eslint/core": "^1.1.1" } }, "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw=="],
|
||||||
|
|
||||||
"@eslint/core": ["@eslint/core@1.1.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw=="],
|
"@eslint/core": ["@eslint/core@1.1.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ=="],
|
||||||
|
|
||||||
"@eslint/object-schema": ["@eslint/object-schema@3.0.2", "", {}, "sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw=="],
|
"@eslint/object-schema": ["@eslint/object-schema@3.0.3", "", {}, "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ=="],
|
||||||
|
|
||||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.0", "", { "dependencies": { "@eslint/core": "^1.1.0", "levn": "^0.4.1" } }, "sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ=="],
|
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "levn": "^0.4.1" } }, "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ=="],
|
||||||
|
|
||||||
"@floating-ui/core": ["@floating-ui/core@1.7.4", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg=="],
|
"@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="],
|
||||||
|
|
||||||
"@floating-ui/dom": ["@floating-ui/dom@1.7.5", "", { "dependencies": { "@floating-ui/core": "^1.7.4", "@floating-ui/utils": "^0.2.10" } }, "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg=="],
|
"@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="],
|
||||||
|
|
||||||
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
|
"@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
|
||||||
|
|
||||||
"@floating-ui/vue": ["@floating-ui/vue@1.1.10", "", { "dependencies": { "@floating-ui/dom": "^1.7.5", "@floating-ui/utils": "^0.2.10", "vue-demi": ">=0.13.0" } }, "sha512-vdf8f6rHnFPPLRsmL4p12wYl+Ux4mOJOkjzKEMYVnwdf7UFdvBtHlLvQyx8iKG5vhPRbDRgZxdtpmyigDPjzYg=="],
|
"@floating-ui/vue": ["@floating-ui/vue@1.1.11", "", { "dependencies": { "@floating-ui/dom": "^1.7.6", "@floating-ui/utils": "^0.2.11", "vue-demi": ">=0.13.0" } }, "sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw=="],
|
||||||
|
|
||||||
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@
|
|||||||
|
|
||||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||||
|
|
||||||
"@iconify/collections": ["@iconify/collections@1.0.654", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-xpxyDlrndFo7z6tRyybLA8U/fzX5b+EZThqqudjbfDRknLWpjQykefbCZLFvp/XMRJCWk75JN0jFtG1Cw+Dbsw=="],
|
"@iconify/collections": ["@iconify/collections@1.0.659", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-gD9i7zfQpr3ZAv1BywaEri8o008KQT9iYaMw5EY4Y/y0qeEZB12FJMMyJGS3NvSeG80udu4kx8aZZLRsAdcANw=="],
|
||||||
|
|
||||||
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||||
|
|
||||||
@@ -210,15 +210,17 @@
|
|||||||
|
|
||||||
"@iconify/vue": ["@iconify/vue@5.0.0", "", { "dependencies": { "@iconify/types": "^2.0.0" }, "peerDependencies": { "vue": ">=3" } }, "sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg=="],
|
"@iconify/vue": ["@iconify/vue@5.0.0", "", { "dependencies": { "@iconify/types": "^2.0.0" }, "peerDependencies": { "vue": ">=3" } }, "sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg=="],
|
||||||
|
|
||||||
"@internationalized/date": ["@internationalized/date@3.11.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q=="],
|
"@internationalized/date": ["@internationalized/date@3.12.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ=="],
|
||||||
|
|
||||||
"@internationalized/number": ["@internationalized/number@3.6.5", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g=="],
|
"@internationalized/number": ["@internationalized/number@3.6.5", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g=="],
|
||||||
|
|
||||||
"@intlify/core-base": ["@intlify/core-base@11.2.8", "", { "dependencies": { "@intlify/message-compiler": "11.2.8", "@intlify/shared": "11.2.8" } }, "sha512-nBq6Y1tVkjIUsLsdOjDSJj4AsjvD0UG3zsg9Fyc+OivwlA/oMHSKooUy9tpKj0HqZ+NWFifweHavdljlBLTwdA=="],
|
"@intlify/core-base": ["@intlify/core-base@11.3.0", "", { "dependencies": { "@intlify/devtools-types": "11.3.0", "@intlify/message-compiler": "11.3.0", "@intlify/shared": "11.3.0" } }, "sha512-NNX5jIwF4TJBe7RtSKDMOA6JD9mp2mRcBHAwt2X+Q8PvnZub0yj5YYXlFu2AcESdgQpEv/5Yx2uOCV/yh7YkZg=="],
|
||||||
|
|
||||||
"@intlify/message-compiler": ["@intlify/message-compiler@11.2.8", "", { "dependencies": { "@intlify/shared": "11.2.8", "source-map-js": "^1.0.2" } }, "sha512-A5n33doOjmHsBtCN421386cG1tWp5rpOjOYPNsnpjIJbQ4POF0QY2ezhZR9kr0boKwaHjbOifvyQvHj2UTrDFQ=="],
|
"@intlify/devtools-types": ["@intlify/devtools-types@11.3.0", "", { "dependencies": { "@intlify/core-base": "11.3.0", "@intlify/shared": "11.3.0" } }, "sha512-G9CNL4WpANWVdUjubOIIS7/D2j/0j+1KJmhBJxHilWNKr9mmt3IjFV3Hq4JoBP23uOoC5ynxz/FHZ42M+YxfGw=="],
|
||||||
|
|
||||||
"@intlify/shared": ["@intlify/shared@11.2.8", "", {}, "sha512-l6e4NZyUgv8VyXXH4DbuucFOBmxLF56C/mqh2tvApbzl2Hrhi1aTDcuv5TKdxzfHYmpO3UB0Cz04fgDT9vszfw=="],
|
"@intlify/message-compiler": ["@intlify/message-compiler@11.3.0", "", { "dependencies": { "@intlify/shared": "11.3.0", "source-map-js": "^1.0.2" } }, "sha512-RAJp3TMsqohg/Wa7bVF3cChRhecSYBLrTCQSj7j0UtWVFLP+6iEJoE2zb7GU5fp+fmG5kCbUdzhmlAUCWXiUJw=="],
|
||||||
|
|
||||||
|
"@intlify/shared": ["@intlify/shared@11.3.0", "", {}, "sha512-LC6P/uay7rXL5zZ5+5iRJfLs/iUN8apu9tm8YqQVmW3Uq3X4A0dOFUIDuAmB7gAC29wTHOS3EiN/IosNSz0eNQ=="],
|
||||||
|
|
||||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
@@ -240,7 +242,7 @@
|
|||||||
|
|
||||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||||
|
|
||||||
"@nuxt/devtools-kit": ["@nuxt/devtools-kit@3.2.2", "", { "dependencies": { "@nuxt/kit": "^4.3.1", "execa": "^8.0.1" }, "peerDependencies": { "vite": ">=6.0" } }, "sha512-07E1phqoVPNlexlkrYuOMPhTzLIRjcl9iEqyc/vZLH2zWeH/T1X3v+RLTVW5Oio40f/XBp9yQuyihmX34ddjgQ=="],
|
"@nuxt/devtools-kit": ["@nuxt/devtools-kit@3.2.3", "", { "dependencies": { "@nuxt/kit": "^4.3.1", "execa": "^8.0.1" }, "peerDependencies": { "vite": ">=6.0" } }, "sha512-5zj7Xx5CDI6P84kMalXoxGLd470buF6ncsRhiEPq8UlwdpVeR7bwi8QnparZNFBdG79bZ5KUkfi5YDXpLYPoIA=="],
|
||||||
|
|
||||||
"@nuxt/fonts": ["@nuxt/fonts@0.14.0", "", { "dependencies": { "@nuxt/devtools-kit": "^3.2.1", "@nuxt/kit": "^4.2.2", "consola": "^3.4.2", "defu": "^6.1.4", "fontless": "^0.2.1", "h3": "^1.15.5", "magic-regexp": "^0.10.0", "ofetch": "^1.5.1", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unifont": "^0.7.4", "unplugin": "^3.0.0", "unstorage": "^1.17.4" } }, "sha512-4uXQl9fa5F4ibdgU8zomoOcyMdnwgdem+Pi8JEqeDYI5yPR32Kam6HnuRr47dTb97CstaepAvXPWQUUHMtjsFQ=="],
|
"@nuxt/fonts": ["@nuxt/fonts@0.14.0", "", { "dependencies": { "@nuxt/devtools-kit": "^3.2.1", "@nuxt/kit": "^4.2.2", "consola": "^3.4.2", "defu": "^6.1.4", "fontless": "^0.2.1", "h3": "^1.15.5", "magic-regexp": "^0.10.0", "ofetch": "^1.5.1", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unifont": "^0.7.4", "unplugin": "^3.0.0", "unstorage": "^1.17.4" } }, "sha512-4uXQl9fa5F4ibdgU8zomoOcyMdnwgdem+Pi8JEqeDYI5yPR32Kam6HnuRr47dTb97CstaepAvXPWQUUHMtjsFQ=="],
|
||||||
|
|
||||||
@@ -250,13 +252,13 @@
|
|||||||
|
|
||||||
"@nuxt/schema": ["@nuxt/schema@4.3.1", "", { "dependencies": { "@vue/shared": "^3.5.27", "defu": "^6.1.4", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "std-env": "^3.10.0" } }, "sha512-S+wHJdYDuyk9I43Ej27y5BeWMZgi7R/UVql3b3qtT35d0fbpXW7fUenzhLRCCDC6O10sjguc6fcMcR9sMKvV8g=="],
|
"@nuxt/schema": ["@nuxt/schema@4.3.1", "", { "dependencies": { "@vue/shared": "^3.5.27", "defu": "^6.1.4", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "std-env": "^3.10.0" } }, "sha512-S+wHJdYDuyk9I43Ej27y5BeWMZgi7R/UVql3b3qtT35d0fbpXW7fUenzhLRCCDC6O10sjguc6fcMcR9sMKvV8g=="],
|
||||||
|
|
||||||
"@nuxt/ui": ["@nuxt/ui@4.5.0", "", { "dependencies": { "@floating-ui/dom": "^1.7.5", "@iconify/vue": "^5.0.0", "@internationalized/date": "^3.11.0", "@internationalized/number": "^3.6.5", "@nuxt/fonts": "^0.14.0", "@nuxt/icon": "^2.2.1", "@nuxt/kit": "^4.3.1", "@nuxt/schema": "^4.3.1", "@nuxtjs/color-mode": "^3.5.2", "@standard-schema/spec": "^1.1.0", "@tailwindcss/postcss": "^4.2.1", "@tailwindcss/vite": "^4.2.1", "@tanstack/vue-table": "^8.21.3", "@tanstack/vue-virtual": "^3.13.18", "@tiptap/core": "^3.20.0", "@tiptap/extension-bubble-menu": "^3.20.0", "@tiptap/extension-code": "^3.20.0", "@tiptap/extension-collaboration": "^3.20.0", "@tiptap/extension-drag-handle": "^3.20.0", "@tiptap/extension-drag-handle-vue-3": "^3.20.0", "@tiptap/extension-floating-menu": "^3.20.0", "@tiptap/extension-horizontal-rule": "^3.20.0", "@tiptap/extension-image": "^3.20.0", "@tiptap/extension-mention": "^3.20.0", "@tiptap/extension-node-range": "^3.20.0", "@tiptap/extension-placeholder": "^3.20.0", "@tiptap/markdown": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/starter-kit": "^3.20.0", "@tiptap/suggestion": "^3.20.0", "@tiptap/vue-3": "^3.20.0", "@unhead/vue": "^2.1.4", "@vueuse/core": "^14.2.1", "@vueuse/integrations": "^14.2.1", "@vueuse/shared": "^14.2.1", "colortranslator": "^5.0.0", "consola": "^3.4.2", "defu": "^6.1.4", "embla-carousel-auto-height": "^8.6.0", "embla-carousel-auto-scroll": "^8.6.0", "embla-carousel-autoplay": "^8.6.0", "embla-carousel-class-names": "^8.6.0", "embla-carousel-fade": "^8.6.0", "embla-carousel-vue": "^8.6.0", "embla-carousel-wheel-gestures": "^8.1.0", "fuse.js": "^7.1.0", "hookable": "^5.5.3", "knitwork": "^1.3.0", "magic-string": "^0.30.21", "mlly": "^1.8.0", "motion-v": "^1.10.3", "ohash": "^2.0.11", "pathe": "^2.0.3", "reka-ui": "2.8.2", "scule": "^1.3.0", "tailwind-merge": "^3.5.0", "tailwind-variants": "^3.2.2", "tailwindcss": "^4.2.1", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unplugin": "^3.0.0", "unplugin-auto-import": "^21.0.0", "unplugin-vue-components": "^31.0.0", "vaul-vue": "0.4.1", "vue-component-type-helpers": "^3.2.5" }, "peerDependencies": { "@inertiajs/vue3": "^2.0.7", "@nuxt/content": "^3.0.0", "joi": "^18.0.0", "superstruct": "^2.0.0", "typescript": "^5.9.3", "valibot": "^1.0.0", "vue-router": "^4.5.0", "yup": "^1.7.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["@inertiajs/vue3", "@nuxt/content", "joi", "superstruct", "valibot", "vue-router", "yup", "zod"], "bin": { "nuxt-ui": "cli/index.mjs" } }, "sha512-aUiaeGFUaKvY6DdHSYputSqGCKthQFk2zkHDrkfMrwZPapYnS0N7Vd5fnlPoTBeMVlG+yLB5F7Knw2qcQfnTWQ=="],
|
"@nuxt/ui": ["@nuxt/ui@4.5.1", "", { "dependencies": { "@floating-ui/dom": "^1.7.5", "@iconify/vue": "^5.0.0", "@internationalized/date": "^3.11.0", "@internationalized/number": "^3.6.5", "@nuxt/fonts": "^0.14.0", "@nuxt/icon": "^2.2.1", "@nuxt/kit": "^4.3.1", "@nuxt/schema": "^4.3.1", "@nuxtjs/color-mode": "^3.5.2", "@standard-schema/spec": "^1.1.0", "@tailwindcss/postcss": "^4.2.1", "@tailwindcss/vite": "^4.2.1", "@tanstack/vue-table": "^8.21.3", "@tanstack/vue-virtual": "^3.13.19", "@tiptap/core": "^3.20.0", "@tiptap/extension-bubble-menu": "^3.20.0", "@tiptap/extension-code": "^3.20.0", "@tiptap/extension-collaboration": "^3.20.0", "@tiptap/extension-drag-handle": "^3.20.0", "@tiptap/extension-drag-handle-vue-3": "^3.20.0", "@tiptap/extension-floating-menu": "^3.20.0", "@tiptap/extension-horizontal-rule": "^3.20.0", "@tiptap/extension-image": "^3.20.0", "@tiptap/extension-mention": "^3.20.0", "@tiptap/extension-node-range": "^3.20.0", "@tiptap/extension-placeholder": "^3.20.0", "@tiptap/markdown": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/starter-kit": "^3.20.0", "@tiptap/suggestion": "^3.20.0", "@tiptap/vue-3": "^3.20.0", "@unhead/vue": "^2.1.10", "@vueuse/core": "^14.2.1", "@vueuse/integrations": "^14.2.1", "@vueuse/shared": "^14.2.1", "colortranslator": "^5.0.0", "consola": "^3.4.2", "defu": "^6.1.4", "embla-carousel-auto-height": "^8.6.0", "embla-carousel-auto-scroll": "^8.6.0", "embla-carousel-autoplay": "^8.6.0", "embla-carousel-class-names": "^8.6.0", "embla-carousel-fade": "^8.6.0", "embla-carousel-vue": "^8.6.0", "embla-carousel-wheel-gestures": "^8.1.0", "fuse.js": "^7.1.0", "hookable": "^5.5.3", "knitwork": "^1.3.0", "magic-string": "^0.30.21", "mlly": "^1.8.0", "motion-v": "^1.10.3", "ohash": "^2.0.11", "pathe": "^2.0.3", "reka-ui": "2.8.2", "scule": "^1.3.0", "tailwind-merge": "^3.5.0", "tailwind-variants": "^3.2.2", "tailwindcss": "^4.2.1", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unplugin": "^3.0.0", "unplugin-auto-import": "^21.0.0", "unplugin-vue-components": "^31.0.0", "vaul-vue": "0.4.1", "vue-component-type-helpers": "^3.2.5" }, "peerDependencies": { "@inertiajs/vue3": "^2.0.7", "@nuxt/content": "^3.0.0", "joi": "^18.0.0", "superstruct": "^2.0.0", "typescript": "^5.9.3", "valibot": "^1.0.0", "vue-router": "^4.5.0", "yup": "^1.7.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["@inertiajs/vue3", "@nuxt/content", "joi", "superstruct", "valibot", "vue-router", "yup", "zod"], "bin": { "nuxt-ui": "cli/index.mjs" } }, "sha512-5hWgreVPX6EsNCZNoOd2o7m9fTA3fwUMDw+zeYTSAjhSKtAuvkZrBtmez4MUeTv+LO1gknesgvErdIvlUnElTg=="],
|
||||||
|
|
||||||
"@nuxtjs/color-mode": ["@nuxtjs/color-mode@3.5.2", "", { "dependencies": { "@nuxt/kit": "^3.13.2", "pathe": "^1.1.2", "pkg-types": "^1.2.1", "semver": "^7.6.3" } }, "sha512-cC6RfgZh3guHBMLLjrBB2Uti5eUoGM9KyauOaYS9ETmxNWBMTvpgjvSiSJp1OFljIXPIqVTJ3xtJpSNZiO3ZaA=="],
|
"@nuxtjs/color-mode": ["@nuxtjs/color-mode@3.5.2", "", { "dependencies": { "@nuxt/kit": "^3.13.2", "pathe": "^1.1.2", "pkg-types": "^1.2.1", "semver": "^7.6.3" } }, "sha512-cC6RfgZh3guHBMLLjrBB2Uti5eUoGM9KyauOaYS9ETmxNWBMTvpgjvSiSJp1OFljIXPIqVTJ3xtJpSNZiO3ZaA=="],
|
||||||
|
|
||||||
"@oxc-project/runtime": ["@oxc-project/runtime@0.114.0", "", {}, "sha512-mVGQvr/uFJGQ3hsvgQ1sJfh79t5owyZZZtw+VaH+WhtvsmtgjT6imznB9sz2Q67Q0/4obM9mOOtQscU4aJteSg=="],
|
"@oxc-project/runtime": ["@oxc-project/runtime@0.115.0", "", {}, "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ=="],
|
||||||
|
|
||||||
"@oxc-project/types": ["@oxc-project/types@0.114.0", "", {}, "sha512-//nBfbzHQHvJs8oFIjv6coZ6uxQ4alLfiPe6D5vit6c4pmxATHHlVwgB1k+Hv4yoAMyncdxgRBF5K4BYWUCzvA=="],
|
"@oxc-project/types": ["@oxc-project/types@0.115.0", "", {}, "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw=="],
|
||||||
|
|
||||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.47.0", "", { "os": "android", "cpu": "arm" }, "sha512-UHqo3te9K/fh29brCuQdHjN+kfpIi9cnTPABuD5S9wb9ykXYRGTOOMVuSV/CK43sOhU4wwb2nT1RVjcbrrQjFw=="],
|
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.47.0", "", { "os": "android", "cpu": "arm" }, "sha512-UHqo3te9K/fh29brCuQdHjN+kfpIi9cnTPABuD5S9wb9ykXYRGTOOMVuSV/CK43sOhU4wwb2nT1RVjcbrrQjFw=="],
|
||||||
|
|
||||||
@@ -300,31 +302,35 @@
|
|||||||
|
|
||||||
"@remirror/core-constants": ["@remirror/core-constants@3.0.0", "", {}, "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg=="],
|
"@remirror/core-constants": ["@remirror/core-constants@3.0.0", "", {}, "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg=="],
|
||||||
|
|
||||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.5", "", { "os": "android", "cpu": "arm64" }, "sha512-zCEmUrt1bggwgBgeKLxNj217J1OrChrp3jJt24VK9jAharSTeVaHODNL+LpcQVhRz+FktYWfT9cjo5oZ99ZLpg=="],
|
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.8", "", { "os": "android", "cpu": "arm64" }, "sha512-5bcmMQDWEfWUq3m79Mcf/kbO6e5Jr6YjKSsA1RnpXR6k73hQ9z1B17+4h93jXpzHvS18p7bQHM1HN/fSd+9zog=="],
|
||||||
|
|
||||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ZP9xb9lPAex36pvkNWCjSEJW/Gfdm9I3ssiqOFLmpZ/vosPXgpoGxCmh+dX1Qs+/bWQE6toNFXWWL8vYoKoK9Q=="],
|
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dcHPd5N4g9w2iiPRJmAvO0fsIWzF2JPr9oSuTjxLL56qu+oML5aMbBMNwWbk58Mt3pc7vYs9CCScwLxdXPdRsg=="],
|
||||||
|
|
||||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-7IdrPunf6dp9mywMgTOKMMGDnMHQ6+h5gRl6LW8rhD8WK2kXX0IwzcM5Zc0B5J7xQs8QWOlKjv8BJsU/1CD3pg=="],
|
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-mw0VzDvoj8AuR761QwpdCFN0sc/jspuc7eRYJetpLWd+XyansUrH3C7IgNw6swBOgQT9zBHNKsVCjzpfGJlhUA=="],
|
||||||
|
|
||||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-o/JCk+dL0IN68EBhZ4DqfsfvxPfMeoM6cJtxORC1YYoxGHZyth2Kb2maXDb4oddw2wu8iIbnYXYPEzBtAF5CAg=="],
|
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xNrRa6mQ9NmMIJBdJtPMPG8Mso0OhM526pDzc/EKnRrIrrkHD1E0Z6tONZRmUeJElfsQ6h44lQQCcDilSNIvSQ=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.5", "", { "os": "linux", "cpu": "arm" }, "sha512-IIBwTtA6VwxQLcEgq2mfrUgam7VvPZjhd/jxmeS1npM+edWsrrpRLHUdze+sk4rhb8/xpP3flemgcZXXUW6ukw=="],
|
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.8", "", { "os": "linux", "cpu": "arm" }, "sha512-WgCKoO6O/rRUwimWfEJDeztwJJmuuX0N2bYLLRxmXDTtCwjToTOqk7Pashl/QpQn3H/jHjx0b5yCMbcTVYVpNg=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-KSol1De1spMZL+Xg7K5IBWXIvRWv7+pveaxFWXpezezAG7CS6ojzRjtCGCiLxQricutTAi/LkNWKMsd2wNhMKQ=="],
|
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-tOHgTOQa8G4Z3ULj4G3NYOGGJEsqPHR91dT72u63OtVsZ7B6wFJKOx+ZKv+pvwzxWz92/I2ycaqi2/Ll4l+rlg=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-WFljyDkxtXRlWxMjxeegf7xMYXxUr8u7JdXlOEWKYgDqEgxUnSEsVDxBiNWQ1D5kQKwf8Wo4sVKEYPRhCdsjwA=="],
|
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-oRbxcgDujCi2Yp1GTxoUFsIFlZsuPHU4OV4AzNc3/6aUmR4lfm9FK0uwQu82PJsuUwnF2jFdop3Ep5c1uK7Uxg=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.5", "", { "os": "linux", "cpu": "x64" }, "sha512-CUlplTujmbDWp2gamvrqVKi2Or8lmngXT1WxsizJfts7JrvfGhZObciaY/+CbdbS9qNnskvwMZNEhTPrn7b+WA=="],
|
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-oaLRyUHw8kQE5M89RqrDJZ10GdmGJcMeCo8tvaE4ukOofqgjV84AbqBSH6tTPjeT2BHv+xlKj678GBuIb47lKA=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.5", "", { "os": "linux", "cpu": "x64" }, "sha512-wdf7g9NbVZCeAo2iGhsjJb7I8ZFfs6X8bumfrWg82VK+8P6AlLXwk48a1ASiJQDTS7Svq2xVzZg3sGO2aXpHRA=="],
|
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-1hjSKFrod5MwBBdLOOA0zpUuSfSDkYIY+QqcMcIU1WOtswZtZdUkcFcZza9b2HcAb0bnpmmyo0LZcaxLb2ov1g=="],
|
||||||
|
|
||||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.5", "", { "os": "none", "cpu": "arm64" }, "sha512-0CWY7ubu12nhzz+tkpHjoG3IRSTlWYe0wrfJRf4qqjqQSGtAYgoL9kwzdvlhaFdZ5ffVeyYw9qLsChcjUMEloQ=="],
|
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.8", "", { "os": "linux", "cpu": "x64" }, "sha512-a1+F0aV4Wy9tT3o+cHl3XhOy6aFV+B8Ll+/JFj98oGkb6lGk3BNgrxd+80RwYRVd23oLGvj3LwluKYzlv1PEuw=="],
|
||||||
|
|
||||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.5", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-LztXnGzv6t2u830mnZrFLRVqT/DPJ9DL4ZTz/y93rqUVkeHjMMYIYaFj+BUthiYxbVH9dH0SZYufETspKY/NhA=="],
|
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.8", "", { "os": "linux", "cpu": "x64" }, "sha512-bGyXCFU11seFrf7z8PcHSwGEiFVkZ9vs+auLacVOQrVsI8PFHJzzJROF3P6b0ODDmXr0m6Tj5FlDhcXVk0Jp8w=="],
|
||||||
|
|
||||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-jUct1XVeGtyjqJXEAfvdFa8xoigYZ2rge7nYEm70ppQxpfH9ze2fbIrpHmP2tNM2vL/F6Dd0CpXhpjPbC6bSxQ=="],
|
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.8", "", { "os": "none", "cpu": "arm64" }, "sha512-n8d+L2bKgf9G3+AM0bhHFWdlz9vYKNim39ujRTieukdRek0RAo2TfG2uEnV9spa4r4oHUfL9IjcY3M9SlqN1gw=="],
|
||||||
|
|
||||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.5", "", { "os": "win32", "cpu": "x64" }, "sha512-VQ8F9ld5gw29epjnVGdrx8ugiLTe8BMqmhDYy7nGbdeDo4HAt4bgdZvLbViEhg7DZyHLpiEUlO5/jPSUrIuxRQ=="],
|
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.8", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-4R4iJDIk7BrJdteAbEAICXPoA7vZoY/M0OBfcRlQxzQvUYMcEp2GbC/C8UOgQJhu2TjGTpX1H8vVO1xHWcRqQA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-3lwnklba9qQOpFnQ7EW+A1m4bZTWXZE4jtehsZ0YOl2ivW1FQqp5gY7X2DLuKITggesyuLwcmqS11fA7NtrmrA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.8", "", { "os": "win32", "cpu": "x64" }, "sha512-VGjCx9Ha1P/r3tXGDZyG0Fcq7Q0Afnk64aaKzr1m40vbn1FL8R3W0V1ELDvPgzLXaaqK/9PnsqSaLWXfn6JtGQ=="],
|
||||||
|
|
||||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.2", "", {}, "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw=="],
|
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.2", "", {}, "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw=="],
|
||||||
|
|
||||||
@@ -366,85 +372,85 @@
|
|||||||
|
|
||||||
"@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="],
|
"@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="],
|
||||||
|
|
||||||
"@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.19", "", {}, "sha512-/BMP7kNhzKOd7wnDeB8NrIRNLwkf5AhCYCvtfZV2GXWbBieFm/el0n6LOAXlTi6ZwHICSNnQcIxRCWHrLzDY+g=="],
|
"@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.21", "", {}, "sha512-ww+fmLHyCbPSf7JNbWZP3g7wl6SdNo3ah5Aiw+0e9FDErkVHLKprYUrwTm7dF646FtEkN/KkAKPYezxpmvOjxw=="],
|
||||||
|
|
||||||
"@tanstack/vue-table": ["@tanstack/vue-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "vue": ">=3.2" } }, "sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw=="],
|
"@tanstack/vue-table": ["@tanstack/vue-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "vue": ">=3.2" } }, "sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw=="],
|
||||||
|
|
||||||
"@tanstack/vue-virtual": ["@tanstack/vue-virtual@3.13.19", "", { "dependencies": { "@tanstack/virtual-core": "3.13.19" }, "peerDependencies": { "vue": "^2.7.0 || ^3.0.0" } }, "sha512-07Fp1TYuIziB4zIDA/moeDKHODePy3K1fN4c4VIAGnkxo1+uOvBJP7m54CoxKiQX6Q9a1dZnznrwOg9C86yvvA=="],
|
"@tanstack/vue-virtual": ["@tanstack/vue-virtual@3.13.21", "", { "dependencies": { "@tanstack/virtual-core": "3.13.21" }, "peerDependencies": { "vue": "^2.7.0 || ^3.0.0" } }, "sha512-zneUNdQTcUhoDl6+ek+/O4S9gSZRAc2q7VLscZ4WZnFfZcHc3M7OyVCfSDC3hGuwFqzfL8Cx5bZF6zbGCYwXmw=="],
|
||||||
|
|
||||||
"@tiptap/core": ["@tiptap/core@3.20.0", "", { "peerDependencies": { "@tiptap/pm": "^3.20.0" } }, "sha512-aC9aROgia/SpJqhsXFiX9TsligL8d+oeoI8W3u00WI45s0VfsqjgeKQLDLF7Tu7hC+7F02teC84SAHuup003VQ=="],
|
"@tiptap/core": ["@tiptap/core@3.20.1", "", { "peerDependencies": { "@tiptap/pm": "^3.20.1" } }, "sha512-SwkPEWIfaDEZjC8SEIi4kZjqIYUbRgLUHUuQezo5GbphUNC8kM1pi3C3EtoOPtxXrEbY6e4pWEzW54Pcrd+rVA=="],
|
||||||
|
|
||||||
"@tiptap/extension-blockquote": ["@tiptap/extension-blockquote@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-LQzn6aGtL4WXz2+rYshl/7/VnP2qJTpD7fWL96GXAzhqviPEY1bJES7poqJb3MU/gzl8VJUVzVzU1VoVfUKlbA=="],
|
"@tiptap/extension-blockquote": ["@tiptap/extension-blockquote@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-WzNXk/63PQI2fav4Ta6P0GmYRyu8Gap1pV3VUqaVK829iJ6Zt1T21xayATHEHWMK27VT1GLPJkx9Ycr2jfDyQw=="],
|
||||||
|
|
||||||
"@tiptap/extension-bold": ["@tiptap/extension-bold@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-sQklEWiyf58yDjiHtm5vmkVjfIc/cBuSusmCsQ0q9vGYnEF1iOHKhGpvnCeEXNeqF3fiJQRlquzt/6ymle3Iwg=="],
|
"@tiptap/extension-bold": ["@tiptap/extension-bold@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-fz++Qv6Rk/Hov0IYG/r7TJ1Y4zWkuGONe0UN5g0KY32NIMg3HeOHicbi4xsNWTm9uAOl3eawWDkezEMrleObMw=="],
|
||||||
|
|
||||||
"@tiptap/extension-bubble-menu": ["@tiptap/extension-bubble-menu@3.20.0", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-MDosUfs8Tj+nwg8RC+wTMWGkLJORXmbR6YZgbiX4hrc7G90Gopdd6kj6ht5/T8t7dLLaX7N0+DEHdUEPGED7dw=="],
|
"@tiptap/extension-bubble-menu": ["@tiptap/extension-bubble-menu@3.20.1", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-XaPvO6aCoWdFnCBus0s88lnj17NR/OopV79i8Qhgz3WMR0vrsL5zsd45l0lZuu9pSvm5VW47SoxakkJiZC1suw=="],
|
||||||
|
|
||||||
"@tiptap/extension-bullet-list": ["@tiptap/extension-bullet-list@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-OcKMeopBbqWzhSi6o8nNz0aayogg1sfOAhto3NxJu3Ya32dwBFqmHXSYM6uW4jOphNvVPyjiq9aNRh3qTdd1dw=="],
|
"@tiptap/extension-bullet-list": ["@tiptap/extension-bullet-list@3.20.1", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.1" } }, "sha512-mbrlvOZo5OF3vLhp+3fk9KuL/6J/wsN0QxF6ZFRAHzQ9NkJdtdfARcBeBnkWXGN8inB6YxbTGY1/E4lmBkOpOw=="],
|
||||||
|
|
||||||
"@tiptap/extension-code": ["@tiptap/extension-code@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-TYDWFeSQ9umiyrqsT6VecbuhL8XIHkUhO+gEk0sVvH67ZLwjFDhAIIgWIr1/dbIGPcvMZM19E7xUUhAdIaXaOQ=="],
|
"@tiptap/extension-code": ["@tiptap/extension-code@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-509DHINIA/Gg+eTG7TEkfsS8RUiPLH5xZNyLRT0A1oaoaJmECKfrV6aAm05IdfTyqDqz6LW5pbnX6DdUC4keug=="],
|
||||||
|
|
||||||
"@tiptap/extension-code-block": ["@tiptap/extension-code-block@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-lBbmNek14aCjrHcBcq3PRqWfNLvC6bcRa2Osc6e/LtmXlcpype4f6n+Yx+WZ+f2uUh0UmDRCz7BEyUETEsDmlQ=="],
|
"@tiptap/extension-code-block": ["@tiptap/extension-code-block@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-vKejwBq+Nlj4Ybd3qOyDxIQKzYymdNH+8eXkKwGShk2nfLJIxq69DCyGvmuHgipIO1qcYPJ149UNpGN+YGcdmA=="],
|
||||||
|
|
||||||
"@tiptap/extension-collaboration": ["@tiptap/extension-collaboration@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/y-tiptap": "^3.0.2", "yjs": "^13" } }, "sha512-JItmI4U0i4kqorO114u24hM9k945IdaQ6Uc2DEtPBFFuS8cepJf2zw+ulAT1kAx6ZRiNvNpT9M7w+J0mWRn+Sg=="],
|
"@tiptap/extension-collaboration": ["@tiptap/extension-collaboration@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1", "@tiptap/y-tiptap": "^3.0.2", "yjs": "^13" } }, "sha512-JnwLvyzrutBffHp6YPnf0XyTnhAgqZ9D8JSUKFp0edvai+dxsb+UMlawesBrgAuoQXw3B8YZUo2VFDVdKas1xQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-document": ["@tiptap/extension-document@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-oJfLIG3vAtZo/wg29WiBcyWt22KUgddpP8wqtCE+kY5Dw8znLR9ehNmVWlSWJA5OJUMO0ntAHx4bBT+I2MBd5w=="],
|
"@tiptap/extension-document": ["@tiptap/extension-document@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-9vrqdGmRV7bQCSY3NLgu7UhIwgOCDp4sKqMNsoNRX0aZ021QQMTvBQDPkiRkCf7MNsnWrNNnr52PVnULEn3vFQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-drag-handle": ["@tiptap/extension-drag-handle@3.20.0", "", { "dependencies": { "@floating-ui/dom": "^1.6.13" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/extension-collaboration": "^3.20.0", "@tiptap/extension-node-range": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/y-tiptap": "^3.0.2" } }, "sha512-CzLRyxZe5QddQey0RUWJUvICyhuRnU/jvzMIYlFvMxM7W97sZ2ggk0cRThlRt2pRUoSr8mmmUnobiorpISmksA=="],
|
"@tiptap/extension-drag-handle": ["@tiptap/extension-drag-handle@3.20.1", "", { "dependencies": { "@floating-ui/dom": "^1.6.13" }, "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/extension-collaboration": "^3.20.1", "@tiptap/extension-node-range": "^3.20.1", "@tiptap/pm": "^3.20.1", "@tiptap/y-tiptap": "^3.0.2" } }, "sha512-sIfu5Gt1aZVAagvzr+3Qx+8GE294eU3G6/pYjqNHvf71sDCpdN2gFpeI7WF05foVsCGsH6ieu8x/kTXf5GbNZA=="],
|
||||||
|
|
||||||
"@tiptap/extension-drag-handle-vue-3": ["@tiptap/extension-drag-handle-vue-3@3.20.0", "", { "peerDependencies": { "@tiptap/extension-drag-handle": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/vue-3": "^3.20.0", "vue": "^3.0.0" } }, "sha512-Jx6LHYRI5uRaJVNQGkQsTFQkAM84rYQh3Q+WBePhGF4yPBUJQFn7Nv+5fQhKKV3A5PVQ6kTAjvW6SSUcD6ON8A=="],
|
"@tiptap/extension-drag-handle-vue-3": ["@tiptap/extension-drag-handle-vue-3@3.20.1", "", { "peerDependencies": { "@tiptap/extension-drag-handle": "^3.20.1", "@tiptap/pm": "^3.20.1", "@tiptap/vue-3": "^3.20.1", "vue": "^3.0.0" } }, "sha512-FJonOxcj/I7uBpJBSqfEfU+Fqem5aanEj+EsqG5ZQnxhp7cxbUYZkGH0tBBR7jeIIkt2Jk+1LoCAlYzCWbDLcQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-dropcursor": ["@tiptap/extension-dropcursor@3.20.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.0" } }, "sha512-d+cxplRlktVgZPwatnc34IArlppM0IFKS1J5wLk+ba1jidizsbMVh45tP/BTK2flhyfRqcNoB5R0TArhUpbkNQ=="],
|
"@tiptap/extension-dropcursor": ["@tiptap/extension-dropcursor@3.20.1", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.1" } }, "sha512-K18L9FX4znn+ViPSIbTLOGcIaXMx/gLNwAPE8wPLwswbHhQqdiY1zzdBw6drgOc1Hicvebo2dIoUlSXOZsOEcw=="],
|
||||||
|
|
||||||
"@tiptap/extension-floating-menu": ["@tiptap/extension-floating-menu@3.20.0", "", { "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-rYs4Bv5pVjqZ/2vvR6oe7ammZapkAwN51As/WDbemvYDjfOGRqK58qGauUjYZiDzPOEIzI2mxGwsZ4eJhPW4Ig=="],
|
"@tiptap/extension-floating-menu": ["@tiptap/extension-floating-menu@3.20.1", "", { "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-BeDC6nfOesIMn5pFuUnkEjOxGv80sOJ8uk1mdt9/3Fkvra8cB9NIYYCVtd6PU8oQFmJ8vFqPrRkUWrG5tbqnOg=="],
|
||||||
|
|
||||||
"@tiptap/extension-gapcursor": ["@tiptap/extension-gapcursor@3.20.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.0" } }, "sha512-P/LasfvG9/qFq43ZAlNbAnPnXC+/RJf49buTrhtFvI9Zg0+Lbpjx1oh6oMHB19T88Y28KtrckfFZ8aTSUWDq6w=="],
|
"@tiptap/extension-gapcursor": ["@tiptap/extension-gapcursor@3.20.1", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.1" } }, "sha512-kZOtttV6Ai8VUAgEng3h4WKFbtdSNJ6ps7r0cRPY+FctWhVmgNb/JJwwyC+vSilR7nRENAhrA/Cv/RxVlvLw+g=="],
|
||||||
|
|
||||||
"@tiptap/extension-hard-break": ["@tiptap/extension-hard-break@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-rqvhMOw4f+XQmEthncbvDjgLH6fz8L9splnKZC7OeS0eX8b0qd7+xI1u5kyxF3KA2Z0BnigES++jjWuecqV6mA=="],
|
"@tiptap/extension-hard-break": ["@tiptap/extension-hard-break@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-9sKpmg/IIdlLXimYWUZ3PplIRcehv4Oc7V1miTqlnAthMzjMqigDkjjgte4JZV67RdnDJTQkRw8TklCAU28Emg=="],
|
||||||
|
|
||||||
"@tiptap/extension-heading": ["@tiptap/extension-heading@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-JgJhurnCe3eN6a0lEsNQM/46R1bcwzwWWZEFDSb1P9dR8+t1/5v7cMZWsSInpD7R4/74iJn0+M5hcXLwCmBmYA=="],
|
"@tiptap/extension-heading": ["@tiptap/extension-heading@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-unudyfQP6FxnyWinxvPqe/51DG91J6AaJm666RnAubgYMCgym+33kBftx4j4A6qf+ddWYbD00thMNKOnVLjAEQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-horizontal-rule": ["@tiptap/extension-horizontal-rule@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-6uvcutFMv+9wPZgptDkbRDjAm3YVxlibmkhWD5GuaWwS9L/yUtobpI3GycujRSUZ8D3q6Q9J7LqpmQtQRTalWA=="],
|
"@tiptap/extension-horizontal-rule": ["@tiptap/extension-horizontal-rule@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-rjFKFXNntdl0jay8oIGFvvykHlpyQTLmrH3Ag2fj3i8yh6MVvqhtaDomYQbw5sxECd5hBkL+T4n2d2DRuVw/QQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-image": ["@tiptap/extension-image@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-0t7HYncV0kYEQS79NFczxdlZoZ8zu8X4VavDqt+mbSAUKRq3gCvgtZ5Zyd778sNmtmbz3arxkEYMIVou2swD0g=="],
|
"@tiptap/extension-image": ["@tiptap/extension-image@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-/GPFSLNdYSZQ0E6VBXSAk0UFtDdn98HT1Aa2tO+STELqc5jAdFB42dfFnTC6KQzTvcUOUYkE2S1Q22YC5H2XNQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-italic": ["@tiptap/extension-italic@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-/DhnKQF8yN8RxtuL8abZ28wd5281EaGoE2Oha35zXSOF1vNYnbyt8Ymkv/7u1BcWEWTvRPgaju0YCGXisPRLYw=="],
|
"@tiptap/extension-italic": ["@tiptap/extension-italic@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-ZYRX13Kt8tR8JOzSXirH3pRpi8x30o7LHxZY58uXBdUvr3tFzOkh03qbN523+diidSVeHP/aMd/+IrplHRkQug=="],
|
||||||
|
|
||||||
"@tiptap/extension-link": ["@tiptap/extension-link@3.20.0", "", { "dependencies": { "linkifyjs": "^4.3.2" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-qI/5A+R0ZWBxo/8HxSn1uOyr7odr3xHBZ/gzOR1GUJaZqjlJxkWFX0RtXMbLKEGEvT25o345cF7b0wFznEh8qA=="],
|
"@tiptap/extension-link": ["@tiptap/extension-link@3.20.1", "", { "dependencies": { "linkifyjs": "^4.3.2" }, "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-oYTTIgsQMqpkSnJAuAc+UtIKMuI4lv9e1y4LfI1iYm6NkEUHhONppU59smhxHLzb3Ww7YpDffbp5IgDTAiJztA=="],
|
||||||
|
|
||||||
"@tiptap/extension-list": ["@tiptap/extension-list@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-+V0/gsVWAv+7vcY0MAe6D52LYTIicMSHw00wz3ISZgprSb2yQhJ4+4gurOnUrQ4Du3AnRQvxPROaofwxIQ66WQ=="],
|
"@tiptap/extension-list": ["@tiptap/extension-list@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-euBRAn0mkV7R2VEE+AuOt3R0j9RHEMFXamPFmtvTo8IInxDClusrm6mJoDjS8gCGAXsQCRiAe1SCQBPgGbOOwg=="],
|
||||||
|
|
||||||
"@tiptap/extension-list-item": ["@tiptap/extension-list-item@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-qEtjaaGPuqaFB4VpLrGDoIe9RHnckxPfu6d3rc22ap6TAHCDyRv05CEyJogqccnFceG/v5WN4znUBER8RWnWHA=="],
|
"@tiptap/extension-list-item": ["@tiptap/extension-list-item@3.20.1", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.1" } }, "sha512-tzgnyTW82lYJkUnadYbatwkI9dLz/OWRSWuFpQPRje/ItmFMWuQ9c9NDD8qLbXPdEYnvrgSAA+ipCD/1G0qA0Q=="],
|
||||||
|
|
||||||
"@tiptap/extension-list-keymap": ["@tiptap/extension-list-keymap@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-Z4GvKy04Ms4cLFN+CY6wXswd36xYsT2p/YL0V89LYFMZTerOeTjFYlndzn6svqL8NV1PRT5Diw4WTTxJSmcJPA=="],
|
"@tiptap/extension-list-keymap": ["@tiptap/extension-list-keymap@3.20.1", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.1" } }, "sha512-Dr0xsQKx0XPOgDg7xqoWwfv7FFwZ3WeF3eOjqh3rDXlNHMj1v+UW5cj1HLphrsAZHTrVTn2C+VWPJkMZrSbpvQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-mention": ["@tiptap/extension-mention@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/suggestion": "^3.20.0" } }, "sha512-wUjsq7Za0JJdJzrGNG+g8nrCpek/85GQ0Rm9bka3PynIVRwus+xQqW6IyWVPBdl1BSkrbgMAUqtrfoh1ymznbg=="],
|
"@tiptap/extension-mention": ["@tiptap/extension-mention@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1", "@tiptap/suggestion": "^3.20.1" } }, "sha512-KOGokj7oH1QpcM8P02V+o6wHsVE0g7XEtdIy2vtq2vlFE3npNNNFkMa8F8VWX6qyC+VeVrNU6SIzS5MFY2TORA=="],
|
||||||
|
|
||||||
"@tiptap/extension-node-range": ["@tiptap/extension-node-range@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-XeKKTV88VuJ4Mh0Rxvc/PPzG76cb44sE+rB4u0J/ms63R/WFTm6yJQlCgUVGnGeHleSlrWuZY8gGSuoljmQzqg=="],
|
"@tiptap/extension-node-range": ["@tiptap/extension-node-range@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-+W/mQJxlkXMcwldWUqwdoR0eniJ1S9cVJoAy2Lkis0NhILZDWVNGKl9J4WFoCOXn8Myr17IllIxRYvAXJJ4FHQ=="],
|
||||||
|
|
||||||
"@tiptap/extension-ordered-list": ["@tiptap/extension-ordered-list@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-jVKnJvrizLk7etwBMfyoj6H2GE4M+PD4k7Bwp6Bh1ohBWtfIA1TlngdS842Mx5i1VB2e3UWIwr8ZH46gl6cwMA=="],
|
"@tiptap/extension-ordered-list": ["@tiptap/extension-ordered-list@3.20.1", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.1" } }, "sha512-Y+3Ad7OwAdagqdYwCnbqf7/to5ypD4NnUNHA0TXRCs7cAHRA8AdgPoIcGFpaaSpV86oosNU3yfeJouYeroffog=="],
|
||||||
|
|
||||||
"@tiptap/extension-paragraph": ["@tiptap/extension-paragraph@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-mM99zK4+RnEXIMCv6akfNATAs0Iija6FgyFA9J9NZ6N4o8y9QiNLLa6HjLpAC+W+VoCgQIekyoF/Q9ftxmAYDQ=="],
|
"@tiptap/extension-paragraph": ["@tiptap/extension-paragraph@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-QFrAtXNyv7JSnomMQc1nx5AnG9mMznfbYJAbdOQYVdbLtAzTfiTuNPNbQrufy5ZGtGaHxDCoaygu2QEfzaKG+Q=="],
|
||||||
|
|
||||||
"@tiptap/extension-placeholder": ["@tiptap/extension-placeholder@3.20.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.0" } }, "sha512-ZhYD3L5m16ydSe2z8vqz+RdtAG/iOQaFHHedFct70tKRoLqi2ajF5kgpemu8DwpaRTcyiCN4G99J/+MqehKNjQ=="],
|
"@tiptap/extension-placeholder": ["@tiptap/extension-placeholder@3.20.1", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.1" } }, "sha512-k+jfbCugYGuIFBdojukgEopGazIMOgHrw46FnyN2X/6ICOIjQP2rh2ObslrsUOsJYoEevxCsNF9hZl1HvWX66g=="],
|
||||||
|
|
||||||
"@tiptap/extension-strike": ["@tiptap/extension-strike@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-0vcTZRRAiDfon3VM1mHBr9EFmTkkUXMhm0Xtdtn0bGe+sIqufyi+hUYTEw93EQOD9XNsPkrud6jzQNYpX2H3AQ=="],
|
"@tiptap/extension-strike": ["@tiptap/extension-strike@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-EYgyma10lpsY+rwbVQL9u+gA7hBlKLSMFH7Zgd37FSxukOjr+HE8iKPQQ+SwbGejyDsPlLT8Z5Jnuxo5Ng90Pg=="],
|
||||||
|
|
||||||
"@tiptap/extension-text": ["@tiptap/extension-text@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-tf8bE8tSaOEWabCzPm71xwiUhyMFKqY9jkP5af3Kr1/F45jzZFIQAYZooHI/+zCHRrgJ99MQHKHe1ZNvODrKHQ=="],
|
"@tiptap/extension-text": ["@tiptap/extension-text@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-7PlIbYW8UenV6NPOXHmv8IcmPGlGx6HFq66RmkJAOJRPXPkTLAiX0N8rQtzUJ6jDEHqoJpaHFEHJw0xzW1yF+A=="],
|
||||||
|
|
||||||
"@tiptap/extension-underline": ["@tiptap/extension-underline@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-LzNXuy2jwR/y+ymoUqC72TiGzbOCjioIjsDu0MNYpHuHqTWPK5aV9Mh0nbZcYFy/7fPlV1q0W139EbJeYBZEAQ=="],
|
"@tiptap/extension-underline": ["@tiptap/extension-underline@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1" } }, "sha512-fmHvDKzwCgnZUwRreq8tYkb1YyEwgzZ6QQkAQ0CsCRtvRMqzerr3Duz0Als4i8voZTuGDEL3VR6nAJbLAb/wPg=="],
|
||||||
|
|
||||||
"@tiptap/extensions": ["@tiptap/extensions@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-HIsXX942w3nbxEQBlMAAR/aa6qiMBEP7CsSMxaxmTIVAmW35p6yUASw6GdV1u0o3lCZjXq2OSRMTskzIqi5uLg=="],
|
"@tiptap/extensions": ["@tiptap/extensions@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-JRc/v+OBH0qLTdvQ7HvHWTxGJH73QOf1MC0R8NhOX2QnAbg2mPFv1h+FjGa2gfLGuCXBdWQomjekWkUKbC4e5A=="],
|
||||||
|
|
||||||
"@tiptap/markdown": ["@tiptap/markdown@3.20.0", "", { "dependencies": { "marked": "^17.0.1" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-3vUxs8tsVIf/KWKLWjFsTqrjuaTYJY9rawDL5sio9NwlqFWDuWpHEVJcqbQXJUrgQSh12AZoTKyfgiEqkAGI3Q=="],
|
"@tiptap/markdown": ["@tiptap/markdown@3.20.1", "", { "dependencies": { "marked": "^17.0.1" }, "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-dNrtP7kmabDomgjv9G/6+JSFL6WraPaFbmKh1eHSYKdDGvIwBfJnVPTV2VS3bP1OuYJEDJN/2ydtiCHyOTrQsQ=="],
|
||||||
|
|
||||||
"@tiptap/pm": ["@tiptap/pm@3.20.0", "", { "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.6.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", "prosemirror-history": "^1.4.1", "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", "prosemirror-markdown": "^1.13.1", "prosemirror-menu": "^1.2.4", "prosemirror-model": "^1.24.1", "prosemirror-schema-basic": "^1.2.3", "prosemirror-schema-list": "^1.5.0", "prosemirror-state": "^1.4.3", "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", "prosemirror-view": "^1.38.1" } }, "sha512-jn+2KnQZn+b+VXr8EFOJKsnjVNaA4diAEr6FOazupMt8W8ro1hfpYtZ25JL87Kao/WbMze55sd8M8BDXLUKu1A=="],
|
"@tiptap/pm": ["@tiptap/pm@3.20.1", "", { "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.6.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", "prosemirror-history": "^1.4.1", "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", "prosemirror-markdown": "^1.13.1", "prosemirror-menu": "^1.2.4", "prosemirror-model": "^1.24.1", "prosemirror-schema-basic": "^1.2.3", "prosemirror-schema-list": "^1.5.0", "prosemirror-state": "^1.4.3", "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", "prosemirror-view": "^1.38.1" } }, "sha512-6kCiGLvpES4AxcEuOhb7HR7/xIeJWMjZlb6J7e8zpiIh5BoQc7NoRdctsnmFEjZvC19bIasccshHQ7H2zchWqw=="],
|
||||||
|
|
||||||
"@tiptap/starter-kit": ["@tiptap/starter-kit@3.20.0", "", { "dependencies": { "@tiptap/core": "^3.20.0", "@tiptap/extension-blockquote": "^3.20.0", "@tiptap/extension-bold": "^3.20.0", "@tiptap/extension-bullet-list": "^3.20.0", "@tiptap/extension-code": "^3.20.0", "@tiptap/extension-code-block": "^3.20.0", "@tiptap/extension-document": "^3.20.0", "@tiptap/extension-dropcursor": "^3.20.0", "@tiptap/extension-gapcursor": "^3.20.0", "@tiptap/extension-hard-break": "^3.20.0", "@tiptap/extension-heading": "^3.20.0", "@tiptap/extension-horizontal-rule": "^3.20.0", "@tiptap/extension-italic": "^3.20.0", "@tiptap/extension-link": "^3.20.0", "@tiptap/extension-list": "^3.20.0", "@tiptap/extension-list-item": "^3.20.0", "@tiptap/extension-list-keymap": "^3.20.0", "@tiptap/extension-ordered-list": "^3.20.0", "@tiptap/extension-paragraph": "^3.20.0", "@tiptap/extension-strike": "^3.20.0", "@tiptap/extension-text": "^3.20.0", "@tiptap/extension-underline": "^3.20.0", "@tiptap/extensions": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-W4+1re35pDNY/7rpXVg+OKo/Fa4Gfrn08Bq3E3fzlJw6gjE3tYU8dY9x9vC2rK9pd9NOp7Af11qCFDaWpohXkw=="],
|
"@tiptap/starter-kit": ["@tiptap/starter-kit@3.20.1", "", { "dependencies": { "@tiptap/core": "^3.20.1", "@tiptap/extension-blockquote": "^3.20.1", "@tiptap/extension-bold": "^3.20.1", "@tiptap/extension-bullet-list": "^3.20.1", "@tiptap/extension-code": "^3.20.1", "@tiptap/extension-code-block": "^3.20.1", "@tiptap/extension-document": "^3.20.1", "@tiptap/extension-dropcursor": "^3.20.1", "@tiptap/extension-gapcursor": "^3.20.1", "@tiptap/extension-hard-break": "^3.20.1", "@tiptap/extension-heading": "^3.20.1", "@tiptap/extension-horizontal-rule": "^3.20.1", "@tiptap/extension-italic": "^3.20.1", "@tiptap/extension-link": "^3.20.1", "@tiptap/extension-list": "^3.20.1", "@tiptap/extension-list-item": "^3.20.1", "@tiptap/extension-list-keymap": "^3.20.1", "@tiptap/extension-ordered-list": "^3.20.1", "@tiptap/extension-paragraph": "^3.20.1", "@tiptap/extension-strike": "^3.20.1", "@tiptap/extension-text": "^3.20.1", "@tiptap/extension-underline": "^3.20.1", "@tiptap/extensions": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-opqWxL/4OTEiqmVC0wsU4o3JhAf6LycJ2G/gRIZVAIFLljI9uHfpPMTFGxZ5w9IVVJaP5PJysfwW/635kKqkrw=="],
|
||||||
|
|
||||||
"@tiptap/suggestion": ["@tiptap/suggestion@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-OA9Fe+1Q/Ex0ivTcpRcVFiLnNsVdIBmiEoctt/gu4H2ayCYmZ906veioXNdc1m/3MtVVUIuEnvwwsrOZXlfDEw=="],
|
"@tiptap/suggestion": ["@tiptap/suggestion@3.20.1", "", { "peerDependencies": { "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1" } }, "sha512-ng7olbzgZhWvPJVJygNQK5153CjquR2eJXpkLq7bRjHlahvt4TH4tGFYvGdYZcXuzbe2g9RoqT7NaPGL9CUq9w=="],
|
||||||
|
|
||||||
"@tiptap/vue-3": ["@tiptap/vue-3@3.20.0", "", { "optionalDependencies": { "@tiptap/extension-bubble-menu": "^3.20.0", "@tiptap/extension-floating-menu": "^3.20.0" }, "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0", "vue": "^3.0.0" } }, "sha512-u8UfDKsbIOF+mVsXwJ946p1jfrLGFUyqp9i/DAeGGg2I85DPOkhZgz67bUPVXkpossoEk+jKCkRN0eBHl9+eZQ=="],
|
"@tiptap/vue-3": ["@tiptap/vue-3@3.20.1", "", { "optionalDependencies": { "@tiptap/extension-bubble-menu": "^3.20.1", "@tiptap/extension-floating-menu": "^3.20.1" }, "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.20.1", "@tiptap/pm": "^3.20.1", "vue": "^3.0.0" } }, "sha512-06IsNzIkAC0HPHNSdXf4AgtExnr02BHBLXmUiNrjjhgHdxXDKIB0Yq3hEWEfbWNPr3lr7jK6EaFu2IKFMhoUtQ=="],
|
||||||
|
|
||||||
"@tiptap/y-tiptap": ["@tiptap/y-tiptap@3.0.2", "", { "dependencies": { "lib0": "^0.2.100" }, "peerDependencies": { "prosemirror-model": "^1.7.1", "prosemirror-state": "^1.2.3", "prosemirror-view": "^1.9.10", "y-protocols": "^1.0.1", "yjs": "^13.5.38" } }, "sha512-flMn/YW6zTbc6cvDaUPh/NfLRTXDIqgpBUkYzM74KA1snqQwhOMjnRcnpu4hDFrTnPO6QGzr99vRyXEA7M44WA=="],
|
"@tiptap/y-tiptap": ["@tiptap/y-tiptap@3.0.2", "", { "dependencies": { "lib0": "^0.2.100" }, "peerDependencies": { "prosemirror-model": "^1.7.1", "prosemirror-state": "^1.2.3", "prosemirror-view": "^1.9.10", "y-protocols": "^1.0.1", "yjs": "^13.5.38" } }, "sha512-flMn/YW6zTbc6cvDaUPh/NfLRTXDIqgpBUkYzM74KA1snqQwhOMjnRcnpu4hDFrTnPO6QGzr99vRyXEA7M44WA=="],
|
||||||
|
|
||||||
@@ -464,31 +470,31 @@
|
|||||||
|
|
||||||
"@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],
|
"@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.10.13", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg=="],
|
"@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||||
|
|
||||||
"@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="],
|
"@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="],
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.56.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/type-utils": "8.56.1", "@typescript-eslint/utils": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.56.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A=="],
|
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/type-utils": "8.57.0", "@typescript-eslint/utils": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.56.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg=="],
|
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g=="],
|
||||||
|
|
||||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.56.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.56.1", "@typescript-eslint/types": "^8.56.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ=="],
|
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.0", "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w=="],
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1" } }, "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w=="],
|
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0" } }, "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw=="],
|
||||||
|
|
||||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.56.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ=="],
|
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA=="],
|
||||||
|
|
||||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/utils": "8.56.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg=="],
|
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/utils": "8.57.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.56.1", "", {}, "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw=="],
|
"@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.56.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.56.1", "@typescript-eslint/tsconfig-utils": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg=="],
|
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.0", "@typescript-eslint/tsconfig-utils": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q=="],
|
||||||
|
|
||||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.56.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA=="],
|
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.56.1", "", { "dependencies": { "@typescript-eslint/types": "8.56.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw=="],
|
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="],
|
||||||
|
|
||||||
"@unhead/vue": ["@unhead/vue@2.1.7", "", { "dependencies": { "hookable": "^6.0.1", "unhead": "2.1.7" }, "peerDependencies": { "vue": ">=3.5.18" } }, "sha512-azD4x32BKBDMcKMcCeU+kCBowPFRFSSFJSHP+mr2P1TpPV/4b6UsmMPiTb+gSW8NZ6s0myJ/CaVMoeC5mGKhKg=="],
|
"@unhead/vue": ["@unhead/vue@2.1.12", "", { "dependencies": { "hookable": "^6.0.1", "unhead": "2.1.12" }, "peerDependencies": { "vue": ">=3.5.18" } }, "sha512-zEWqg0nZM8acpuTZE40wkeUl8AhIe0tU0OkilVi1D4fmVjACrwoh5HP6aNqJ8kUnKsoy6D+R3Vi/O+fmdNGO7g=="],
|
||||||
|
|
||||||
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.4", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.2" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "vue": "^3.2.25" } }, "sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ=="],
|
"@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.4", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.2" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "vue": "^3.2.25" } }, "sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ=="],
|
||||||
|
|
||||||
@@ -506,39 +512,39 @@
|
|||||||
|
|
||||||
"@vue/babel-plugin-resolve-type": ["@vue/babel-plugin-resolve-type@1.5.0", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/parser": "^7.28.0", "@vue/compiler-sfc": "^3.5.18" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w=="],
|
"@vue/babel-plugin-resolve-type": ["@vue/babel-plugin-resolve-type@1.5.0", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/parser": "^7.28.0", "@vue/compiler-sfc": "^3.5.18" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w=="],
|
||||||
|
|
||||||
"@vue/compiler-core": ["@vue/compiler-core@3.6.0-beta.6", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/shared": "3.6.0-beta.6", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-0/YAWFJKJEpYMiMkNaYgUxbf4TWVrCnZ4Pmp898yQUJgQ3B+E2usG8n4tCytniGIIQ3BoLnkUipTNia8g6vp8A=="],
|
"@vue/compiler-core": ["@vue/compiler-core@3.6.0-beta.7", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/shared": "3.6.0-beta.7", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-fYOlA9PCFuf5l8AtKJSxAM+K+MLoM8dyN9Xsa/GDE0Uf6wxFe33AEU6xyVqYMPy6uxp4RtgE4KuQ7JdYvE0Jnw=="],
|
||||||
|
|
||||||
"@vue/compiler-dom": ["@vue/compiler-dom@3.6.0-beta.6", "", { "dependencies": { "@vue/compiler-core": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6" } }, "sha512-kX9aROGuDCz9YTvPiOltOsZ4lu2lAH9rMc5tFt7zrFs2KNBXON4HDSg5Vnu4kTb5tNhM/8YX1Cv2XjwmaCD6Wg=="],
|
"@vue/compiler-dom": ["@vue/compiler-dom@3.6.0-beta.7", "", { "dependencies": { "@vue/compiler-core": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7" } }, "sha512-4myAKKPogd6MAA/oKKn1+uDOPGJ6gB+pivaUxaBqfvXJch1QHSpcUgdHCJqDb9O/99EjcwppkTLGe7cRWMSqHQ=="],
|
||||||
|
|
||||||
"@vue/compiler-sfc": ["@vue/compiler-sfc@3.6.0-beta.6", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/compiler-core": "3.6.0-beta.6", "@vue/compiler-dom": "3.6.0-beta.6", "@vue/compiler-ssr": "3.6.0-beta.6", "@vue/compiler-vapor": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-hQL0RqB4jNf9QFUvl8xl7nDHZdsWE3IysbMAbgVUmQvhzmFdnP6Bcp8FnyGBhxwo6IJouQoT0HniKudXP13aGA=="],
|
"@vue/compiler-sfc": ["@vue/compiler-sfc@3.6.0-beta.7", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/compiler-core": "3.6.0-beta.7", "@vue/compiler-dom": "3.6.0-beta.7", "@vue/compiler-ssr": "3.6.0-beta.7", "@vue/compiler-vapor": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-bf0NkJb0Hxoj1K8cZKYgduEY0FPP28WnoUGqHvYA/a1cjJfrhaypbiS5u6pEFVXug/JZJF9sI+c4JTHkgqRKDw=="],
|
||||||
|
|
||||||
"@vue/compiler-ssr": ["@vue/compiler-ssr@3.6.0-beta.6", "", { "dependencies": { "@vue/compiler-dom": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6" } }, "sha512-UkaN+QhSQh4Nc9BiQZvH7fuL+3RDWOvGc+zuHCwUsR8FLOxNbuUKsDe0FlFk914xDDx4IUYzJKyIeSEzqoxCYA=="],
|
"@vue/compiler-ssr": ["@vue/compiler-ssr@3.6.0-beta.7", "", { "dependencies": { "@vue/compiler-dom": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7" } }, "sha512-fwO4qe6iXZ+SZedurh/vLwjBgjAX/wL5aI/eIECv0C79AgTAlJNjD6dwMafukhnZamQgNKYBxXUOkGl8sqn1PA=="],
|
||||||
|
|
||||||
"@vue/compiler-vapor": ["@vue/compiler-vapor@3.6.0-beta.6", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/compiler-dom": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-U04KIqp/YYRVt+GU2pGZhZ+q4GWm/Ii2SFrwZqCjXFghU4f5+21Ba6Sru9FzuaYzRY4ubdUz9bpKE0BVd2d46Q=="],
|
"@vue/compiler-vapor": ["@vue/compiler-vapor@3.6.0-beta.7", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/compiler-dom": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-fc6ZAFv9yRSoQQVsgN5gGDaUWdTPctDb6lVUtUGgnrCB7n+hQIBwuId7HIeic3PK6HPVZMoEbluNU/ge3DIveA=="],
|
||||||
|
|
||||||
"@vue/devtools-api": ["@vue/devtools-api@7.7.9", "", { "dependencies": { "@vue/devtools-kit": "^7.7.9" } }, "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g=="],
|
"@vue/devtools-api": ["@vue/devtools-api@7.7.9", "", { "dependencies": { "@vue/devtools-kit": "^7.7.9" } }, "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g=="],
|
||||||
|
|
||||||
"@vue/devtools-core": ["@vue/devtools-core@8.0.6", "", { "dependencies": { "@vue/devtools-kit": "^8.0.6", "@vue/devtools-shared": "^8.0.6", "mitt": "^3.0.1", "nanoid": "^5.1.5", "pathe": "^2.0.3", "vite-hot-client": "^2.1.0" }, "peerDependencies": { "vue": "^3.0.0" } }, "sha512-fN7iVtpSQQdtMORWwVZ1JiIAKriinhD+lCHqPw9Rr252ae2TczILEmW0zcAZifPW8HfYcbFkn+h7Wv6kQQCayw=="],
|
"@vue/devtools-core": ["@vue/devtools-core@8.0.7", "", { "dependencies": { "@vue/devtools-kit": "^8.0.7", "@vue/devtools-shared": "^8.0.7" }, "peerDependencies": { "vue": "^3.0.0" } }, "sha512-PmpiPxvg3Of80ODHVvyckxwEW1Z02VIAvARIZS1xegINn3VuNQLm9iHUmKD+o6cLkMNWV8OG8x7zo0kgydZgdg=="],
|
||||||
|
|
||||||
"@vue/devtools-kit": ["@vue/devtools-kit@8.0.6", "", { "dependencies": { "@vue/devtools-shared": "^8.0.6", "birpc": "^2.6.1", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^2.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-9zXZPTJW72OteDXeSa5RVML3zWDCRcO5t77aJqSs228mdopYj5AiTpihozbsfFJ0IodfNs7pSgOGO3qfCuxDtw=="],
|
"@vue/devtools-kit": ["@vue/devtools-kit@8.0.7", "", { "dependencies": { "@vue/devtools-shared": "^8.0.7", "birpc": "^2.6.1", "hookable": "^5.5.3", "perfect-debounce": "^2.0.0" } }, "sha512-H6esJGHGl5q0E9iV3m2EoBQHJ+V83WMW83A0/+Fn95eZ2iIvdsq4+UCS6yT/Fdd4cGZSchx/MdWDreM3WqMsDw=="],
|
||||||
|
|
||||||
"@vue/devtools-shared": ["@vue/devtools-shared@8.0.6", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-Pp1JylTqlgMJvxW6MGyfTF8vGvlBSCAvMFaDCYa82Mgw7TT5eE5kkHgDvmOGHWeJE4zIDfCpCxHapsK2LtIAJg=="],
|
"@vue/devtools-shared": ["@vue/devtools-shared@8.0.7", "", {}, "sha512-CgAb9oJH5NUmbQRdYDj/1zMiaICYSLtm+B1kxcP72LBrifGAjUmt8bx52dDH1gWRPlQgxGPqpAMKavzVirAEhA=="],
|
||||||
|
|
||||||
"@vue/eslint-config-typescript": ["@vue/eslint-config-typescript@14.7.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.56.0", "fast-glob": "^3.3.3", "typescript-eslint": "^8.56.0", "vue-eslint-parser": "^10.4.0" }, "peerDependencies": { "eslint": "^9.10.0 || ^10.0.0", "eslint-plugin-vue": "^9.28.0 || ^10.0.0", "typescript": ">=4.8.4" }, "optionalPeers": ["typescript"] }, "sha512-iegbMINVc+seZ/QxtzWiOBozctrHiF2WvGedruu2EbLujg9VuU0FQiNcN2z1ycuaoKKpF4m2qzB5HDEMKbxtIg=="],
|
"@vue/eslint-config-typescript": ["@vue/eslint-config-typescript@14.7.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.56.0", "fast-glob": "^3.3.3", "typescript-eslint": "^8.56.0", "vue-eslint-parser": "^10.4.0" }, "peerDependencies": { "eslint": "^9.10.0 || ^10.0.0", "eslint-plugin-vue": "^9.28.0 || ^10.0.0", "typescript": ">=4.8.4" }, "optionalPeers": ["typescript"] }, "sha512-iegbMINVc+seZ/QxtzWiOBozctrHiF2WvGedruu2EbLujg9VuU0FQiNcN2z1ycuaoKKpF4m2qzB5HDEMKbxtIg=="],
|
||||||
|
|
||||||
"@vue/language-core": ["@vue/language-core@3.2.5", "", { "dependencies": { "@volar/language-core": "2.4.28", "@vue/compiler-dom": "^3.5.0", "@vue/shared": "^3.5.0", "alien-signals": "^3.0.0", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", "picomatch": "^4.0.2" } }, "sha512-d3OIxN/+KRedeM5wQ6H6NIpwS3P5gC9nmyaHgBk+rO6dIsjY+tOh4UlPpiZbAh3YtLdCGEX4M16RmsBqPmJV+g=="],
|
"@vue/language-core": ["@vue/language-core@3.2.5", "", { "dependencies": { "@volar/language-core": "2.4.28", "@vue/compiler-dom": "^3.5.0", "@vue/shared": "^3.5.0", "alien-signals": "^3.0.0", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", "picomatch": "^4.0.2" } }, "sha512-d3OIxN/+KRedeM5wQ6H6NIpwS3P5gC9nmyaHgBk+rO6dIsjY+tOh4UlPpiZbAh3YtLdCGEX4M16RmsBqPmJV+g=="],
|
||||||
|
|
||||||
"@vue/reactivity": ["@vue/reactivity@3.6.0-beta.6", "", { "dependencies": { "@vue/shared": "3.6.0-beta.6" } }, "sha512-DWpq1Qk23XFWZI0dAho9koJNV+fjOJv5YNmLO2yymyjtDpraRaot+gQQlmyut3dEt4gIUKUHF7H/azi7ub5mZQ=="],
|
"@vue/reactivity": ["@vue/reactivity@3.6.0-beta.7", "", { "dependencies": { "@vue/shared": "3.6.0-beta.7" } }, "sha512-d1Z7U3QqfrpnT1/m8glRDBGlzQVj4J3u7LvCxieyxvrH03ZcR9qZ8hMw9x/Q3K/VcT2BSHp8A8662cqigCiCEA=="],
|
||||||
|
|
||||||
"@vue/runtime-core": ["@vue/runtime-core@3.6.0-beta.6", "", { "dependencies": { "@vue/reactivity": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6" } }, "sha512-whCWAVoBnac1rlLdAu17IrG4E1t05a44VOpvXWo+mYWgq28ukaoQmr3w7LPLyUU7ehWOh+Gp31fxAbKSArherg=="],
|
"@vue/runtime-core": ["@vue/runtime-core@3.6.0-beta.7", "", { "dependencies": { "@vue/reactivity": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7" } }, "sha512-z6wXT1w0lFYS2uHAYuNZRutxNmg5i4S6yKYVf58/DVu+j/L1eq2ntPNVpPJpof71izXbv14ImvvPUCTTqHwAUA=="],
|
||||||
|
|
||||||
"@vue/runtime-dom": ["@vue/runtime-dom@3.6.0-beta.6", "", { "dependencies": { "@vue/reactivity": "3.6.0-beta.6", "@vue/runtime-core": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6", "csstype": "^3.2.3" } }, "sha512-auc/UnNwB+Vcydp+HpV63a0WbDSueteT8OZNhcKicWtvRSVfxPAp83pVNtiY+CvRp4myl28Nxewff19XK+u1kw=="],
|
"@vue/runtime-dom": ["@vue/runtime-dom@3.6.0-beta.7", "", { "dependencies": { "@vue/reactivity": "3.6.0-beta.7", "@vue/runtime-core": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7", "csstype": "^3.2.3" } }, "sha512-purk/iT3R5y2CizeV+YdxHhqPE1yAk3MSptggsCdO0zkShl2NA1/xec1WgVg1OL6IV0xNrknsMxl9Fit4g44hA=="],
|
||||||
|
|
||||||
"@vue/runtime-vapor": ["@vue/runtime-vapor@3.6.0-beta.6", "", { "dependencies": { "@vue/reactivity": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6" }, "peerDependencies": { "@vue/runtime-dom": "3.6.0-beta.6" } }, "sha512-psN1lh/LJS7FS/KE8+JJYvdFWySq09Ww9xCFnXOaISFwh/2VWs5AvcAAq9dgk6+Z0qMUjrVVbspa6byLVCP/aA=="],
|
"@vue/runtime-vapor": ["@vue/runtime-vapor@3.6.0-beta.7", "", { "dependencies": { "@vue/reactivity": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7" }, "peerDependencies": { "@vue/runtime-dom": "3.6.0-beta.7" } }, "sha512-H+XdbkqtBI+9gsS957Om94qpTx+keklzvO6rllls4TcKlRo/xcXsDnMhWjghX0Irg6iM/MgBBK8bQkfUkF+xSg=="],
|
||||||
|
|
||||||
"@vue/server-renderer": ["@vue/server-renderer@3.6.0-beta.6", "", { "dependencies": { "@vue/compiler-ssr": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6" }, "peerDependencies": { "vue": "3.6.0-beta.6" } }, "sha512-IL8RRjIuNmmh4JZmne48htACrvTAYw+IvvGHezpSmom5uzXUyEW9VJqhda9LBnjEBWFVNImzAJGrQ1IZB9X1vg=="],
|
"@vue/server-renderer": ["@vue/server-renderer@3.6.0-beta.7", "", { "dependencies": { "@vue/compiler-ssr": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7" }, "peerDependencies": { "vue": "3.6.0-beta.7" } }, "sha512-VqX6+8+NyCC/nqkOvj/vKHeMtBr3Mxo7rccDLNyuSb6o5Mp+itlxdpaD0LD28SqHEaDjqfIUBTnFsfDJLN/cww=="],
|
||||||
|
|
||||||
"@vue/shared": ["@vue/shared@3.6.0-beta.6", "", {}, "sha512-CR/Df2m47Ou7mzF4IksSqfLpk5KtP1KBssocpoSSUbS/dUXPDRS/gRKT59LA3XHmluvnrMw+PYKuf5mzJPFt1Q=="],
|
"@vue/shared": ["@vue/shared@3.6.0-beta.7", "", {}, "sha512-BNC0ohwv5hYybiUvZ/7gBjSzWFRxpZ2MzRQ/lH2zYZds085ylmAqMGEwbGlWFD+/WPRBsXQd7+e1hNGFksNuCg=="],
|
||||||
|
|
||||||
"@vue/tsconfig": ["@vue/tsconfig@0.8.1", "", { "peerDependencies": { "typescript": "5.x", "vue": "^3.4.0" }, "optionalPeers": ["typescript", "vue"] }, "sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g=="],
|
"@vue/tsconfig": ["@vue/tsconfig@0.8.1", "", { "peerDependencies": { "typescript": "5.x", "vue": "^3.4.0" }, "optionalPeers": ["typescript", "vue"] }, "sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g=="],
|
||||||
|
|
||||||
@@ -580,7 +586,7 @@
|
|||||||
|
|
||||||
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
|
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@5.0.3", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA=="],
|
"brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||||
|
|
||||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||||
|
|
||||||
@@ -590,7 +596,7 @@
|
|||||||
|
|
||||||
"c12": ["c12@3.3.3", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q=="],
|
"c12": ["c12@3.3.3", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q=="],
|
||||||
|
|
||||||
"caniuse-lite": ["caniuse-lite@1.0.30001774", "", {}, "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA=="],
|
"caniuse-lite": ["caniuse-lite@1.0.30001777", "", {}, "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ=="],
|
||||||
|
|
||||||
"chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="],
|
"chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="],
|
||||||
|
|
||||||
@@ -616,7 +622,7 @@
|
|||||||
|
|
||||||
"crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="],
|
"crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="],
|
||||||
|
|
||||||
"css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="],
|
"css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="],
|
||||||
|
|
||||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||||
|
|
||||||
@@ -640,7 +646,7 @@
|
|||||||
|
|
||||||
"dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
|
"dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
|
||||||
|
|
||||||
"electron-to-chromium": ["electron-to-chromium@1.5.302", "", {}, "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg=="],
|
"electron-to-chromium": ["electron-to-chromium@1.5.307", "", {}, "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg=="],
|
||||||
|
|
||||||
"embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
|
"embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
|
||||||
|
|
||||||
@@ -660,7 +666,7 @@
|
|||||||
|
|
||||||
"embla-carousel-wheel-gestures": ["embla-carousel-wheel-gestures@8.1.0", "", { "dependencies": { "wheel-gestures": "^2.2.5" }, "peerDependencies": { "embla-carousel": "^8.0.0 || ~8.0.0-rc03" } }, "sha512-J68jkYrxbWDmXOm2n2YHl+uMEXzkGSKjWmjaEgL9xVvPb3HqVmg6rJSKfI3sqIDVvm7mkeTy87wtG/5263XqHQ=="],
|
"embla-carousel-wheel-gestures": ["embla-carousel-wheel-gestures@8.1.0", "", { "dependencies": { "wheel-gestures": "^2.2.5" }, "peerDependencies": { "embla-carousel": "^8.0.0 || ~8.0.0-rc03" } }, "sha512-J68jkYrxbWDmXOm2n2YHl+uMEXzkGSKjWmjaEgL9xVvPb3HqVmg6rJSKfI3sqIDVvm7mkeTy87wtG/5263XqHQ=="],
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="],
|
"enhanced-resolve": ["enhanced-resolve@5.20.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="],
|
||||||
|
|
||||||
"entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
|
"entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
|
||||||
|
|
||||||
@@ -674,15 +680,15 @@
|
|||||||
|
|
||||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||||
|
|
||||||
"eslint": ["eslint@10.0.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.2", "@eslint/config-helpers": "^0.5.2", "@eslint/core": "^1.1.0", "@eslint/plugin-kit": "^0.6.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.1", "eslint-visitor-keys": "^5.0.1", "espree": "^11.1.1", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.1", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-uYixubwmqJZH+KLVYIVKY1JQt7tysXhtj21WSvjcSmU5SVNzMus1bgLe+pAt816yQ8opKfheVVoPLqvVMGejYw=="],
|
"eslint": ["eslint@10.0.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.3", "@eslint/config-helpers": "^0.5.2", "@eslint/core": "^1.1.1", "@eslint/plugin-kit": "^0.6.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.1.1", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ=="],
|
||||||
|
|
||||||
"eslint-plugin-vue": ["eslint-plugin-vue@10.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^7.1.0", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "vue-eslint-parser": "^10.0.0" }, "optionalPeers": ["@stylistic/eslint-plugin", "@typescript-eslint/parser"] }, "sha512-f1J/tcbnrpgC8suPN5AtdJ5MQjuXbSU9pGRSSYAuF3SHoiYCOdEX6O22pLaRyLHXvDcOe+O5ENgc1owQ587agA=="],
|
"eslint-plugin-vue": ["eslint-plugin-vue@10.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^7.1.0", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "vue-eslint-parser": "^10.0.0" }, "optionalPeers": ["@stylistic/eslint-plugin", "@typescript-eslint/parser"] }, "sha512-f1J/tcbnrpgC8suPN5AtdJ5MQjuXbSU9pGRSSYAuF3SHoiYCOdEX6O22pLaRyLHXvDcOe+O5ENgc1owQ587agA=="],
|
||||||
|
|
||||||
"eslint-scope": ["eslint-scope@9.1.1", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw=="],
|
"eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="],
|
||||||
|
|
||||||
"eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
"eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||||
|
|
||||||
"espree": ["espree@11.1.1", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ=="],
|
"espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="],
|
||||||
|
|
||||||
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
|
||||||
|
|
||||||
@@ -718,15 +724,15 @@
|
|||||||
|
|
||||||
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
||||||
|
|
||||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
"flatted": ["flatted@3.4.1", "", {}, "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ=="],
|
||||||
|
|
||||||
"fontaine": ["fontaine@0.8.0", "", { "dependencies": { "@capsizecss/unpack": "^4.0.0", "css-tree": "^3.1.0", "magic-regexp": "^0.10.0", "magic-string": "^0.30.21", "pathe": "^2.0.3", "ufo": "^1.6.1", "unplugin": "^2.3.10" } }, "sha512-eek1GbzOdWIj9FyQH/emqW1aEdfC3lYRCHepzwlFCm5T77fBSRSyNRKE6/antF1/B1M+SfJXVRQTY9GAr7lnDg=="],
|
"fontaine": ["fontaine@0.8.0", "", { "dependencies": { "@capsizecss/unpack": "^4.0.0", "css-tree": "^3.1.0", "magic-regexp": "^0.10.0", "magic-string": "^0.30.21", "pathe": "^2.0.3", "ufo": "^1.6.1", "unplugin": "^2.3.10" } }, "sha512-eek1GbzOdWIj9FyQH/emqW1aEdfC3lYRCHepzwlFCm5T77fBSRSyNRKE6/antF1/B1M+SfJXVRQTY9GAr7lnDg=="],
|
||||||
|
|
||||||
"fontkitten": ["fontkitten@1.0.2", "", { "dependencies": { "tiny-inflate": "^1.0.3" } }, "sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q=="],
|
"fontkitten": ["fontkitten@1.0.3", "", { "dependencies": { "tiny-inflate": "^1.0.3" } }, "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw=="],
|
||||||
|
|
||||||
"fontless": ["fontless@0.2.1", "", { "dependencies": { "consola": "^3.4.2", "css-tree": "^3.1.0", "defu": "^6.1.4", "esbuild": "^0.27.0", "fontaine": "0.8.0", "jiti": "^2.6.1", "lightningcss": "^1.30.2", "magic-string": "^0.30.21", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1", "unifont": "^0.7.4", "unstorage": "^1.17.1" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-mUWZ8w91/mw2KEcZ6gHNoNNmsAq9Wiw2IypIux5lM03nhXm+WSloXGUNuRETNTLqZexMgpt7Aj/v63qqrsWraQ=="],
|
"fontless": ["fontless@0.2.1", "", { "dependencies": { "consola": "^3.4.2", "css-tree": "^3.1.0", "defu": "^6.1.4", "esbuild": "^0.27.0", "fontaine": "0.8.0", "jiti": "^2.6.1", "lightningcss": "^1.30.2", "magic-string": "^0.30.21", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1", "unifont": "^0.7.4", "unstorage": "^1.17.1" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-mUWZ8w91/mw2KEcZ6gHNoNNmsAq9Wiw2IypIux5lM03nhXm+WSloXGUNuRETNTLqZexMgpt7Aj/v63qqrsWraQ=="],
|
||||||
|
|
||||||
"framer-motion": ["framer-motion@12.34.3", "", { "dependencies": { "motion-dom": "^12.34.3", "motion-utils": "^12.29.2", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-v81ecyZKYO/DfpTwHivqkxSUBzvceOpoI+wLfgCgoUIKxlFKEXdg0oR9imxwXumT4SFy8vRk9xzJ5l3/Du/55Q=="],
|
"framer-motion": ["framer-motion@12.35.2", "", { "dependencies": { "motion-dom": "^12.35.2", "motion-utils": "^12.29.2", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-dhfuEMaNo0hc+AEqyHiIfiJRNb9U9UQutE9FoKm5pjf7CMitp9xPEF1iWZihR1q86LBmo6EJ7S8cN8QXEy49AA=="],
|
||||||
|
|
||||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||||
|
|
||||||
@@ -742,7 +748,7 @@
|
|||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||||
|
|
||||||
"h3": ["h3@1.15.5", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg=="],
|
"h3": ["h3@1.15.6", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-oi15ESLW5LRthZ+qPCi5GNasY/gvynSKUQxgiovrY63bPAtG59wtM+LSrlcwvOHAXzGrXVLnI97brbkdPF9WoQ=="],
|
||||||
|
|
||||||
"hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="],
|
"hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="],
|
||||||
|
|
||||||
@@ -804,29 +810,29 @@
|
|||||||
|
|
||||||
"lib0": ["lib0@0.2.117", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0serve": "bin/0serve.js", "0gentesthtml": "bin/gentesthtml.js", "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js" } }, "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw=="],
|
"lib0": ["lib0@0.2.117", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0serve": "bin/0serve.js", "0gentesthtml": "bin/gentesthtml.js", "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js" } }, "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw=="],
|
||||||
|
|
||||||
"lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
|
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
||||||
|
|
||||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
|
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
||||||
|
|
||||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
|
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
||||||
|
|
||||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
|
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
||||||
|
|
||||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
|
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
|
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
|
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
|
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
||||||
|
|
||||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
|
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
||||||
|
|
||||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
|
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
||||||
|
|
||||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
|
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
||||||
|
|
||||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
|
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
||||||
|
|
||||||
"linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="],
|
"linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="],
|
||||||
|
|
||||||
@@ -846,9 +852,9 @@
|
|||||||
|
|
||||||
"markdown-it": ["markdown-it@14.1.1", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA=="],
|
"markdown-it": ["markdown-it@14.1.1", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA=="],
|
||||||
|
|
||||||
"marked": ["marked@17.0.3", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A=="],
|
"marked": ["marked@17.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ=="],
|
||||||
|
|
||||||
"mdn-data": ["mdn-data@2.12.2", "", {}, "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA=="],
|
"mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="],
|
||||||
|
|
||||||
"mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="],
|
"mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="],
|
||||||
|
|
||||||
@@ -862,13 +868,13 @@
|
|||||||
|
|
||||||
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@10.2.3", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg=="],
|
"minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||||
|
|
||||||
"mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
|
"mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
|
||||||
|
|
||||||
"mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="],
|
"mlly": ["mlly@1.8.1", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ=="],
|
||||||
|
|
||||||
"motion-dom": ["motion-dom@12.34.3", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-sYgFe+pR9aIM7o4fhs2aXtOI+oqlUd33N9Yoxcgo1Fv7M20sRkHtCmzE/VRNIcq7uNJ+qio+Xubt1FXH3pQ+eQ=="],
|
"motion-dom": ["motion-dom@12.35.2", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-pWXFMTwvGDbx1Fe9YL5HZebv2NhvGBzRtiNUv58aoK7+XrsuaydQ0JGRKK2r+bTKlwgSWwWxHbP5249Qr/BNpg=="],
|
||||||
|
|
||||||
"motion-utils": ["motion-utils@12.29.2", "", {}, "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A=="],
|
"motion-utils": ["motion-utils@12.29.2", "", {}, "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A=="],
|
||||||
|
|
||||||
@@ -888,7 +894,7 @@
|
|||||||
|
|
||||||
"node-mock-http": ["node-mock-http@1.0.4", "", {}, "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ=="],
|
"node-mock-http": ["node-mock-http@1.0.4", "", {}, "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ=="],
|
||||||
|
|
||||||
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
|
"node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="],
|
||||||
|
|
||||||
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
||||||
|
|
||||||
@@ -944,7 +950,7 @@
|
|||||||
|
|
||||||
"pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
|
"pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
|
||||||
|
|
||||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
|
"postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="],
|
||||||
|
|
||||||
@@ -960,7 +966,7 @@
|
|||||||
|
|
||||||
"prosemirror-dropcursor": ["prosemirror-dropcursor@1.8.2", "", { "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0", "prosemirror-view": "^1.1.0" } }, "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw=="],
|
"prosemirror-dropcursor": ["prosemirror-dropcursor@1.8.2", "", { "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0", "prosemirror-view": "^1.1.0" } }, "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw=="],
|
||||||
|
|
||||||
"prosemirror-gapcursor": ["prosemirror-gapcursor@1.4.0", "", { "dependencies": { "prosemirror-keymap": "^1.0.0", "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", "prosemirror-view": "^1.0.0" } }, "sha512-z00qvurSdCEWUIulij/isHaqu4uLS8r/Fi61IbjdIPJEonQgggbJsLnstW7Lgdk4zQ68/yr6B6bf7sJXowIgdQ=="],
|
"prosemirror-gapcursor": ["prosemirror-gapcursor@1.4.1", "", { "dependencies": { "prosemirror-keymap": "^1.0.0", "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", "prosemirror-view": "^1.0.0" } }, "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw=="],
|
||||||
|
|
||||||
"prosemirror-history": ["prosemirror-history@1.5.0", "", { "dependencies": { "prosemirror-state": "^1.2.2", "prosemirror-transform": "^1.0.0", "prosemirror-view": "^1.31.0", "rope-sequence": "^1.3.0" } }, "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg=="],
|
"prosemirror-history": ["prosemirror-history@1.5.0", "", { "dependencies": { "prosemirror-state": "^1.2.2", "prosemirror-transform": "^1.0.0", "prosemirror-view": "^1.31.0", "rope-sequence": "^1.3.0" } }, "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg=="],
|
||||||
|
|
||||||
@@ -1012,7 +1018,7 @@
|
|||||||
|
|
||||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
||||||
|
|
||||||
"rolldown": ["rolldown@1.0.0-rc.5", "", { "dependencies": { "@oxc-project/types": "=0.114.0", "@rolldown/pluginutils": "1.0.0-rc.5" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.5", "@rolldown/binding-darwin-arm64": "1.0.0-rc.5", "@rolldown/binding-darwin-x64": "1.0.0-rc.5", "@rolldown/binding-freebsd-x64": "1.0.0-rc.5", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.5", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.5", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.5", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.5", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.5", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.5", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.5", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.5", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.5" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-0AdalTs6hNTioaCYIkAa7+xsmHBfU5hCNclZnM/lp7lGGDuUOb6N4BVNtwiomybbencDjq/waKjTImqiGCs5sw=="],
|
"rolldown": ["rolldown@1.0.0-rc.8", "", { "dependencies": { "@oxc-project/types": "=0.115.0", "@rolldown/pluginutils": "1.0.0-rc.8" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.8", "@rolldown/binding-darwin-arm64": "1.0.0-rc.8", "@rolldown/binding-darwin-x64": "1.0.0-rc.8", "@rolldown/binding-freebsd-x64": "1.0.0-rc.8", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.8", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.8", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.8", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.8", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.8", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.8", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.8", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.8", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.8", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.8", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.8" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-RGOL7mz/aoQpy/y+/XS9iePBfeNRDUdozrhCEJxdpJyimW8v6yp4c30q6OviUU5AnUJVLRL9GP//HUs6N3ALrQ=="],
|
||||||
|
|
||||||
"rope-sequence": ["rope-sequence@1.3.4", "", {}, "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="],
|
"rope-sequence": ["rope-sequence@1.3.4", "", {}, "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="],
|
||||||
|
|
||||||
@@ -1074,7 +1080,7 @@
|
|||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
"typescript-eslint": ["typescript-eslint@8.56.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.56.1", "@typescript-eslint/parser": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/utils": "8.56.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ=="],
|
"typescript-eslint": ["typescript-eslint@8.57.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.57.0", "@typescript-eslint/parser": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/utils": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA=="],
|
||||||
|
|
||||||
"uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
|
"uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
|
||||||
|
|
||||||
@@ -1086,11 +1092,11 @@
|
|||||||
|
|
||||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||||
|
|
||||||
"unhead": ["unhead@2.1.7", "", { "dependencies": { "hookable": "^6.0.1" } }, "sha512-LZlyHgDnDieyhpBnkd80pn/kVum0P15nNs4DtPUvRwd98uuS1Xqmlc2Ms48P88HI5nLo3nkqHWg2VOs/RgcOWg=="],
|
"unhead": ["unhead@2.1.12", "", { "dependencies": { "hookable": "^6.0.1" } }, "sha512-iTHdWD9ztTunOErtfUFk6Wr11BxvzumcYJ0CzaSCBUOEtg+DUZ9+gnE99i8QkLFT2q1rZD48BYYGXpOZVDLYkA=="],
|
||||||
|
|
||||||
"unifont": ["unifont@0.7.4", "", { "dependencies": { "css-tree": "^3.1.0", "ofetch": "^1.5.1", "ohash": "^2.0.11" } }, "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg=="],
|
"unifont": ["unifont@0.7.4", "", { "dependencies": { "css-tree": "^3.1.0", "ofetch": "^1.5.1", "ohash": "^2.0.11" } }, "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg=="],
|
||||||
|
|
||||||
"unimport": ["unimport@5.6.0", "", { "dependencies": { "acorn": "^8.15.0", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "pathe": "^2.0.3", "picomatch": "^4.0.3", "pkg-types": "^2.3.0", "scule": "^1.3.0", "strip-literal": "^3.1.0", "tinyglobby": "^0.2.15", "unplugin": "^2.3.11", "unplugin-utils": "^0.3.1" } }, "sha512-8rqAmtJV8o60x46kBAJKtHpJDJWkA2xcBqWKPI14MgUb05o1pnpnCnXSxedUXyeq7p8fR5g3pTo2BaswZ9lD9A=="],
|
"unimport": ["unimport@5.7.0", "", { "dependencies": { "acorn": "^8.16.0", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "pathe": "^2.0.3", "picomatch": "^4.0.3", "pkg-types": "^2.3.0", "scule": "^1.3.0", "strip-literal": "^3.1.0", "tinyglobby": "^0.2.15", "unplugin": "^2.3.11", "unplugin-utils": "^0.3.1" } }, "sha512-njnL6sp8lEA8QQbZrt+52p/g4X0rw3bnGGmUcJnt1jeG8+iiqO779aGz0PirCtydAIVcuTBRlJ52F0u46z309Q=="],
|
||||||
|
|
||||||
"unplugin": ["unplugin@3.0.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg=="],
|
"unplugin": ["unplugin@3.0.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg=="],
|
||||||
|
|
||||||
@@ -1112,7 +1118,7 @@
|
|||||||
|
|
||||||
"vaul-vue": ["vaul-vue@0.4.1", "", { "dependencies": { "@vueuse/core": "^10.8.0", "reka-ui": "^2.0.0", "vue": "^3.4.5" } }, "sha512-A6jOWOZX5yvyo1qMn7IveoWN91mJI5L3BUKsIwkg6qrTGgHs1Sb1JF/vyLJgnbN1rH4OOOxFbtqL9A46bOyGUQ=="],
|
"vaul-vue": ["vaul-vue@0.4.1", "", { "dependencies": { "@vueuse/core": "^10.8.0", "reka-ui": "^2.0.0", "vue": "^3.4.5" } }, "sha512-A6jOWOZX5yvyo1qMn7IveoWN91mJI5L3BUKsIwkg6qrTGgHs1Sb1JF/vyLJgnbN1rH4OOOxFbtqL9A46bOyGUQ=="],
|
||||||
|
|
||||||
"vite": ["vite@8.0.0-beta.15", "", { "dependencies": { "@oxc-project/runtime": "0.114.0", "lightningcss": "^1.31.1", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-rc.5", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.0.0-alpha.31", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-RHX7IvsJlEfjyA1rS7MY0UsmF91etdLAamslHR5lfuO3W/BXRdXm2tRE64ztpSPZbKqB4wAAZ0AwtF6QzfKZLA=="],
|
"vite": ["vite@8.0.0-beta.18", "", { "dependencies": { "@oxc-project/runtime": "0.115.0", "lightningcss": "^1.31.1", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-rc.8", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.0.0-alpha.31", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-azgNbWdsO/WBqHQxwSCy+zd+Fq+37Fix2hn64cQuiUvaaGGSUac7f8RGQhI1aQl9OKbfWblrCFLWs+tln06c2A=="],
|
||||||
|
|
||||||
"vite-dev-rpc": ["vite-dev-rpc@1.1.0", "", { "dependencies": { "birpc": "^2.4.0", "vite-hot-client": "^2.1.0" }, "peerDependencies": { "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" } }, "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A=="],
|
"vite-dev-rpc": ["vite-dev-rpc@1.1.0", "", { "dependencies": { "birpc": "^2.4.0", "vite-hot-client": "^2.1.0" }, "peerDependencies": { "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" } }, "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A=="],
|
||||||
|
|
||||||
@@ -1120,13 +1126,13 @@
|
|||||||
|
|
||||||
"vite-plugin-inspect": ["vite-plugin-inspect@11.3.3", "", { "dependencies": { "ansis": "^4.1.0", "debug": "^4.4.1", "error-stack-parser-es": "^1.0.5", "ohash": "^2.0.11", "open": "^10.2.0", "perfect-debounce": "^2.0.0", "sirv": "^3.0.1", "unplugin-utils": "^0.3.0", "vite-dev-rpc": "^1.1.0" }, "peerDependencies": { "vite": "^6.0.0 || ^7.0.0-0" } }, "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA=="],
|
"vite-plugin-inspect": ["vite-plugin-inspect@11.3.3", "", { "dependencies": { "ansis": "^4.1.0", "debug": "^4.4.1", "error-stack-parser-es": "^1.0.5", "ohash": "^2.0.11", "open": "^10.2.0", "perfect-debounce": "^2.0.0", "sirv": "^3.0.1", "unplugin-utils": "^0.3.0", "vite-dev-rpc": "^1.1.0" }, "peerDependencies": { "vite": "^6.0.0 || ^7.0.0-0" } }, "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA=="],
|
||||||
|
|
||||||
"vite-plugin-vue-devtools": ["vite-plugin-vue-devtools@8.0.6", "", { "dependencies": { "@vue/devtools-core": "^8.0.6", "@vue/devtools-kit": "^8.0.6", "@vue/devtools-shared": "^8.0.6", "sirv": "^3.0.2", "vite-plugin-inspect": "^11.3.3", "vite-plugin-vue-inspector": "^5.3.2" }, "peerDependencies": { "vite": "^6.0.0 || ^7.0.0-0" } }, "sha512-IiTCIJDb1ZliOT8fPbYXllyfgARzz1+R1r8RN9ScGIDzAB6o8bDME1a9JjrfdSJibL7i8DIPQH+pGv0U7haBeA=="],
|
"vite-plugin-vue-devtools": ["vite-plugin-vue-devtools@8.0.7", "", { "dependencies": { "@vue/devtools-core": "^8.0.7", "@vue/devtools-kit": "^8.0.7", "@vue/devtools-shared": "^8.0.7", "sirv": "^3.0.2", "vite-plugin-inspect": "^11.3.3", "vite-plugin-vue-inspector": "^5.3.2" }, "peerDependencies": { "vite": "^6.0.0 || ^7.0.0-0 || ^8.0.0-0" } }, "sha512-BWj/ykGpqVAJVdPyHmSTUm44buz3jPv+6jnvuFdQSRH0kAgP1cEIE4doHiFyqHXOmuB5EQVR/nh2g9YRiRNs9g=="],
|
||||||
|
|
||||||
"vite-plugin-vue-inspector": ["vite-plugin-vue-inspector@5.3.2", "", { "dependencies": { "@babel/core": "^7.23.0", "@babel/plugin-proposal-decorators": "^7.23.0", "@babel/plugin-syntax-import-attributes": "^7.22.5", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-transform-typescript": "^7.22.15", "@vue/babel-plugin-jsx": "^1.1.5", "@vue/compiler-dom": "^3.3.4", "kolorist": "^1.8.0", "magic-string": "^0.30.4" }, "peerDependencies": { "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" } }, "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q=="],
|
"vite-plugin-vue-inspector": ["vite-plugin-vue-inspector@5.3.2", "", { "dependencies": { "@babel/core": "^7.23.0", "@babel/plugin-proposal-decorators": "^7.23.0", "@babel/plugin-syntax-import-attributes": "^7.22.5", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-transform-typescript": "^7.22.15", "@vue/babel-plugin-jsx": "^1.1.5", "@vue/compiler-dom": "^3.3.4", "kolorist": "^1.8.0", "magic-string": "^0.30.4" }, "peerDependencies": { "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" } }, "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q=="],
|
||||||
|
|
||||||
"vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="],
|
"vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="],
|
||||||
|
|
||||||
"vue": ["vue@3.6.0-beta.6", "", { "dependencies": { "@vue/compiler-dom": "3.6.0-beta.6", "@vue/compiler-sfc": "3.6.0-beta.6", "@vue/runtime-dom": "3.6.0-beta.6", "@vue/runtime-vapor": "3.6.0-beta.6", "@vue/server-renderer": "3.6.0-beta.6", "@vue/shared": "3.6.0-beta.6" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-xtAUa5mT3x8un9Ck8bkuvZYU9Bx0TTjlsrbJe5p/51zcz00+on3QuL0rODYlp+W7QIpGBgZZo/KFIK8SLZoSIQ=="],
|
"vue": ["vue@3.6.0-beta.7", "", { "dependencies": { "@vue/compiler-dom": "3.6.0-beta.7", "@vue/compiler-sfc": "3.6.0-beta.7", "@vue/runtime-dom": "3.6.0-beta.7", "@vue/runtime-vapor": "3.6.0-beta.7", "@vue/server-renderer": "3.6.0-beta.7", "@vue/shared": "3.6.0-beta.7" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-SlNdNG+c37xycRFIJ/KB9CmpZmWwKovbDTNl00ck0+ZSNZSgb+n6DKLuXtVvGZImNPu6jj+zzaM1gqNB5NeC6Q=="],
|
||||||
|
|
||||||
"vue-chartjs": ["vue-chartjs@5.3.3", "", { "peerDependencies": { "chart.js": "^4.1.1", "vue": "^3.0.0-0 || ^2.7.0" } }, "sha512-jqxtL8KZ6YJ5NTv6XzrzLS7osyegOi28UGNZW0h9OkDL7Sh1396ht4Dorh04aKrl2LiSalQ84WtqiG0RIJb0tA=="],
|
"vue-chartjs": ["vue-chartjs@5.3.3", "", { "peerDependencies": { "chart.js": "^4.1.1", "vue": "^3.0.0-0 || ^2.7.0" } }, "sha512-jqxtL8KZ6YJ5NTv6XzrzLS7osyegOi28UGNZW0h9OkDL7Sh1396ht4Dorh04aKrl2LiSalQ84WtqiG0RIJb0tA=="],
|
||||||
|
|
||||||
@@ -1136,7 +1142,7 @@
|
|||||||
|
|
||||||
"vue-eslint-parser": ["vue-eslint-parser@10.4.0", "", { "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0 || ^9.0.0", "eslint-visitor-keys": "^4.2.0 || ^5.0.0", "espree": "^10.3.0 || ^11.0.0", "esquery": "^1.6.0", "semver": "^7.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" } }, "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg=="],
|
"vue-eslint-parser": ["vue-eslint-parser@10.4.0", "", { "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0 || ^9.0.0", "eslint-visitor-keys": "^4.2.0 || ^5.0.0", "espree": "^10.3.0 || ^11.0.0", "esquery": "^1.6.0", "semver": "^7.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" } }, "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg=="],
|
||||||
|
|
||||||
"vue-i18n": ["vue-i18n@11.2.8", "", { "dependencies": { "@intlify/core-base": "11.2.8", "@intlify/shared": "11.2.8", "@vue/devtools-api": "^6.5.0" }, "peerDependencies": { "vue": "^3.0.0" } }, "sha512-vJ123v/PXCZntd6Qj5Jumy7UBmIuE92VrtdX+AXr+1WzdBHojiBxnAxdfctUFL+/JIN+VQH4BhsfTtiGsvVObg=="],
|
"vue-i18n": ["vue-i18n@11.3.0", "", { "dependencies": { "@intlify/core-base": "11.3.0", "@intlify/devtools-types": "11.3.0", "@intlify/shared": "11.3.0", "@vue/devtools-api": "^6.5.0" }, "peerDependencies": { "vue": "^3.0.0" } }, "sha512-1J+xDfDJTLhDxElkd3+XUhT7FYSZd2b8pa7IRKGxhWH/8yt6PTvi3xmWhGwhYT5EaXdatui11pF2R6tL73/zPA=="],
|
||||||
|
|
||||||
"vue-router": ["vue-router@5.0.3", "", { "dependencies": { "@babel/generator": "^7.28.6", "@vue-macros/common": "^3.1.1", "@vue/devtools-api": "^8.0.6", "ast-walker-scope": "^0.8.3", "chokidar": "^5.0.0", "json5": "^2.2.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "muggle-string": "^0.4.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "scule": "^1.3.0", "tinyglobby": "^0.2.15", "unplugin": "^3.0.0", "unplugin-utils": "^0.3.1", "yaml": "^2.8.2" }, "peerDependencies": { "@pinia/colada": ">=0.21.2", "@vue/compiler-sfc": "^3.5.17", "pinia": "^3.0.4", "vue": "^3.5.0" }, "optionalPeers": ["@pinia/colada", "@vue/compiler-sfc", "pinia"] }, "sha512-nG1c7aAFac7NYj8Hluo68WyWfc41xkEjaR0ViLHCa3oDvTQ/nIuLJlXJX1NUPw/DXzx/8+OKMng045HHQKQKWw=="],
|
"vue-router": ["vue-router@5.0.3", "", { "dependencies": { "@babel/generator": "^7.28.6", "@vue-macros/common": "^3.1.1", "@vue/devtools-api": "^8.0.6", "ast-walker-scope": "^0.8.3", "chokidar": "^5.0.0", "json5": "^2.2.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "muggle-string": "^0.4.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "scule": "^1.3.0", "tinyglobby": "^0.2.15", "unplugin": "^3.0.0", "unplugin-utils": "^0.3.1", "yaml": "^2.8.2" }, "peerDependencies": { "@pinia/colada": ">=0.21.2", "@vue/compiler-sfc": "^3.5.17", "pinia": "^3.0.4", "vue": "^3.5.0" }, "optionalPeers": ["@pinia/colada", "@vue/compiler-sfc", "pinia"] }, "sha512-nG1c7aAFac7NYj8Hluo68WyWfc41xkEjaR0ViLHCa3oDvTQ/nIuLJlXJX1NUPw/DXzx/8+OKMng045HHQKQKWw=="],
|
||||||
|
|
||||||
@@ -1184,6 +1190,8 @@
|
|||||||
|
|
||||||
"@nuxtjs/color-mode/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
"@nuxtjs/color-mode/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||||
@@ -1202,8 +1210,6 @@
|
|||||||
|
|
||||||
"@vue/devtools-api/@vue/devtools-kit": ["@vue/devtools-kit@7.7.9", "", { "dependencies": { "@vue/devtools-shared": "^7.7.9", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA=="],
|
"@vue/devtools-api/@vue/devtools-kit": ["@vue/devtools-kit@7.7.9", "", { "dependencies": { "@vue/devtools-shared": "^7.7.9", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA=="],
|
||||||
|
|
||||||
"@vue/devtools-core/nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
|
|
||||||
|
|
||||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
|
|
||||||
"c12/rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="],
|
"c12/rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="],
|
||||||
@@ -1228,7 +1234,7 @@
|
|||||||
|
|
||||||
"nypm/citty": ["citty@0.2.1", "", {}, "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg=="],
|
"nypm/citty": ["citty@0.2.1", "", {}, "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg=="],
|
||||||
|
|
||||||
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.5", "", {}, "sha512-RxlLX/DPoarZ9PtxVrQgZhPoor987YtKQqCo5zkjX+0S0yLJ7Vv515Wk6+xtTL67VONKJKxETWZwuZjss2idYw=="],
|
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.8", "", {}, "sha512-wzJwL82/arVfeSP3BLr1oTy40XddjtEdrdgtJ4lLRBu06mP3q/8HGM6K0JRlQuTA3XB0pNJx2so/nmpY4xyOew=="],
|
||||||
|
|
||||||
"strip-literal/js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
|
"strip-literal/js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
|
||||||
|
|
||||||
@@ -1252,7 +1258,7 @@
|
|||||||
|
|
||||||
"vue-i18n/@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="],
|
"vue-i18n/@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="],
|
||||||
|
|
||||||
"vue-router/@vue/devtools-api": ["@vue/devtools-api@8.0.6", "", { "dependencies": { "@vue/devtools-kit": "^8.0.6" } }, "sha512-+lGBI+WTvJmnU2FZqHhEB8J1DXcvNlDeEalz77iYgOdY1jTj1ipSBaKj3sRhYcy+kqA8v/BSuvOz1XJucfQmUA=="],
|
"vue-router/@vue/devtools-api": ["@vue/devtools-api@8.0.7", "", { "dependencies": { "@vue/devtools-kit": "^8.0.7" } }, "sha512-tc1TXAxclsn55JblLkFVcIRG7MeSJC4fWsPjfM7qu/IcmPUYnQ5Q8vzWwBpyDY24ZjmZTUCCwjRSNbx58IhlAA=="],
|
||||||
|
|
||||||
"@nuxtjs/color-mode/@nuxt/kit/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
"@nuxtjs/color-mode/@nuxt/kit/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||||
|
|
||||||
@@ -1264,6 +1270,28 @@
|
|||||||
|
|
||||||
"@nuxtjs/color-mode/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"@nuxtjs/color-mode/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
|
||||||
|
|
||||||
"@vue/devtools-api/@vue/devtools-kit/@vue/devtools-shared": ["@vue/devtools-shared@7.7.9", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA=="],
|
"@vue/devtools-api/@vue/devtools-kit/@vue/devtools-shared": ["@vue/devtools-shared@7.7.9", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA=="],
|
||||||
|
|
||||||
"@vue/devtools-api/@vue/devtools-kit/perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
"@vue/devtools-api/@vue/devtools-kit/perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
||||||
|
|||||||
16
bo/components.d.ts
vendored
16
bo/components.d.ts
vendored
@@ -11,13 +11,26 @@ export {}
|
|||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
Cart1: typeof import('./src/components/customer/Cart1.vue')['default']
|
||||||
|
CompanyAccountView: typeof import('./src/components/customer/CompanyAccountView.vue')['default']
|
||||||
Cs_PrivacyPolicyView: typeof import('./src/components/terms/cs_PrivacyPolicyView.vue')['default']
|
Cs_PrivacyPolicyView: typeof import('./src/components/terms/cs_PrivacyPolicyView.vue')['default']
|
||||||
Cs_TermsAndConditionsView: typeof import('./src/components/terms/cs_TermsAndConditionsView.vue')['default']
|
Cs_TermsAndConditionsView: typeof import('./src/components/terms/cs_TermsAndConditionsView.vue')['default']
|
||||||
En_PrivacyPolicyView: typeof import('./src/components/terms/en_PrivacyPolicyView.vue')['default']
|
En_PrivacyPolicyView: typeof import('./src/components/terms/en_PrivacyPolicyView.vue')['default']
|
||||||
En_TermsAndConditionsView: typeof import('./src/components/terms/en_TermsAndConditionsView.vue')['default']
|
En_TermsAndConditionsView: typeof import('./src/components/terms/en_TermsAndConditionsView.vue')['default']
|
||||||
LangSwitch: typeof import('./src/components/inner/langSwitch.vue')['default']
|
LangSwitch: typeof import('./src/components/inner/langSwitch.vue')['default']
|
||||||
|
PageAccount: typeof import('./src/components/customer/PageAccount.vue')['default']
|
||||||
|
PageAddresses: typeof import('./src/components/customer/PageAddresses.vue')['default']
|
||||||
|
PageCart: typeof import('./src/components/customer/PageCart.vue')['default']
|
||||||
|
PageCreateAccount: typeof import('./src/components/customer/PageCreateAccount.vue')['default']
|
||||||
|
PageCustomerData: typeof import('./src/components/customer/PageCustomerData.vue')['default']
|
||||||
|
PageProductCardFull: typeof import('./src/components/customer/PageProductCardFull.vue')['default']
|
||||||
|
PageProductsList: typeof import('./src/components/customer/PageProductsList.vue')['default']
|
||||||
Pl_PrivacyPolicyView: typeof import('./src/components/terms/pl_PrivacyPolicyView.vue')['default']
|
Pl_PrivacyPolicyView: typeof import('./src/components/terms/pl_PrivacyPolicyView.vue')['default']
|
||||||
Pl_TermsAndConditionsView: typeof import('./src/components/terms/pl_TermsAndConditionsView.vue')['default']
|
Pl_TermsAndConditionsView: typeof import('./src/components/terms/pl_TermsAndConditionsView.vue')['default']
|
||||||
|
ProductCustomization: typeof import('./src/components/customer/components/ProductCustomization.vue')['default']
|
||||||
|
ProductDetailView: typeof import('./src/components/admin/ProductDetailView.vue')['default']
|
||||||
|
ProductsView: typeof import('./src/components/admin/ProductsView.vue')['default']
|
||||||
|
ProductVariants: typeof import('./src/components/customer/components/ProductVariants.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
ThemeSwitch: typeof import('./src/components/inner/themeSwitch.vue')['default']
|
ThemeSwitch: typeof import('./src/components/inner/themeSwitch.vue')['default']
|
||||||
@@ -27,12 +40,13 @@ declare module 'vue' {
|
|||||||
UButton: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Button.vue')['default']
|
UButton: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Button.vue')['default']
|
||||||
UCard: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Card.vue')['default']
|
UCard: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Card.vue')['default']
|
||||||
UCheckbox: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Checkbox.vue')['default']
|
UCheckbox: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Checkbox.vue')['default']
|
||||||
UContainer: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Container.vue')['default']
|
|
||||||
UDrawer: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Drawer.vue')['default']
|
UDrawer: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Drawer.vue')['default']
|
||||||
UForm: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Form.vue')['default']
|
UForm: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Form.vue')['default']
|
||||||
UFormField: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/FormField.vue')['default']
|
UFormField: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/FormField.vue')['default']
|
||||||
UIcon: typeof import('./node_modules/@nuxt/ui/dist/runtime/vue/components/Icon.vue')['default']
|
UIcon: typeof import('./node_modules/@nuxt/ui/dist/runtime/vue/components/Icon.vue')['default']
|
||||||
UInput: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Input.vue')['default']
|
UInput: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Input.vue')['default']
|
||||||
|
UInputNumber: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/InputNumber.vue')['default']
|
||||||
|
UModal: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Modal.vue')['default']
|
||||||
UPagination: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Pagination.vue')['default']
|
UPagination: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Pagination.vue')['default']
|
||||||
USelect: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Select.vue')['default']
|
USelect: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Select.vue')['default']
|
||||||
USelectMenu: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/SelectMenu.vue')['default']
|
USelectMenu: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/SelectMenu.vue')['default']
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ import type { NuxtUIOptions } from '@nuxt/ui/unplugin'
|
|||||||
|
|
||||||
export const uiOptions: NuxtUIOptions = {
|
export const uiOptions: NuxtUIOptions = {
|
||||||
ui: {
|
ui: {
|
||||||
colors: {
|
|
||||||
primary: 'blue',
|
|
||||||
neutral: 'zink',
|
|
||||||
},
|
|
||||||
pagination: {
|
pagination: {
|
||||||
slots: {
|
slots: {
|
||||||
root: '',
|
root: '',
|
||||||
@@ -22,6 +18,13 @@ export const uiOptions: NuxtUIOptions = {
|
|||||||
error: 'text-red-600!'
|
error: 'text-red-600!'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
inputNumber: {
|
||||||
|
slots: {
|
||||||
|
base: 'text-(--black) dark:text-white border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0! pt-2 px-1! w-auto!',
|
||||||
|
increment: 'border-0! pe-0! ps-0!',
|
||||||
|
decrement: 'border-0! pe-0! ps-0!'
|
||||||
|
},
|
||||||
|
},
|
||||||
select: {
|
select: {
|
||||||
slots: {
|
slots: {
|
||||||
base: 'w-full! cursor-pointer border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0!',
|
base: 'w-full! cursor-pointer border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0!',
|
||||||
@@ -42,6 +45,19 @@ export const uiOptions: NuxtUIOptions = {
|
|||||||
itemLeadingIcon: 'text-(--black)! dark:text-white!'
|
itemLeadingIcon: 'text-(--black)! dark:text-white!'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
slots: {
|
||||||
|
base: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0! bg-(--second-light) dark:bg-(--main-dark)',
|
||||||
|
tr: 'border-b! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0! text-(--black)! dark:text-white!',
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
modal: {
|
||||||
|
slots: {
|
||||||
|
content: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0! bg-(--second-light) dark:bg-(--main-dark)',
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,6 @@ body {
|
|||||||
|
|
||||||
.container{
|
.container{
|
||||||
max-width: 2100px;
|
max-width: 2100px;
|
||||||
margin: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
@@ -22,14 +21,16 @@ body {
|
|||||||
--black: #1A1A1A;
|
--black: #1A1A1A;
|
||||||
|
|
||||||
/* gray */
|
/* gray */
|
||||||
--gray: #6B6B6B;
|
--gray: #E5E7EB;
|
||||||
--gray-dark: #A3A3A3;
|
--gray-dark: #6B7280;
|
||||||
|
|
||||||
/* borders */
|
/* borders */
|
||||||
--border-light: #E8E7E0;
|
--border-light: #E8E7E0;
|
||||||
--border-dark: #3F3E3D;
|
--border-dark: #3F3E3D;
|
||||||
|
|
||||||
/* text */
|
/* text */
|
||||||
|
--accent-blue-dark: #3B82F6;
|
||||||
|
--accent-blue-light:#2563EB;
|
||||||
--text-dark: #FFFEFB;
|
--text-dark: #FFFEFB;
|
||||||
|
|
||||||
/* placeholder */
|
/* placeholder */
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const authStore = useAuthStore()
|
|||||||
<template>
|
<template>
|
||||||
<header
|
<header
|
||||||
class="fixed top-0 left-0 right-0 z-50 bg-white/80 dark:bg-(--black) backdrop-blur-md border-b border-(--border-light) dark:border-(--border-dark)">
|
class="fixed top-0 left-0 right-0 z-50 bg-white/80 dark:bg-(--black) backdrop-blur-md border-b border-(--border-light) dark:border-(--border-dark)">
|
||||||
<div class="container px-4 sm:px-6 lg:px-8">
|
<div class="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-14">
|
<div class="flex items-center justify-between h-14">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<RouterLink :to="{ name: 'home' }" class="flex items-center gap-2">
|
<RouterLink :to="{ name: 'home' }" class="flex items-center gap-2">
|
||||||
@@ -19,6 +19,27 @@ const authStore = useAuthStore()
|
|||||||
<span class="font-semibold text-gray-900 dark:text-white">TimeTracker</span>
|
<span class="font-semibold text-gray-900 dark:text-white">TimeTracker</span>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
<!-- Right Side Actions -->
|
<!-- Right Side Actions -->
|
||||||
|
<RouterLink :to="{ name: 'product-detail' }">
|
||||||
|
product detail
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink :to="{ name: 'product-card-full' }">
|
||||||
|
ProductCardFull
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink :to="{ name: 'addresses' }">
|
||||||
|
Addresses
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink :to="{ name: 'customer-data' }">
|
||||||
|
Customer Data
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink :to="{ name: 'cart' }">
|
||||||
|
Cart
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink :to="{ name: 'cart1' }">
|
||||||
|
Cart1
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink :to="{ name: 'products-list' }">
|
||||||
|
Products List
|
||||||
|
</RouterLink>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<!-- Language Switcher -->
|
<!-- Language Switcher -->
|
||||||
<LangSwitch />
|
<LangSwitch />
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ const authStore = useAuthStore()
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header
|
<header
|
||||||
class="fixed top-0 left-0 right-0 z-50 bg-white/80 dark:bg-(--black) backdrop-blur-md border-b border-(--border-light) dark:border-(--border-dark)">
|
class="fixed top-0 left-0 right-0 z-50 bg-(--main-light)/80 dark:bg-(--black) backdrop-blur-md border-b border-(--border-light) dark:border-(--border-dark)">
|
||||||
<div class="container px-4 sm:px-6 lg:px-8">
|
<div class="container px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-14">
|
<div class="flex items-center justify-between h-14">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<RouterLink :to="{ name: 'home' }" class="flex items-center gap-2">
|
<RouterLink :to="{ name: 'home' }" class="flex items-center gap-2">
|
||||||
<div class="w-8 h-8 rounded-lg bg-primary text-white flex items-center justify-center">
|
<div class="w-8 h-8 rounded-lg bg-primary text-white flex items-center justify-center">
|
||||||
<UIcon name="i-heroicons-clock" class="w-5 h-5" />
|
<UIcon name="carbon:ibm-webmethods-b2b-integration" class="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<span class="font-semibold text-gray-900 dark:text-white">TimeTracker</span>
|
<span class="font-semibold text-gray-900 dark:text-white">B2B</span>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
<!-- Right Side Actions -->
|
<!-- Right Side Actions -->
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
|||||||
221
bo/src/components/admin/ProductDetailView.vue
Normal file
221
bo/src/components/admin/ProductDetailView.vue
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container my-10 mx-auto ">
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-between gap-4 mb-6 bg-(--second-light) dark:bg-(--main-dark) border border-(--border-light) dark:border-(--border-dark) p-4 rounded-md">
|
||||||
|
<div class="flex items-end gap-3">
|
||||||
|
<USelect v-model="selectedLanguage" :items="availableLangs" variant="outline" class="w-40!" valueKey="iso_code">
|
||||||
|
<template #default="{ modelValue }">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-md">{{availableLangs.find(x => x.iso_code == modelValue)?.flag}}</span>
|
||||||
|
<span class="font-medium dark:text-white text-black">{{availableLangs.find(x => x.iso_code ==
|
||||||
|
modelValue)?.name}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #item-leading="{ item }">
|
||||||
|
<div class="flex items-center rounded-md cursor-pointer transition-colors">
|
||||||
|
<span class="text-md">{{ item.flag }}</span>
|
||||||
|
<span class="ml-2 dark:text-white text-black font-medium">{{ item.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</USelect>
|
||||||
|
</div>
|
||||||
|
<UButton @click="translateToSelectedLanguage" color="primary" :loading="translating"
|
||||||
|
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) px-12!">
|
||||||
|
Translate
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="translating" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
||||||
|
<div class="flex flex-col items-center gap-4 p-8 bg-(--main-light) dark:bg-(--main-dark) rounded-lg shadow-xl">
|
||||||
|
<UIcon name="svg-spinners:ring-resize" class="text-4xl text-primary" />
|
||||||
|
<p class="text-lg font-medium dark:text-white text-black">Translating...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-start gap-30">
|
||||||
|
<p class="p-80 bg-(--second-light)">img</p>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<p class="text-[25px] font-bold text-black dark:text-white">
|
||||||
|
{{ productStore.productDescription.name }}
|
||||||
|
</p>
|
||||||
|
<p v-html="productStore.productDescription.description_short" class="text-black dark:text-white"></p>
|
||||||
|
<div class="space-y-[10px]">
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<UIcon name="lets-icons:done-ring-round-fill" class="text-[20px] text-green-600" />
|
||||||
|
<p class="text-[16px] font-bold text-(--accent-blue-light) dark:text-(--accent-blue-dark)">
|
||||||
|
{{ productStore.productDescription.available_now }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<UIcon name="marketeq:car-shipping" class="text-[25px] text-green-600" />
|
||||||
|
<p class="text-[18px] font-bold text-black dark:text-white">
|
||||||
|
{{ productStore.productDescription.delivery_in_stock }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-16">
|
||||||
|
<div class="flex gap-4 my-6">
|
||||||
|
<UButton @click="activeTab = 'description'"
|
||||||
|
:class="['cursor-pointer', activeTab === 'description' ? 'bg-blue-500 text-white' : '']" color="neutral"
|
||||||
|
variant="outline">
|
||||||
|
<p class="dark:text-white">Description</p>
|
||||||
|
</UButton>
|
||||||
|
|
||||||
|
<UButton @click="activeTab = 'usage'"
|
||||||
|
:class="['cursor-pointer', activeTab === 'usage' ? 'bg-blue-500 text-white' : '']" color="neutral"
|
||||||
|
variant="outline">
|
||||||
|
<p class="dark:text-white">Usage</p>
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="activeTab === 'usage'"
|
||||||
|
class="px-8 py-4 border border-(--border-light) dark:border-(--border-dark) rounded-md bg-(--second-light) dark:bg-(--main-dark)">
|
||||||
|
|
||||||
|
<div class="flex justify-end items-center gap-3 mb-4">
|
||||||
|
<UButton v-if="!isEditing" @click="enableEdit"
|
||||||
|
class="flex items-center gap-2 m-2 cursor-pointer bg-(--accent-blue-light)! dark:bg-(--accent-blue-dark)!">
|
||||||
|
<p class="text-white">Change Text</p>
|
||||||
|
<UIcon name="material-symbols-light:stylus-note-sharp" class="text-[30px] text-white!" />
|
||||||
|
</UButton>
|
||||||
|
<UButton v-if="isEditing" @click="saveText" color="neutral" variant="outline" class="p-2.5 cursor-pointer">
|
||||||
|
<p class="dark:text-white text-black">Save the edited text</p>
|
||||||
|
</UButton>
|
||||||
|
<UButton v-if="isEditing" @click="cancelEdit" color="neutral" variant="outline" class="p-2.5 cursor-pointer">
|
||||||
|
Cancel
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
<p ref="usageRef" v-html="productStore.productDescription.usage"
|
||||||
|
class="flex flex-col justify-center w-full text-start dark:text-white! text-black!"></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="activeTab === 'description'"
|
||||||
|
class="px-8 py-4 border border-(--border-light) dark:border-(--border-dark) rounded-md bg-(--second-light) dark:bg-(--main-dark)">
|
||||||
|
<div class="flex items-center justify-end gap-3 mb-4">
|
||||||
|
<UButton v-if="!descriptionEdit.isEditing.value" @click="enableDescriptionEdit"
|
||||||
|
class="flex items-center gap-2 m-2 cursor-pointer bg-(--accent-blue-light)! dark:bg-(--accent-blue-dark)!">
|
||||||
|
<p class="text-white">Change Text</p>
|
||||||
|
<UIcon name="material-symbols-light:stylus-note-sharp" class="text-[30px] text-white!" />
|
||||||
|
</UButton>
|
||||||
|
<UButton v-if="descriptionEdit.isEditing.value" @click="saveDescription" color="neutral" variant="outline" class="p-2.5 cursor-pointer">
|
||||||
|
<p class="dark:text-white text-black ">Save the edited text</p>
|
||||||
|
</UButton>
|
||||||
|
<UButton v-if="descriptionEdit.isEditing.value" @click="cancelDescriptionEdit" color="neutral" variant="outline" class="p-2.5 cursor-pointer">Cancel</UButton>
|
||||||
|
</div>
|
||||||
|
<div ref="descriptionRef" v-html="productStore.productDescription.description"
|
||||||
|
class="flex flex-col justify-center dark:text-white text-black">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useProductStore } from '@/stores/product'
|
||||||
|
import { useEditable } from '@/composable/useConteditable'
|
||||||
|
import { langs } from '@/router/langs'
|
||||||
|
import type { Language } from '@/types'
|
||||||
|
|
||||||
|
const activeTab = ref('description')
|
||||||
|
const productStore = useProductStore()
|
||||||
|
const translating = ref(false)
|
||||||
|
|
||||||
|
// const availableLangs = computed(() => {
|
||||||
|
// return langs.filter((l: Language) => ['cs', 'pl', 'der'].includes(l.iso_code))
|
||||||
|
// })
|
||||||
|
|
||||||
|
const isEditing = ref(false)
|
||||||
|
|
||||||
|
const availableLangs = computed(() => langs)
|
||||||
|
|
||||||
|
const selectedLanguage = ref('pl')
|
||||||
|
|
||||||
|
const currentLangId = ref(2)
|
||||||
|
|
||||||
|
const fetchForLanguage = async (langCode: string) => {
|
||||||
|
const lang = langs.find((l: Language) => l.iso_code === langCode)
|
||||||
|
if (lang) {
|
||||||
|
await productStore.getProductDescription(lang.id)
|
||||||
|
currentLangId.value = lang.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateToSelectedLanguage = async () => {
|
||||||
|
const targetLang = langs.find((l: Language) => l.iso_code === selectedLanguage.value)
|
||||||
|
if (targetLang && currentLangId.value) {
|
||||||
|
translating.value = true
|
||||||
|
try {
|
||||||
|
await productStore.translateProductDescription(currentLangId.value, targetLang.id)
|
||||||
|
currentLangId.value = targetLang.id
|
||||||
|
} finally {
|
||||||
|
translating.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await fetchForLanguage(selectedLanguage.value)
|
||||||
|
const descriptionRef = ref<HTMLElement | null>(null)
|
||||||
|
const usageRef = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
|
const descriptionEdit = useEditable(descriptionRef)
|
||||||
|
const usageEdit = useEditable(usageRef)
|
||||||
|
|
||||||
|
const originalDescription = ref('')
|
||||||
|
const originalUsage = ref('')
|
||||||
|
|
||||||
|
const saveDescription = async () => {
|
||||||
|
descriptionEdit.disableEdit()
|
||||||
|
await productStore.saveProductDescription()
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelDescriptionEdit = () => {
|
||||||
|
if (descriptionRef.value) {
|
||||||
|
descriptionRef.value.innerHTML = originalDescription.value
|
||||||
|
}
|
||||||
|
descriptionEdit.disableEdit()
|
||||||
|
}
|
||||||
|
|
||||||
|
const enableDescriptionEdit = () => {
|
||||||
|
if (descriptionRef.value) {
|
||||||
|
originalDescription.value = descriptionRef.value.innerHTML
|
||||||
|
}
|
||||||
|
descriptionEdit.enableEdit()
|
||||||
|
}
|
||||||
|
|
||||||
|
const enableEdit = () => {
|
||||||
|
if (usageRef.value) {
|
||||||
|
originalUsage.value = usageRef.value.innerHTML
|
||||||
|
}
|
||||||
|
isEditing.value = true
|
||||||
|
usageEdit.enableEdit()
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveText = () => {
|
||||||
|
usageEdit.disableEdit()
|
||||||
|
isEditing.value = false
|
||||||
|
productStore.saveProductDescription()
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelEdit = () => {
|
||||||
|
if (usageRef.value) {
|
||||||
|
usageRef.value.innerHTML = originalUsage.value
|
||||||
|
}
|
||||||
|
usageEdit.disableEdit()
|
||||||
|
isEditing.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.images {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 70px;
|
||||||
|
margin: 20px 0 20px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
257
bo/src/components/admin/ProductsView.vue
Normal file
257
bo/src/components/admin/ProductsView.vue
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useAuthStore } from '@/stores/auth'
|
||||||
|
import { useProductStore, type Product } from '@/stores/product'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import type { TableColumn } from '@nuxt/ui'
|
||||||
|
import { h } from 'vue'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
const productStore = useProductStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const searchName = ref('')
|
||||||
|
const searchCode = ref('')
|
||||||
|
const priceFromFilter = ref<number | null>(null)
|
||||||
|
const priceToFilter = ref<number | null>(null)
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
const page = ref(1)
|
||||||
|
const pageSize = 5
|
||||||
|
|
||||||
|
// Fetch products on mount
|
||||||
|
onMounted(() => {
|
||||||
|
productStore.getProductDescription()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Filtered products
|
||||||
|
// const filteredProducts = computed(() => {
|
||||||
|
// console.log(productStore.products);
|
||||||
|
|
||||||
|
// return productStore.products.filter(product => {
|
||||||
|
// const matchesName = product.name.toLowerCase().includes(searchName.value.toLowerCase())
|
||||||
|
// const matchesCode = product.code.toLowerCase().includes(searchCode.value.toLowerCase())
|
||||||
|
// const matchesPriceFrom = priceFromFilter.value === null || product.priceFrom >= priceFromFilter.value
|
||||||
|
// const matchesPriceTo = priceToFilter.value === null || product.priceTo <= priceToFilter.value
|
||||||
|
|
||||||
|
// return matchesName && matchesCode && matchesPriceFrom && matchesPriceTo
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
|
// const totalItems = computed(() => filteredProducts.value.length)
|
||||||
|
|
||||||
|
// const paginatedProducts = computed(() => {
|
||||||
|
// const start = (page.value - 1) * pageSize
|
||||||
|
// const end = start + pageSize
|
||||||
|
// return filteredProducts.value.slice(start, end)
|
||||||
|
// })
|
||||||
|
|
||||||
|
// Reset page when filters change
|
||||||
|
function resetPage() {
|
||||||
|
page.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigate to product detail
|
||||||
|
function goToProduct(product: Product) {
|
||||||
|
router.push({ name: 'product-detail', params: { id: product.id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table columns
|
||||||
|
const columns = computed<TableColumn<Product>[]>(() => [
|
||||||
|
{
|
||||||
|
accessorKey: 'image',
|
||||||
|
header: () => h('div', { class: 'text-center' }, t('products.image')),
|
||||||
|
cell: ({ row }) => h('img', {
|
||||||
|
src: row.getValue('image'),
|
||||||
|
alt: 'Product',
|
||||||
|
class: 'w-12 h-12 object-cover rounded'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'name',
|
||||||
|
header: t('products.product_name'),
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const product = row.original
|
||||||
|
return h('button', {
|
||||||
|
class: 'text-primary hover:underline font-medium text-left',
|
||||||
|
onClick: (e: Event) => { e.stopPropagation(); goToProduct(product) }
|
||||||
|
}, product.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'code',
|
||||||
|
header: t('products.product_code'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'description',
|
||||||
|
header: t('products.description'),
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const desc = row.getValue('description') as string
|
||||||
|
return h('span', { class: 'text-sm text-gray-500 dark:text-gray-400' }, desc?.substring(0, 50) + (desc && desc.length > 50 ? '...' : ''))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'inStock',
|
||||||
|
header: t('products.in_stock'),
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const inStock = row.getValue('inStock')
|
||||||
|
return h('span', {
|
||||||
|
class: inStock ? 'text-green-600 font-medium' : 'text-red-600 font-medium'
|
||||||
|
}, inStock ? t('products.yes') : t('products.no'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'price',
|
||||||
|
header: t('products.price'),
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const priceFromVal = row.original.priceFrom
|
||||||
|
const priceToVal = row.original.priceTo
|
||||||
|
return `${priceFromVal} - ${priceToVal}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'count',
|
||||||
|
header: t('products.count'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
header: '',
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const product = row.original
|
||||||
|
return h('div', { class: 'flex gap-2' }, [
|
||||||
|
h('button', {
|
||||||
|
class: 'px-3 py-1.5 text-sm font-medium bg-primary text-white rounded-lg hover:bg-blue-600 transition-colors',
|
||||||
|
onClick: (e: Event) => { e.stopPropagation(); addToCart(product) }
|
||||||
|
}, t('products.add_to_cart')),
|
||||||
|
h('button', {
|
||||||
|
class: 'px-3 py-1.5 text-sm font-medium bg-gray-200 dark:bg-gray-700 text-black dark:text-white rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors',
|
||||||
|
onClick: (e: Event) => { e.stopPropagation(); incrementCount(product) }
|
||||||
|
}, '+')
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
function addToCart(product: Product) {
|
||||||
|
console.log('Add to cart:', product)
|
||||||
|
}
|
||||||
|
|
||||||
|
function incrementCount(product: Product) {
|
||||||
|
product.count++
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearFilters() {
|
||||||
|
searchName.value = ''
|
||||||
|
searchCode.value = ''
|
||||||
|
priceFromFilter.value = null
|
||||||
|
priceToFilter.value = null
|
||||||
|
resetPage()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="p-6 bg-white dark:bg-(--black) min-h-screen font-sans">
|
||||||
|
<div >
|
||||||
|
<!-- v-html="productStore.products" -->
|
||||||
|
</div>
|
||||||
|
<h1 class="text-2xl font-bold mb-6 text-black dark:text-white">{{ t('products.title') }}</h1>
|
||||||
|
|
||||||
|
<div v-if="!authStore.isAuthenticated" class="mb-4 p-3 bg-yellow-100 text-yellow-700 rounded">
|
||||||
|
{{ t('products.login_to_view') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Loading State -->
|
||||||
|
<div v-if="productStore.loading" class="mb-4 p-3 bg-blue-100 text-blue-700 rounded">
|
||||||
|
{{ t('products.loading') }}...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Error State -->
|
||||||
|
<div v-if="productStore.error" class="mb-4 p-3 bg-red-100 text-red-700 rounded">
|
||||||
|
{{ productStore.error }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="authStore.isAuthenticated && !productStore.loading && !productStore.error" class="space-y-4">
|
||||||
|
<!-- Filter Block -->
|
||||||
|
<div class="flex flex-wrap gap-4 mb-4 p-4 border border-(--border-light) dark:border-(--border-dark) rounded bg-gray-50 dark:bg-gray-800">
|
||||||
|
<div class="flex flex-col min-w-[180px]">
|
||||||
|
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ t('products.search_by_name') }}</label>
|
||||||
|
<UInput
|
||||||
|
v-model="searchName"
|
||||||
|
:placeholder="t('products.search_name_placeholder')"
|
||||||
|
@update:model-value="resetPage"
|
||||||
|
class="dark:text-white text-black"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col min-w-[180px]">
|
||||||
|
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ t('products.search_by_code') }}</label>
|
||||||
|
<UInput
|
||||||
|
v-model="searchCode"
|
||||||
|
:placeholder="t('products.search_code_placeholder')"
|
||||||
|
@update:model-value="resetPage"
|
||||||
|
class="dark:text-white text-black"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col min-w-[120px]">
|
||||||
|
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ t('products.price_from') }}</label>
|
||||||
|
<UInput
|
||||||
|
v-model="priceFromFilter"
|
||||||
|
type="number"
|
||||||
|
:placeholder="t('products.price_from')"
|
||||||
|
@update:model-value="resetPage"
|
||||||
|
class="dark:text-white text-black"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col min-w-[120px]">
|
||||||
|
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ t('products.price_to') }}</label>
|
||||||
|
<UInput
|
||||||
|
v-model="priceToFilter"
|
||||||
|
type="number"
|
||||||
|
:placeholder="t('products.price_to')"
|
||||||
|
@update:model-value="resetPage"
|
||||||
|
class="dark:text-white text-black"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-end">
|
||||||
|
<button
|
||||||
|
@click="clearFilters"
|
||||||
|
class="px-4 py-2 text-sm font-medium text-black dark:text-white bg-gray-200 dark:bg-gray-700 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors"
|
||||||
|
>
|
||||||
|
{{ t('products.clear_filters') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Products Table -->
|
||||||
|
<!-- <div class="border border-(--border-light) dark:border-(--border-dark) rounded overflow-hidden">
|
||||||
|
<UTable
|
||||||
|
:data="paginatedProducts"
|
||||||
|
:columns="columns"
|
||||||
|
class="dark:text-white! text-dark"
|
||||||
|
/>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- Empty State -->
|
||||||
|
<!-- <div v-if="filteredProducts.length === 0" class="text-center py-10 text-gray-500 dark:text-gray-400">
|
||||||
|
{{ t('products.no_products') }}
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- Pagination -->
|
||||||
|
<!-- <div v-if="filteredProducts.length > 0" class="pt-4 flex justify-center items-center dark:text-white! text-dark">
|
||||||
|
<UPagination
|
||||||
|
v-model:page="page"
|
||||||
|
:page-count="pageSize"
|
||||||
|
:total="totalItems"
|
||||||
|
/>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- Results count -->
|
||||||
|
<!-- <div v-if="filteredProducts.length > 0" class="text-sm text-gray-600 dark:text-gray-400 text-center">
|
||||||
|
{{ t('products.showing') }} {{ paginatedProducts.length }} {{ t('products.of') }} {{ totalItems }} {{ t('products.products') }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
72
bo/src/components/customer/Cart1.vue
Normal file
72
bo/src/components/customer/Cart1.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container mx-auto mt-20">
|
||||||
|
<h2
|
||||||
|
class="font-semibold text-black dark:text-white pb-6 text-2xl">
|
||||||
|
{{ t('Cart Items') }}
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) overflow-hidden">
|
||||||
|
<div v-if="cartStore.items.length > 0" class="divide-y divide-(--border-light) dark:divide-(--border-dark)">
|
||||||
|
<div v-for="item in cartStore.items" :key="item.id" class="flex items-center justify-between p-4 gap-4">
|
||||||
|
<div class="grid grid-cols-5 w-[100%]">
|
||||||
|
<div
|
||||||
|
class="w-20 bg-(--second-light) dark:bg-(--main-dark) rounded flex items-center justify-center overflow-hidden">
|
||||||
|
<img v-if="item.image" :src="item.image" :alt="item.name" class="w-full h-full object-cover" />
|
||||||
|
<UIcon v-else name="mdi:package-variant" class="text-xl text-gray-400" />
|
||||||
|
</div>
|
||||||
|
<p class="text-black dark:text-white text-sm font-medium truncate">{{ item.name }}</p>
|
||||||
|
<p class="text-black dark:text-white text-sm font-medium truncate">{{ item.product_number }}</p>
|
||||||
|
<p class="text-black dark:text-white font-medium">${{ (item.price * item.quantity).toFixed(2) }}</p>
|
||||||
|
<div class="flex items-center justify-end gap-10">
|
||||||
|
<UInputNumber v-model="item.quantity" class="text-gray-500 dark:text-gray-400 text-sm" />
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<button @click="removeItem(item.id)"
|
||||||
|
class="p-2 text-red-500 bg-red-100 dark:bg-(--main-dark) rounded transition-colors"
|
||||||
|
:title="t('Remove')">
|
||||||
|
<UIcon name="material-symbols:delete" class="text-[20px]" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="p-8 text-center">
|
||||||
|
<UIcon name="mdi:cart-outline" class="text-5xl text-gray-300 dark:text-gray-600 mb-4 mx-auto" />
|
||||||
|
<p class="text-gray-500 dark:text-gray-400">{{ t('Your cart is empty') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="cartStore.items.length > 0" class="flex gap-4 justify-end items-center pt-6">
|
||||||
|
<UButton color="primary" @click="handleContinueToCheckout"
|
||||||
|
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
|
||||||
|
{{ t('Continue to Checkout') }}
|
||||||
|
</UButton>
|
||||||
|
<UButton variant="outline" color="neutral" @click="handleCancel"
|
||||||
|
class="text-black dark:text-white border-(--border-light) dark:border-(--border-dark) hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||||
|
{{ t('Cancel') }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useCartStore } from '@/stores/cart'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const cartStore = useCartStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
const router = useRouter()
|
||||||
|
function handleCancel() {
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleContinueToCheckout() {
|
||||||
|
router.push({ name: 'cart' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeItem(itemId: number) {
|
||||||
|
cartStore.removeItem(itemId)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
180
bo/src/components/customer/PageAddresses.vue
Normal file
180
bo/src/components/customer/PageAddresses.vue
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container mx-auto mt-20">
|
||||||
|
<div class="flex flex-col gap-5 mb-6">
|
||||||
|
<h1 class="text-2xl font-bold text-black dark:text-white">{{ t('Addresses') }}</h1>
|
||||||
|
<div class="flex md:flex-row flex-col justify-between items-start md:items-center gap-5 md:gap-0">
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
<UInput v-model="searchQuery" type="text" :placeholder="t('Search address')"
|
||||||
|
class="bg-white dark:bg-gray-800 text-black dark:text-white absolute" />
|
||||||
|
<UIcon name="ic:baseline-search"
|
||||||
|
class="text-[20px] text-(--accent-blue-light) dark:text-(--accent-blue-dark) relative left-40" />
|
||||||
|
</div>
|
||||||
|
<UButton color="primary" @click="openCreateModal"
|
||||||
|
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
|
||||||
|
<UIcon name="mdi:add-bold" />
|
||||||
|
{{ t('Add Address') }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="paginatedAddresses.length" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
|
<div v-for="address in paginatedAddresses" :key="address.id"
|
||||||
|
class="border border-(--border-light) dark:border-(--border-dark) rounded-md p-4 bg-(--second-light) dark:bg-(--main-dark) hover:shadow-md transition-shadow flex justify-between">
|
||||||
|
<div class="flex flex-col gap-2 items-strat justify-end">
|
||||||
|
<p class="text-black dark:text-white">{{ address.street }}</p>
|
||||||
|
<p class="text-black dark:text-white">{{ address.zipCode }}, {{ address.city }}</p>
|
||||||
|
<p class="text-black dark:text-white">{{ address.country }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-end justify-between gap-2">
|
||||||
|
<button @click="confirmDelete(address.id)"
|
||||||
|
class="p-2 text-red-500 bg-red-100 dark:bg-(--main-dark) rounded transition-colors"
|
||||||
|
:title="t('Remove')">
|
||||||
|
<UIcon name="material-symbols:delete" class="text-[18px]" />
|
||||||
|
</button>
|
||||||
|
<UButton size="sm" color="neutral" variant="outline" @click="openEditModal(address)"
|
||||||
|
class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) text-[13px]">
|
||||||
|
{{ t('edit') }}
|
||||||
|
<UIcon name="ic:sharp-edit" class="text-[15px]" />
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="text-center py-8 text-gray-500 dark:text-gray-400">{{ t('No addresses found') }}</div>
|
||||||
|
<div class="mt-6 flex justify-center">
|
||||||
|
<UPagination v-model:page="page" :total="totalItems" :page-size="pageSize" />
|
||||||
|
</div>
|
||||||
|
<UModal v-model:open="showModal" :overlay="true" class="max-w-md mx-auto">
|
||||||
|
<template #content>
|
||||||
|
<div class="p-6 flex flex-col gap-6">
|
||||||
|
<p class="text-[20px] text-black dark:text-white ">Address</p>
|
||||||
|
<UForm @submit.prevent="saveAddress" class="space-y-4" :validate="validate">
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">Street *</label>
|
||||||
|
<UInput v-model="formData.street" placeholder="Enter street" name="street" class="w-full" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">Zip Code *</label>
|
||||||
|
<UInput v-model="formData.zipCode" placeholder="Enter zip code" name="zipCode"
|
||||||
|
class="w-full" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">City *</label>
|
||||||
|
<UInput v-model="formData.city" placeholder="Enter city" name="city" class="w-full" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">Country *</label>
|
||||||
|
<UInput v-model="formData.country" placeholder="Enter country" name="country"
|
||||||
|
class="w-full" />
|
||||||
|
</div>
|
||||||
|
</UForm>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<UButton variant="outline" color="neutral" @click="closeModal"
|
||||||
|
class="text-black dark:text-white">{{ t('Cancel') }}</UButton>
|
||||||
|
<UButton variant="outline" color="neutral" @click="saveAddress"
|
||||||
|
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
|
||||||
|
{{ t('Save') }}</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</UModal>
|
||||||
|
<UModal v-model:open="showDeleteConfirm" :overlay="true" class="max-w-md mx-auto">
|
||||||
|
<template #content>
|
||||||
|
<div class="p-6 flex flex-col gap-3">
|
||||||
|
<div class="flex flex-col gap-2 justify-center items-center">
|
||||||
|
<p class="flex items-end gap-2 dark:text-white text-black">
|
||||||
|
<UIcon name='f7:exclamationmark-triangle' class="text-[35px] text-red-700" />
|
||||||
|
Confirm Delete
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-700 dark:text-gray-300">
|
||||||
|
{{ t('Are you sure you want to delete this address?') }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center gap-5">
|
||||||
|
<UButton variant="outline" color="neutral" @click="showDeleteConfirm = false"
|
||||||
|
class="dark:text-white text-black">{{ t('Cancel') }}
|
||||||
|
</UButton>
|
||||||
|
<UButton variant="outline" color="neutral" @click="deleteAddress" class="text-red-700">
|
||||||
|
{{ t('Delete') }}</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</UModal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, watch } from 'vue'
|
||||||
|
import { useAddressStore } from '@/stores/address'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
const addressStore = useAddressStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
const searchQuery = ref('')
|
||||||
|
const showModal = ref(false)
|
||||||
|
const isEditing = ref(false)
|
||||||
|
const editingAddressId = ref<number | null>(null)
|
||||||
|
const formData = ref({ street: '', zipCode: '', city: '', country: '' })
|
||||||
|
|
||||||
|
const showDeleteConfirm = ref(false)
|
||||||
|
const addressToDelete = ref<number | null>(null)
|
||||||
|
|
||||||
|
const page = ref(addressStore.currentPage)
|
||||||
|
const paginatedAddresses = computed(() => addressStore.paginatedAddresses)
|
||||||
|
const totalItems = computed(() => addressStore.totalItems)
|
||||||
|
const pageSize = addressStore.pageSize
|
||||||
|
|
||||||
|
watch(page, (newPage) => addressStore.setPage(newPage))
|
||||||
|
watch(searchQuery, (val) => {
|
||||||
|
addressStore.setSearchQuery(val)
|
||||||
|
})
|
||||||
|
function openCreateModal() {
|
||||||
|
resetForm()
|
||||||
|
isEditing.value = false
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
function openEditModal(address: any) {
|
||||||
|
formData.value = {
|
||||||
|
street: address.street,
|
||||||
|
zipCode: address.zipCode,
|
||||||
|
city: address.city,
|
||||||
|
country: address.country
|
||||||
|
}
|
||||||
|
isEditing.value = true
|
||||||
|
editingAddressId.value = address.id
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
function resetForm() {
|
||||||
|
formData.value = { street: '', zipCode: '', city: '', country: '' }
|
||||||
|
editingAddressId.value = null
|
||||||
|
}
|
||||||
|
function closeModal() {
|
||||||
|
showModal.value = false
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
function validate() {
|
||||||
|
const errors = []
|
||||||
|
if (!formData.value.street) errors.push({ name: 'street', message: 'Street required' })
|
||||||
|
if (!formData.value.zipCode) errors.push({ name: 'zipCode', message: 'Zip Code required' })
|
||||||
|
if (!formData.value.city) errors.push({ name: 'city', message: 'City required' })
|
||||||
|
if (!formData.value.country) errors.push({ name: 'country', message: 'Country required' })
|
||||||
|
return errors.length ? errors : null
|
||||||
|
}
|
||||||
|
function saveAddress() {
|
||||||
|
if (validate()) return
|
||||||
|
if (isEditing.value && editingAddressId.value) {
|
||||||
|
addressStore.updateAddress(editingAddressId.value, formData.value)
|
||||||
|
} else {
|
||||||
|
addressStore.addAddress(formData.value)
|
||||||
|
}
|
||||||
|
closeModal()
|
||||||
|
}
|
||||||
|
function confirmDelete(id: number) {
|
||||||
|
addressToDelete.value = id
|
||||||
|
showDeleteConfirm.value = true
|
||||||
|
}
|
||||||
|
function deleteAddress() {
|
||||||
|
if (addressToDelete.value) {
|
||||||
|
addressStore.deleteAddress(addressToDelete.value)
|
||||||
|
}
|
||||||
|
showDeleteConfirm.value = false
|
||||||
|
addressToDelete.value = null
|
||||||
|
}
|
||||||
|
</script>
|
||||||
199
bo/src/components/customer/PageCart.vue
Normal file
199
bo/src/components/customer/PageCart.vue
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container mx-auto mt-20 flex flex-col gap-5 md:gap-10">
|
||||||
|
<h1 class="text-2xl font-bold text-black dark:text-white">{{ t('Shopping Cart') }}</h1>
|
||||||
|
<div class="flex flex-col lg:flex-row gap-5 md:gap-10">
|
||||||
|
<div class="flex-1">
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) overflow-hidden">
|
||||||
|
<h2
|
||||||
|
class="text-lg font-semibold text-black dark:text-white p-4 border-b border-(--border-light) dark:border-(--border-dark)">
|
||||||
|
{{ t('Selected Products') }}
|
||||||
|
</h2>
|
||||||
|
<div v-if="cartStore.items.length > 0">
|
||||||
|
<div v-for="item in cartStore.items" :key="item.id"
|
||||||
|
class="grid grid-cols-5 items-center p-4 border-b border-(--border-light) dark:border-(--border-dark) w-[100%]">
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded flex items-center justify-center overflow-hidden">
|
||||||
|
<img v-if="item.image" :src="item.image" :alt="item.name" class="w-full h-full object-cover" />
|
||||||
|
<UIcon v-else name="mdi:package-variant" class="text-2xl text-gray-400" />
|
||||||
|
</div>
|
||||||
|
<p class="text-black dark:text-white text-sm font-medium">{{ item.name }}</p>
|
||||||
|
<p class="text-black dark:text-white">${{ item.price.toFixed(2) }}</p>
|
||||||
|
<p class="text-black dark:text-white font-medium">${{ (item.price * item.quantity).toFixed(2)
|
||||||
|
}}</p>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end gap-10">
|
||||||
|
<UInputNumber v-model="item.quantity" :min="1"
|
||||||
|
@update:model-value="(val: number) => cartStore.updateQuantity(item.id, val)" />
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<button @click="removeItem(item.id)"
|
||||||
|
class="p-2 text-red-500 bg-red-100 dark:bg-(--main-dark) rounded transition-colors"
|
||||||
|
:title="t('Remove')">
|
||||||
|
<UIcon name="material-symbols:delete" class="text-[20px]" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="p-8 text-center">
|
||||||
|
<UIcon name="mdi:cart-outline" class="text-6xl text-gray-300 dark:text-gray-600 mb-4" />
|
||||||
|
<p class="text-gray-500 dark:text-gray-400">{{ t('Your cart is empty') }}</p>
|
||||||
|
<RouterLink :to="{ name: 'product-card-full' }"
|
||||||
|
class="inline-block mt-4 text-(--accent-blue-light) dark:text-(--accent-blue-dark) hover:underline">
|
||||||
|
{{ t('Continue Shopping') }}
|
||||||
|
</RouterLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="lg:w-80">
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-6 sticky top-24">
|
||||||
|
<h2 class="text-lg font-semibold text-black dark:text-white mb-4">{{ t('Order Summary') }}</h2>
|
||||||
|
<div class="space-y-3 border-b border-(--border-light) dark:border-(--border-dark) pb-4 mb-4">
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">{{ t('Products total') }}</span>
|
||||||
|
<span class="text-black dark:text-white">${{ cartStore.productsTotal.toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">{{ t('Shipping') }}</span>
|
||||||
|
<span class="text-black dark:text-white">
|
||||||
|
{{ cartStore.shippingCost > 0 ? `$${cartStore.shippingCost.toFixed(2)}` : t('Free') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">{{ t('VAT') }} ({{ (cartStore.vatRate * 100).toFixed(0)
|
||||||
|
}}%)</span>
|
||||||
|
<span class="text-black dark:text-white">${{ cartStore.vatAmount.toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between mb-6">
|
||||||
|
<span class="text-black dark:text-white font-semibold text-lg">{{ t('Total') }}</span>
|
||||||
|
<span class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) font-bold text-lg">${{
|
||||||
|
cartStore.orderTotal.toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<UButton block color="primary" @click="placeOrder" :disabled="!canPlaceOrder"
|
||||||
|
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light) disabled:opacity-50 disabled:cursor-not-allowed">
|
||||||
|
{{ t('Place Order') }}
|
||||||
|
</UButton>
|
||||||
|
<UButton block variant="outline" color="neutral" @click="cancelOrder"
|
||||||
|
class="text-black dark:text-white border-(--border-light) dark:border-(--border-dark) hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||||
|
{{ t('Cancel') }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 md:gap-10">
|
||||||
|
<div class="flex-1">
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-6">
|
||||||
|
<h2 class="text-lg font-semibold text-black dark:text-white mb-4">{{ t('Select Delivery Address') }}</h2>
|
||||||
|
<div class="mb-4">
|
||||||
|
<UInput v-model="addressSearchQuery" type="text" :placeholder="t('Search address')"
|
||||||
|
class="w-full bg-white dark:bg-gray-800 text-black dark:text-white" />
|
||||||
|
</div>
|
||||||
|
<div v-if="addressStore.filteredAddresses.length > 0" class="space-y-3">
|
||||||
|
<label v-for="address in addressStore.filteredAddresses" :key="address.id"
|
||||||
|
class="flex items-start gap-3 p-4 border rounded-lg cursor-pointer transition-colors" :class="cartStore.selectedAddressId === address.id
|
||||||
|
? 'border-(--accent-blue-light) dark:border-(--accent-blue-dark) bg-blue-50 dark:bg-blue-900/20'
|
||||||
|
: 'border-(--border-light) dark:border-(--border-dark) hover:border-gray-400'">
|
||||||
|
<input type="radio" :value="address.id" v-model="selectedAddress"
|
||||||
|
class="mt-1 w-4 h-4 text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
<div class="flex-1">
|
||||||
|
<p class="text-black dark:text-white font-medium">{{ address.street }}</p>
|
||||||
|
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ address.zipCode }}, {{ address.city }}</p>
|
||||||
|
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ address.country }}</p>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div v-else class="text-center py-6">
|
||||||
|
<UIcon name="mdi:map-marker-outline" class="text-4xl text-gray-400 mb-2" />
|
||||||
|
<p class="text-gray-500 dark:text-gray-400">{{ t('No addresses found') }}</p>
|
||||||
|
<RouterLink :to="{ name: 'addresses' }"
|
||||||
|
class="inline-block mt-2 text-(--accent-blue-light) dark:text-(--accent-blue-dark) hover:underline">
|
||||||
|
{{ t('Add Address') }}
|
||||||
|
</RouterLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-6">
|
||||||
|
<h2 class="text-lg font-semibold text-black dark:text-white mb-4">{{ t('Delivery Method') }}</h2>
|
||||||
|
<div class="space-y-3">
|
||||||
|
<label v-for="method in cartStore.deliveryMethods" :key="method.id"
|
||||||
|
class="flex items-center gap-3 p-4 border rounded-lg cursor-pointer transition-colors" :class="cartStore.selectedDeliveryMethodId === method.id
|
||||||
|
? 'border-(--accent-blue-light) dark:border-(--accent-blue-dark) bg-blue-50 dark:bg-blue-900/20'
|
||||||
|
: 'border-(--border-light) dark:border-(--border-dark) hover:border-gray-400'">
|
||||||
|
<input type="radio" :value="method.id" v-model="selectedDeliveryMethod"
|
||||||
|
class="w-4 h-4 text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<span class="text-black dark:text-white font-medium">{{ method.name }}</span>
|
||||||
|
<span class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) font-medium">
|
||||||
|
{{ method.price > 0 ? `$${method.price.toFixed(2)}` : t('Free') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-500 dark:text-gray-400 text-sm">{{ method.description }}</p>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, watch } from 'vue'
|
||||||
|
import { useCartStore } from '@/stores/cart'
|
||||||
|
import { useAddressStore } from '@/stores/address'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const cartStore = useCartStore()
|
||||||
|
const addressStore = useAddressStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const selectedAddress = ref<number | null>(cartStore.selectedAddressId)
|
||||||
|
const selectedDeliveryMethod = ref<number | null>(cartStore.selectedDeliveryMethodId)
|
||||||
|
const addressSearchQuery = ref('')
|
||||||
|
|
||||||
|
watch(addressSearchQuery, (val) => {
|
||||||
|
addressStore.setSearchQuery(val)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(selectedAddress, (newValue) => {
|
||||||
|
cartStore.setSelectedAddress(newValue)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(selectedDeliveryMethod, (newValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
cartStore.setDeliveryMethod(newValue)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const canPlaceOrder = computed(() => {
|
||||||
|
return cartStore.items.length > 0 &&
|
||||||
|
cartStore.selectedAddressId !== null &&
|
||||||
|
cartStore.selectedDeliveryMethodId !== null
|
||||||
|
})
|
||||||
|
function removeItem(itemId: number) {
|
||||||
|
cartStore.removeItem(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeOrder() {
|
||||||
|
if (canPlaceOrder.value) {
|
||||||
|
console.log('Placing order...')
|
||||||
|
alert(t('Order placed successfully!'))
|
||||||
|
cartStore.clearCart()
|
||||||
|
router.push({ name: 'home' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelOrder() {
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
178
bo/src/components/customer/PageCreateAccount.vue
Normal file
178
bo/src/components/customer/PageCreateAccount.vue
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container mx-auto mt-20">
|
||||||
|
<div class="max-w-2xl mx-auto">
|
||||||
|
<div class="flex flex-col gap-5 mb-6">
|
||||||
|
<h1 class="text-2xl font-bold text-black dark:text-white">{{ t('Create Account') }}</h1>
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-4">
|
||||||
|
<UForm @submit.prevent="saveAccount" :validate="validate" class="space-y-6">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-lg font-semibold text-black dark:text-white mb-4 flex items-center gap-2">
|
||||||
|
<UIcon name="mdi:domain"
|
||||||
|
class="text-[20px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
{{ t('Company Information') }}
|
||||||
|
</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div class="md:col-span-2">
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">{{
|
||||||
|
t('Company Name') }} *</label>
|
||||||
|
<UInput v-model="formData.companyName" :placeholder="t('Enter company name')"
|
||||||
|
name="companyName" class="w-full" />
|
||||||
|
</div>
|
||||||
|
<div class="md:col-span-2">
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">{{
|
||||||
|
t('Company Email') }} *</label>
|
||||||
|
<UInput v-model="formData.companyEmail" type="email"
|
||||||
|
:placeholder="t('Enter company email')" name="companyEmail" class="w-full" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">{{
|
||||||
|
t('REGON') }}</label>
|
||||||
|
<UInput v-model="formData.regon" :placeholder="t('Enter REGON')" name="regon"
|
||||||
|
class="w-full" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">{{ t('NIP')
|
||||||
|
}}</label>
|
||||||
|
<UInput v-model="formData.nip" :placeholder="t('Enter NIP')" name="nip"
|
||||||
|
class="w-full" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-black dark:text-white mb-1">{{ t('VAT')
|
||||||
|
}}</label>
|
||||||
|
<UInput v-model="formData.vat" :placeholder="t('Enter VAT')" name="vat"
|
||||||
|
class="w-full" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2 class="text-lg font-semibold text-black dark:text-white mb-4 flex items-center gap-2">
|
||||||
|
<UIcon name="mdi:map-marker"
|
||||||
|
class="text-[20px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
{{ t('Select Addresses') }}
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark)">
|
||||||
|
<div class="mb-4">
|
||||||
|
<UInput v-model="addressSearchQuery" type="text" :placeholder="t('Search address')"
|
||||||
|
class="w-full bg-white dark:bg-(--black) text-black dark:text-white" />
|
||||||
|
</div>
|
||||||
|
<div v-if="addressStore.filteredAddresses.length > 0" class="space-y-3">
|
||||||
|
<label v-for="address in addressStore.filteredAddresses" :key="address.id"
|
||||||
|
class="flex items-start gap-3 p-4 border rounded-lg cursor-pointer transition-colors"
|
||||||
|
:class="cartStore.selectedAddressId === address.id
|
||||||
|
? 'border-(--accent-blue-light) dark:border-(--accent-blue-dark) bg-blue-50 dark:bg-blue-900/20'
|
||||||
|
: 'border-(--border-light) dark:border-(--border-dark) hover:border-gray-400'">
|
||||||
|
<input type="radio" :value="address.id" v-model="selectedAddress"
|
||||||
|
class="mt-1 w-4 h-4 text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
<div class="flex-1">
|
||||||
|
<p class="text-black dark:text-white font-medium">{{ address.street }}</p>
|
||||||
|
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ address.zipCode }},
|
||||||
|
{{ address.city }}</p>
|
||||||
|
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ address.country }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div v-else class="text-center py-6">
|
||||||
|
<UIcon name="mdi:map-marker-outline" class="text-4xl text-gray-400 mb-2" />
|
||||||
|
<p class="text-gray-500 dark:text-gray-400">{{ t('No addresses found') }}</p>
|
||||||
|
<RouterLink :to="{ name: 'addresses' }"
|
||||||
|
class="inline-block mt-2 text-(--accent-blue-light) dark:text-(--accent-blue-dark) hover:underline">
|
||||||
|
{{ t('Add Address') }}
|
||||||
|
</RouterLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end gap-3 pt-4">
|
||||||
|
<UButton variant="outline" color="neutral" @click="goBack"
|
||||||
|
class="text-black dark:text-white">
|
||||||
|
{{ t('Cancel') }}
|
||||||
|
</UButton>
|
||||||
|
<UButton type="submit" color="primary"
|
||||||
|
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
|
||||||
|
<UIcon name="mdi:content-save" />
|
||||||
|
{{ t('Save') }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</UForm>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useCustomerStore } from '@/stores/customer'
|
||||||
|
import { useAddressStore } from '@/stores/address'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useCartStore } from '@/stores/cart'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const customerStore = useCustomerStore()
|
||||||
|
const addressStore = useAddressStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
const cartStore = useCartStore()
|
||||||
|
const formData = ref({
|
||||||
|
companyName: customerStore.customer?.companyName || '',
|
||||||
|
companyEmail: customerStore.customer?.companyEmail || '',
|
||||||
|
regon: customerStore.customer?.regon || '',
|
||||||
|
nip: customerStore.customer?.nip || '',
|
||||||
|
vat: customerStore.customer?.vat || '',
|
||||||
|
companyAddressId: customerStore.customer?.companyAddressId || null,
|
||||||
|
billingAddressId: customerStore.customer?.billingAddressId || null
|
||||||
|
})
|
||||||
|
|
||||||
|
const addressSearchQuery = ref('')
|
||||||
|
|
||||||
|
watch(addressSearchQuery, (val) => {
|
||||||
|
addressStore.setSearchQuery(val)
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedAddress = ref<number | null>(formData.value.companyAddressId)
|
||||||
|
|
||||||
|
watch(selectedAddress, (newValue) => {
|
||||||
|
formData.value.companyAddressId = newValue
|
||||||
|
})
|
||||||
|
|
||||||
|
function validate() {
|
||||||
|
const errors: { name: string; message: string }[] = []
|
||||||
|
|
||||||
|
if (!formData.value.companyName?.trim()) {
|
||||||
|
errors.push({ name: 'companyName', message: t('Company name is required') })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formData.value.companyEmail?.trim()) {
|
||||||
|
errors.push({ name: 'companyEmail', message: t('Company email is required') })
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveAccount() {
|
||||||
|
const errors = validate()
|
||||||
|
if (errors.length) return
|
||||||
|
|
||||||
|
const selectedAddr = addressStore.addresses.find(
|
||||||
|
addr => addr.id === formData.value.companyAddressId
|
||||||
|
)
|
||||||
|
|
||||||
|
customerStore.setCustomer({
|
||||||
|
companyName: formData.value.companyName,
|
||||||
|
companyEmail: formData.value.companyEmail,
|
||||||
|
regon: formData.value.regon,
|
||||||
|
nip: formData.value.nip,
|
||||||
|
vat: formData.value.vat,
|
||||||
|
companyAddressId: formData.value.companyAddressId,
|
||||||
|
billingAddressId: formData.value.billingAddressId,
|
||||||
|
companyAddress: selectedAddr || null
|
||||||
|
})
|
||||||
|
|
||||||
|
router.push({ name: 'customer-data' })
|
||||||
|
}
|
||||||
|
function goBack() {
|
||||||
|
router.push({ name: 'customer-data' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
108
bo/src/components/customer/PageCustomerData.vue
Normal file
108
bo/src/components/customer/PageCustomerData.vue
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container mx-auto mt-20">
|
||||||
|
<div class="flex flex-col gap-5 mb-6">
|
||||||
|
<h1 class="text-2xl font-bold text-black dark:text-white">{{ t('Customer Data') }}</h1>
|
||||||
|
|
||||||
|
<div v-if="!customerStore.hasAccount" class="flex flex-col items-center justify-center py-12">
|
||||||
|
<div class="text-center flex flex-col items-center justify-center mb-6">
|
||||||
|
<UIcon name="mdi:domain" class="text-[60px] text-gray-400 dark:text-gray-500" />
|
||||||
|
<p class="mt-4 text-lg text-gray-600 dark:text-gray-400">{{ t('No customer account found') }}</p>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-500">{{ t('Create an account to manage your company data') }}</p>
|
||||||
|
</div>
|
||||||
|
<UButton color="primary" @click="goToCreateAccount"
|
||||||
|
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
|
||||||
|
<UIcon name="mdi:add-bold" />
|
||||||
|
{{ t('Create Account') }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="flex flex-col gap-3">
|
||||||
|
<div class="grid grid-cols-2 gap-5">
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-4">
|
||||||
|
<h2 class="text-xl font-semibold text-black dark:text-white mb-4 flex items-center gap-2">
|
||||||
|
<UIcon name="mdi:domain"
|
||||||
|
class="text-[24px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
{{ t('Company Information') }}
|
||||||
|
</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{ t('Company Name') }}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.companyName || '-' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('Company Email') }}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.companyEmail || '-' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('REGON') }}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.regon || '-' }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('NIP') }}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.nip || '-' }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('VAT') }}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.vat || '-' }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-4">
|
||||||
|
<h2 class="text-xl font-semibold text-black dark:text-white mb-4 flex items-center gap-2">
|
||||||
|
<UIcon name="mdi:map-marker"
|
||||||
|
class="text-[24px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
{{ t('Addresses') }}
|
||||||
|
</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-2">{{ t('Company Address') }}</label>
|
||||||
|
<div v-if="companyAddress"
|
||||||
|
class="p-4 bg-white dark:bg-(--black) rounded-md border border-(--border-light) dark:border-(--border-dark)">
|
||||||
|
<p class="text-black dark:text-white">{{ companyAddress.street }}</p>
|
||||||
|
<p class="text-black dark:text-white">{{ companyAddress.zipCode }}, {{
|
||||||
|
companyAddress.city }}</p>
|
||||||
|
<p class="text-black dark:text-white">{{ companyAddress.country }}</p>
|
||||||
|
</div>
|
||||||
|
<p v-else class="text-gray-400 dark:text-gray-500">-</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<UButton color="primary" variant="outline"
|
||||||
|
class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) border-(--accent-blue-light) dark:border-(--accent-blue-dark)"
|
||||||
|
@click="goToCreateAccount">
|
||||||
|
<UIcon name="ic:sharp-edit" />
|
||||||
|
{{ t('Edit Account') }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useCustomerStore } from '@/stores/customer'
|
||||||
|
import { useAddressStore } from '@/stores/address'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const customerStore = useCustomerStore()
|
||||||
|
const addressStore = useAddressStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const companyAddress = computed(() => {
|
||||||
|
const id = customerStore.customer?.companyAddressId
|
||||||
|
return id ? addressStore.getAddressById(id) : null
|
||||||
|
})
|
||||||
|
|
||||||
|
function goToCreateAccount() {
|
||||||
|
router.push({ name: 'create-account' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
164
bo/src/components/customer/PageProductCardFull.vue
Normal file
164
bo/src/components/customer/PageProductCardFull.vue
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container mt-20 mx-auto">
|
||||||
|
<div class="flex md:flex-row flex-col justify-between gap-8 my-6">
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="bg-gray-100 dark:bg-gray-800 rounded-lg p-8 flex items-center justify-center min-h-[300px] ">
|
||||||
|
<img :src="selectedColor?.image || productData.image" :alt="productData.name"
|
||||||
|
class="max-w-full h-auto object-contain" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 flex flex-col gap-4">
|
||||||
|
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||||
|
{{ productData.name }}
|
||||||
|
</h1>
|
||||||
|
<p class="text-gray-600 dark:text-gray-300">
|
||||||
|
{{ productData.description }}
|
||||||
|
</p>
|
||||||
|
<div class="text-3xl font-bold text-(--accent-blue-light) dark:text-(--accent-blue-dark)">
|
||||||
|
{{ productData.price }}
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<span class="text-gray-500 dark:text-gray-400">Dimensions:</span>
|
||||||
|
<p class="font-medium dark:text-white">{{ productData.dimensions }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<span class="text-gray-500 dark:text-gray-400">Seat Height:</span>
|
||||||
|
<p class="font-medium dark:text-white">{{ productData.seatHeight }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex md:flex-row flex-col justify-between md:items-end items-start gap-5 md:gap-0 md:mb-8 mb-4">
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<span class="text-sm text-(--accent-blue-light) dark:text-(--accent-blue-dark) ">Colors:</span>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<button v-for="color in productData.colors" :key="color.id" @click="selectedColor = color"
|
||||||
|
class="w-10 h-10 border-2 transition-all" :class="selectedColor?.id === color.id
|
||||||
|
? 'border-(--accent-blue-light) ring-2 ring-blue-600 ring-offset-2'
|
||||||
|
: 'border-gray-300 dark:border-gray-600 hover:border-gray-400'"
|
||||||
|
:style="{ backgroundColor: color.hex }" :title="color.name" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-5 items-end">
|
||||||
|
<UInputNumber v-model="value" />
|
||||||
|
<UButton color="primary" class="px-14! bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white">
|
||||||
|
Add to Cart
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ProductCustomization />
|
||||||
|
<hr class="border-t border-(--border-light) dark:border-(--border-dark) mb-8" />
|
||||||
|
<div class="mb-6 w-[100%] xl:w-[60%]">
|
||||||
|
<div class="grid grid-cols-2 lg:grid-cols-4 gap-10 mb-8">
|
||||||
|
<UButton v-for="tab in tabs" :key="tab.id" @click="activeTab = tab.id" :class="[
|
||||||
|
'px-15 py-2 cursor-pointer sm:text-nowrap flex items-center! justify-center!',
|
||||||
|
activeTab === tab.id
|
||||||
|
? 'bg-blue-600 hover:text-black hover:dark:text-white text-white'
|
||||||
|
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'
|
||||||
|
]" variant="ghost">
|
||||||
|
{{ tab.label }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
<div class="py-5 px-3 bg-(--second-light) dark:bg-(--main-dark) rounded-md">
|
||||||
|
<p class="dark:text-white whitespace-pre-line">
|
||||||
|
{{ activeTabContent }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="border-t border-(--border-light) dark:border-(--border-dark) mb-8" />
|
||||||
|
<ProductVariants />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import ProductCustomization from './components/ProductCustomization.vue'
|
||||||
|
import ProductVariants from './components/ProductVariants.vue'
|
||||||
|
|
||||||
|
interface Color {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
hex: string
|
||||||
|
image: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProductData {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
price: string
|
||||||
|
dimensions: string
|
||||||
|
seatHeight: string
|
||||||
|
image: string
|
||||||
|
colors: Color[]
|
||||||
|
descriptionText: string
|
||||||
|
howToUseText: string
|
||||||
|
productDetailsText: string
|
||||||
|
documentsText: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeTab = ref('description')
|
||||||
|
const value = ref(5)
|
||||||
|
const selectedColor = ref<Color | null>(null)
|
||||||
|
|
||||||
|
const productData: ProductData = {
|
||||||
|
name: 'Larger Corner Sofa',
|
||||||
|
description: 'The large corner sofa is a comfortable seating solution for young children. It is upholstered with phthalate-free PVC-coated material intended for medical products, making it very easy to clean and disinfect. The product is available in a wide range of colours (13 colours), allowing it to fit into any interior.',
|
||||||
|
price: 'PLN 519.00 (VAT 23%)',
|
||||||
|
dimensions: '65 x 65 x 120 cm',
|
||||||
|
seatHeight: '45-55 cm',
|
||||||
|
image: '/placeholder-chair.jpg',
|
||||||
|
colors: [
|
||||||
|
{ id: 'black', name: 'Black', hex: '#1a1a1a', image: '/chair-black.jpg' },
|
||||||
|
{ id: 'gray', name: 'Gray', hex: '#6b7280', image: '/chair-gray.jpg' },
|
||||||
|
{ id: 'blue', name: 'Blue', hex: '#3b82f6', image: '/chair-blue.jpg' },
|
||||||
|
{ id: 'brown', name: 'Brown', hex: '#92400e', image: '/chair-brown.jpg' },
|
||||||
|
],
|
||||||
|
descriptionText: 'The large corner sofa is a comfortable seating solution for young children. It is upholstered with phthalate-free PVC-coated material intended for medical products, making it very easy to clean and disinfect. The product is available in a wide range of colours (13 colours), allowing it to fit into any interior',
|
||||||
|
howToUseText: '1. Adjust the seat height using the lever under the seat.\n2. Set the lumbar support to your preferred position.\n3. Adjust the armrests for optimal arm support.\n4. Use the recline tension knob to adjust the backrest resistance.\n5. Lock the recline position when needed.',
|
||||||
|
productDetailsText: '• Material: Mesh, Foam, Plastic\n• Max Load: 150 kg\n• Weight: 18 kg\n• Warranty: 2 years\n• Certifications: BIFMA, EN 1335',
|
||||||
|
documentsText: '• Assembly Instructions (PDF)\n• User Manual (PDF)\n• Warranty Terms (PDF)\n• Safety Certificate (PDF)',
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{ id: 'description', label: 'Description' },
|
||||||
|
{ id: 'howToUse', label: 'How to Use' },
|
||||||
|
{ id: 'productDetails', label: 'Product Details' },
|
||||||
|
{ id: 'documents', label: 'Documents' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const userActions = [
|
||||||
|
'View detailed product information',
|
||||||
|
'Browse product images and available colors',
|
||||||
|
'Check product dimensions and specifications',
|
||||||
|
'Select a product variant',
|
||||||
|
'Select quantity',
|
||||||
|
'Add the product to the cart',
|
||||||
|
'Navigate between product description, usage instructions, and product details',
|
||||||
|
]
|
||||||
|
|
||||||
|
const activeTabContent = computed(() => {
|
||||||
|
switch (activeTab.value) {
|
||||||
|
case 'description':
|
||||||
|
return productData.descriptionText
|
||||||
|
case 'howToUse':
|
||||||
|
return productData.howToUseText
|
||||||
|
case 'productDetails':
|
||||||
|
return productData.productDetailsText
|
||||||
|
case 'documents':
|
||||||
|
return productData.documentsText
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (productData.colors.length > 0) {
|
||||||
|
selectedColor.value = productData.colors[0] as Color
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.product-card-full {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
90
bo/src/components/customer/PageProductsList.vue
Normal file
90
bo/src/components/customer/PageProductsList.vue
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container mx-auto mt-20">
|
||||||
|
<h1 class="text-2xl font-bold mb-6 text-gray-900 dark:text-white">Products</h1>
|
||||||
|
<div v-if="loading" class="text-center py-8">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">Loading products...</span>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="error" class="mb-4 p-3 bg-red-100 text-red-700 rounded">
|
||||||
|
{{ error }}
|
||||||
|
</div>
|
||||||
|
<div v-else class="overflow-x-auto">
|
||||||
|
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
|
<thead class="bg-gray-50 dark:bg-gray-800">
|
||||||
|
<tr>
|
||||||
|
<th
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||||
|
Image</th>
|
||||||
|
<th
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||||
|
Product ID</th>
|
||||||
|
<th
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||||
|
Name</th>
|
||||||
|
<th
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
||||||
|
Link</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
|
<tr v-for="product in productsList" :key="product.product_id"
|
||||||
|
class="hover:bg-gray-50 dark:hover:bg-gray-800">
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<img :src="getImageUrl(product.ImageID, product.LinkRewrite,)" alt="product image"
|
||||||
|
class="w-16 h-16 object-cover rounded" />
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{
|
||||||
|
product.product_id }}</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{ product.name }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-blue-600 dark:text-blue-400">
|
||||||
|
{{ product.LinkRewrite }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div v-if="productsList.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
|
||||||
|
No products found
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useFetchJson } from '@/composable/useFetchJson'
|
||||||
|
|
||||||
|
interface Product {
|
||||||
|
product_id: number
|
||||||
|
name: string
|
||||||
|
ImageID: number
|
||||||
|
LinkRewrite: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ApiResponse {
|
||||||
|
message: string
|
||||||
|
items: Product[]
|
||||||
|
count: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const productsList = ref<Product[]>([])
|
||||||
|
const loading = ref(true)
|
||||||
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
|
function getImageUrl(imageID: number, linkRewrite: string, size: string = 'small_default') {
|
||||||
|
return `https://www.naluconcept.com/${imageID}-${size}/${linkRewrite}.webp`
|
||||||
|
}
|
||||||
|
async function fetchProductList() {
|
||||||
|
loading.value = true
|
||||||
|
error.value = null
|
||||||
|
try {
|
||||||
|
const response = await useFetchJson('/api/v1/restricted/list-products/get-listing?p&elems&shopID=1') as ApiResponse
|
||||||
|
productsList.value = response.items || []
|
||||||
|
} catch (e: unknown) {
|
||||||
|
error.value = e instanceof Error ? e.message : 'Failed to load products'
|
||||||
|
console.error(e)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(fetchProductList)
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container flex flex-col gap-8">
|
||||||
|
<div class="space-y-1 dark:text-white text-black">
|
||||||
|
<p class="text-[24px] font-bold">Product customization</p>
|
||||||
|
<p class="text-[15px]">Don't forget to save your customization to be able to add to cart</p>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 gap-5 md:gap-10 ">
|
||||||
|
<UInput label="Podaj kolor kanapy narożnej" placeholder="Podaj kolor kanapy narożnej" class="dark:text-white text-black"/>
|
||||||
|
<UInput label="Podaj kolor fotela" placeholder="Podaj kolor fotela" class="dark:text-white text-black"/>
|
||||||
|
<UInput label="Podaj kolor kwadratu" placeholder="Podaj kolor kwadratu" class="dark:text-white text-black"/>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end items-end mb-8">
|
||||||
|
<UButton class="px-10! bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white">Save</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
57
bo/src/components/customer/components/ProductVariants.vue
Normal file
57
bo/src/components/customer/components/ProductVariants.vue
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container flex flex-col gap-8">
|
||||||
|
<p class="text-[24px] font-bold dark:text-white text-black">Product Variants:</p>
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<div v-for="(variant, index) in variants" :key="index" class="flex gap-10">
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-15 border border-(--border-light) dark:border-(--border-dark) p-5 rounded-md hover:bg-gray-50 hover:dark:bg-gray-700 bg-(--second-light) dark:bg-(--second-dark) dark:text-white text-black">
|
||||||
|
<img :src="variant.image" :alt="variant.image" class="w-16 h-16 object-cover" />
|
||||||
|
<p class="">{{ variant.name }}</p>
|
||||||
|
<p class="">{{ variant.productNumber }}</p>
|
||||||
|
<p class="">{{ variant.value }}</p>
|
||||||
|
<p class="">{{ variant.price }}</p>
|
||||||
|
<p class="">{{ variant.quantity }}</p>
|
||||||
|
<button class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded"
|
||||||
|
@click="addToCart(variant)">
|
||||||
|
Add to Cart
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const variants = ref([
|
||||||
|
{
|
||||||
|
image: 'img',
|
||||||
|
name: 'Duży fotelik narożny ',
|
||||||
|
productNumber: 'NC209/7000',
|
||||||
|
value: '20,000',
|
||||||
|
price: '519,00 zł',
|
||||||
|
quantity: 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: 'img',
|
||||||
|
name: 'Duży fotelik narożny ',
|
||||||
|
productNumber: 'NC209/7000',
|
||||||
|
value: '20,000',
|
||||||
|
price: '519,00 zł',
|
||||||
|
quantity: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: 'img',
|
||||||
|
name: 'Duży fotelik narożny ',
|
||||||
|
productNumber: 'NC209/7000',
|
||||||
|
value: '20,000',
|
||||||
|
price: '519,00 zł',
|
||||||
|
quantity: 8
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const addToCart = (variant: any) => {
|
||||||
|
console.log('Added to cart:', variant)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<USelectMenu v-model="locale" :items="langs" class="w-40 bg-white dark:bg-(--black) rounded-md shadow-sm hover:none!"
|
<USelectMenu v-model="locale" :items="langs" class="w-40 bg-(--main-light) dark:bg-(--black) rounded-md shadow-sm hover:none!"
|
||||||
valueKey="iso_code" :searchInput="false">
|
valueKey="iso_code" :searchInput="false">
|
||||||
<template #default="{ modelValue }">
|
<template #default="{ modelValue }">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
|
|||||||
41
bo/src/composable/useConteditable.ts
Normal file
41
bo/src/composable/useConteditable.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { ref, type Ref } from 'vue'
|
||||||
|
import DOMPurify from 'dompurify'
|
||||||
|
|
||||||
|
export function useEditable(elementRef: Ref<HTMLElement | null>) {
|
||||||
|
|
||||||
|
const isEditing = ref(false)
|
||||||
|
|
||||||
|
const enableEdit = () => {
|
||||||
|
if (!elementRef.value) return
|
||||||
|
|
||||||
|
isEditing.value = true
|
||||||
|
|
||||||
|
Array.from(elementRef.value.children).forEach(item => {
|
||||||
|
item.setAttribute('contenteditable', 'true')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const disableEdit = () => {
|
||||||
|
if (!elementRef.value) return
|
||||||
|
|
||||||
|
isEditing.value = false
|
||||||
|
|
||||||
|
Array.from(elementRef.value.children).forEach(item => {
|
||||||
|
item.setAttribute('contenteditable', 'false')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCleanHtml = () => {
|
||||||
|
if (!elementRef.value) return ''
|
||||||
|
|
||||||
|
const html = elementRef.value.innerHTML
|
||||||
|
return DOMPurify.sanitize(html)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isEditing,
|
||||||
|
enableEdit,
|
||||||
|
disableEdit,
|
||||||
|
getCleanHtml
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,10 +26,10 @@ export interface PagingParams {
|
|||||||
pageSize?: number
|
pageSize?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRepos(): Promise<any> {
|
// export async function getRepos(): Promise<any> {
|
||||||
const result = await useFetchJson<number[]>(`${API_PREFIX}/get-repos`)
|
// const result = await useFetchJson<number[]>(`${API_PREFIX}/get-repos`)
|
||||||
return result
|
// return result
|
||||||
}
|
// }
|
||||||
|
|
||||||
// export async function getYears(repoID: number): Promise<any> {
|
// export async function getYears(repoID: number): Promise<any> {
|
||||||
// return useFetchJson<number[]>(`${API_PREFIX}/get-years?repoID=${repoID}`)
|
// return useFetchJson<number[]>(`${API_PREFIX}/get-years?repoID=${repoID}`)
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import TopBar from '@/components/TopBar.vue';
|
import TopBar from '@/components/TopBar.vue';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-screen grid grid-rows-[auto_1fr_auto]">
|
<div class="h-screen grid grid-rows-[auto_1fr_auto]">
|
||||||
<!-- <header class="w-full bg-gray-100 text-primary shadow border-b-gray-300 p-4 mb-8">Header</header> -->
|
<!-- <header class="w-full bg-gray-100 text-primary shadow border-b-gray-300 p-4 mb-8">Header</header> -->
|
||||||
<UContainer>
|
<main class="px-4 sm:px-6 lg:px-8">
|
||||||
<main class="p-10">
|
|
||||||
<TopBar/>
|
<TopBar/>
|
||||||
<router-view />
|
<router-view />
|
||||||
</main>
|
</main>
|
||||||
</UContainer>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -5,17 +5,11 @@ import { getSettings } from './settings'
|
|||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import Default from '@/layouts/default.vue'
|
import Default from '@/layouts/default.vue'
|
||||||
|
|
||||||
// Helper: read the non-HTTPOnly is_authenticated cookie set by the backend.
|
|
||||||
// The backend sets it to "1" on login and removes it on logout.
|
|
||||||
function isAuthenticated(): boolean {
|
function isAuthenticated(): boolean {
|
||||||
if (typeof document === 'undefined') return false
|
if (typeof document === 'undefined') return false
|
||||||
return document.cookie.split('; ').some((c) => c === 'is_authenticated=1')
|
return document.cookie.split('; ').some((c) => c === 'is_authenticated=1')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await getSettings()
|
await getSettings()
|
||||||
|
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.VITE_BASE_URL),
|
history: createWebHistory(import.meta.env.VITE_BASE_URL),
|
||||||
routes: [
|
routes: [
|
||||||
@@ -31,6 +25,15 @@ const router = createRouter({
|
|||||||
component: Default,
|
component: Default,
|
||||||
children: [
|
children: [
|
||||||
{ path: '', component: () => import('../views/RepoChartView.vue'), name: 'home' },
|
{ path: '', component: () => import('../views/RepoChartView.vue'), name: 'home' },
|
||||||
|
{ path: 'products', component: () => import('../components/admin/ProductsView.vue'), name: 'products' },
|
||||||
|
{ path: 'products-datail/', component: () => import('../components/admin/ProductDetailView.vue'), name: 'product-detail' },
|
||||||
|
{ path: 'product-card-full/', component: () => import('../components/customer/PageProductCardFull.vue'), name: 'product-card-full' },
|
||||||
|
{ path: 'addresses', component: () => import('../components/customer/PageAddresses.vue'), name: 'addresses' },
|
||||||
|
{ path: 'customer-data', component: () => import('../components/customer/PageCustomerData.vue'), name: 'customer-data' },
|
||||||
|
{ path: 'create-account', component: () => import('../components/customer/PageCreateAccount.vue'), name: 'create-account' },
|
||||||
|
{ path: 'cart', component: () => import('../components/customer/PageCart.vue'), name: 'cart' },
|
||||||
|
{ path: 'cart1', component: () => import('../components/customer/Cart1.vue'), name: 'cart1' },
|
||||||
|
{ path: 'products-list', component: () => import('../components/customer/PageProductsList.vue'), name: 'products-list' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -49,12 +52,9 @@ const router = createRouter({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
// Navigation guard: language handling + auth protection
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
const locale = to.params.locale as string
|
const locale = to.params.locale as string
|
||||||
const localeLang = langs.find((x) => x.iso_code == locale)
|
const localeLang = langs.find((x) => x.iso_code == locale)
|
||||||
|
|
||||||
// Check if the locale is valid
|
|
||||||
if (locale && langs.length > 0) {
|
if (locale && langs.length > 0) {
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
console.log(authStore.isAuthenticated, to, from)
|
console.log(authStore.isAuthenticated, to, from)
|
||||||
@@ -63,24 +63,19 @@ router.beforeEach((to, from, next) => {
|
|||||||
|
|
||||||
if (validLocale) {
|
if (validLocale) {
|
||||||
currentLang.value = localeLang
|
currentLang.value = localeLang
|
||||||
|
|
||||||
// Auth guard: if the route does NOT have meta.guest = true, require authentication
|
|
||||||
if (!to.meta?.guest && !isAuthenticated()) {
|
if (!to.meta?.guest && !isAuthenticated()) {
|
||||||
return next({ name: 'login', params: { locale } })
|
return next({ name: 'login', params: { locale } })
|
||||||
}
|
}
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
} else if (locale) {
|
} else if (locale) {
|
||||||
// Invalid locale - redirect to default language
|
|
||||||
return next(`/${currentLang.value?.iso_code}${to.path.replace(`/${locale}`, '') || '/'}`)
|
return next(`/${currentLang.value?.iso_code}${to.path.replace(`/${locale}`, '') || '/'}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No locale in URL - redirect to default language
|
|
||||||
if (!locale && to.path !== '/') {
|
if (!locale && to.path !== '/') {
|
||||||
return next(`/${currentLang.value?.iso_code}${to.path}`)
|
return next(`/${currentLang.value?.iso_code}${to.path}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
144
bo/src/stores/address.ts
Normal file
144
bo/src/stores/address.ts
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
|
export interface AddressFormData {
|
||||||
|
street: string
|
||||||
|
zipCode: string
|
||||||
|
city: string
|
||||||
|
country: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Address {
|
||||||
|
id: number
|
||||||
|
street: string
|
||||||
|
zipCode: string
|
||||||
|
city: string
|
||||||
|
country: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAddressStore = defineStore('address', () => {
|
||||||
|
const addresses = ref<Address[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
|
const currentPage = ref(1)
|
||||||
|
const pageSize = 20
|
||||||
|
|
||||||
|
const searchQuery = ref('')
|
||||||
|
|
||||||
|
function initMockData() {
|
||||||
|
addresses.value = [
|
||||||
|
{ id: 1, street: 'Main Street 123', zipCode: '10-001', city: 'New York', country: 'United States' },
|
||||||
|
{ id: 2, street: 'Oak Avenue 123', zipCode: '90-001', city: 'Los Angeles', country: 'United States' },
|
||||||
|
{ id: 3, street: 'Pine Road 123', zipCode: '60-601', city: 'Chicago', country: 'United States' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredAddresses = computed(() => {
|
||||||
|
if (!searchQuery.value) return addresses.value
|
||||||
|
|
||||||
|
const query = searchQuery.value.toLowerCase()
|
||||||
|
|
||||||
|
return addresses.value.filter(addr =>
|
||||||
|
addr.street.toLowerCase().includes(query) ||
|
||||||
|
addr.city.toLowerCase().includes(query) ||
|
||||||
|
addr.country.toLowerCase().includes(query) ||
|
||||||
|
addr.zipCode.toLowerCase().includes(query)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const totalItems = computed(() => filteredAddresses.value.length)
|
||||||
|
const totalPages = computed(() => Math.ceil(totalItems.value / pageSize))
|
||||||
|
|
||||||
|
const paginatedAddresses = computed(() => {
|
||||||
|
const start = (currentPage.value - 1) * pageSize
|
||||||
|
return filteredAddresses.value.slice(start, start + pageSize)
|
||||||
|
})
|
||||||
|
|
||||||
|
function getAddressById(id: number) {
|
||||||
|
return addresses.value.find(addr => addr.id === id)
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalize(data: AddressFormData): AddressFormData {
|
||||||
|
return {
|
||||||
|
street: data.street.trim(),
|
||||||
|
zipCode: data.zipCode.trim(),
|
||||||
|
city: data.city.trim(),
|
||||||
|
country: data.country.trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateId(): number {
|
||||||
|
return Math.max(0, ...addresses.value.map(a => a.id)) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function addAddress(formData: AddressFormData): Address {
|
||||||
|
const newAddress: Address = {
|
||||||
|
id: generateId(),
|
||||||
|
...normalize(formData)
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses.value.unshift(newAddress)
|
||||||
|
resetPagination()
|
||||||
|
|
||||||
|
return newAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateAddress(id: number, formData: AddressFormData): boolean {
|
||||||
|
const index = addresses.value.findIndex(a => a.id === id)
|
||||||
|
if (index === -1) return false
|
||||||
|
|
||||||
|
const existing = addresses.value[index]
|
||||||
|
if (!existing) return false
|
||||||
|
|
||||||
|
addresses.value[index] = {
|
||||||
|
id: existing.id,
|
||||||
|
...normalize(formData)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
function deleteAddress(id: number): boolean {
|
||||||
|
const index = addresses.value.findIndex(a => a.id === id)
|
||||||
|
if (index === -1) return false
|
||||||
|
|
||||||
|
addresses.value.splice(index, 1)
|
||||||
|
resetPagination()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPage(page: number) {
|
||||||
|
currentPage.value = page
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSearchQuery(query: string) {
|
||||||
|
searchQuery.value = query
|
||||||
|
currentPage.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetPagination() {
|
||||||
|
currentPage.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
initMockData()
|
||||||
|
|
||||||
|
return {
|
||||||
|
addresses,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
currentPage,
|
||||||
|
pageSize,
|
||||||
|
totalItems,
|
||||||
|
totalPages,
|
||||||
|
searchQuery,
|
||||||
|
filteredAddresses,
|
||||||
|
paginatedAddresses,
|
||||||
|
getAddressById,
|
||||||
|
addAddress,
|
||||||
|
updateAddress,
|
||||||
|
deleteAddress,
|
||||||
|
setPage,
|
||||||
|
setSearchQuery,
|
||||||
|
resetPagination
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -77,14 +77,42 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
password: string,
|
password: string,
|
||||||
confirm_password: string,
|
confirm_password: string,
|
||||||
lang?: string,
|
lang?: string,
|
||||||
|
company_name?: string,
|
||||||
|
company_email?: string,
|
||||||
|
company_address?: {
|
||||||
|
street: string
|
||||||
|
zipCode: string
|
||||||
|
city: string
|
||||||
|
country: string
|
||||||
|
},
|
||||||
|
regon?: string,
|
||||||
|
nip?: string,
|
||||||
|
vat?: string,
|
||||||
|
billing_address?: {
|
||||||
|
street: string
|
||||||
|
zipCode: string
|
||||||
|
city: string
|
||||||
|
country: string
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
|
const body: any = { first_name, last_name, email, password, confirm_password, lang: lang || 'en' }
|
||||||
|
|
||||||
|
// Add company information if provided
|
||||||
|
if (company_name) body.company_name = company_name
|
||||||
|
if (company_email) body.company_email = company_email
|
||||||
|
if (company_address) body.company_address = company_address
|
||||||
|
if (regon) body.regon = regon
|
||||||
|
if (nip) body.nip = nip
|
||||||
|
if (vat) body.vat = vat
|
||||||
|
if (billing_address) body.billing_address = billing_address
|
||||||
|
|
||||||
await useFetchJson('/api/v1/public/auth/register', {
|
await useFetchJson('/api/v1/public/auth/register', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ first_name, last_name, email, password, confirm_password, lang: lang || 'en' }),
|
body: JSON.stringify(body),
|
||||||
})
|
})
|
||||||
|
|
||||||
return { success: true, requiresVerification: true }
|
return { success: true, requiresVerification: true }
|
||||||
|
|||||||
129
bo/src/stores/cart.ts
Normal file
129
bo/src/stores/cart.ts
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
|
export interface CartItem {
|
||||||
|
id: number
|
||||||
|
productId: number
|
||||||
|
name: string
|
||||||
|
image: string
|
||||||
|
price: number
|
||||||
|
quantity: number
|
||||||
|
product_number: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeliveryMethod {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
price: number
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useCartStore = defineStore('cart', () => {
|
||||||
|
const items = ref<CartItem[]>([])
|
||||||
|
const selectedAddressId = ref<number | null>(null)
|
||||||
|
const selectedDeliveryMethodId = ref<number | null>(null)
|
||||||
|
const shippingCost = ref(0)
|
||||||
|
const vatRate = ref(0.23) // 23% VAT
|
||||||
|
const currentPage = ref(1)
|
||||||
|
const deliveryMethods = ref<DeliveryMethod[]>([
|
||||||
|
{ id: 1, name: 'Standard Delivery', price: 0, description: '5-7 business days' },
|
||||||
|
{ id: 2, name: 'Express Delivery', price: 15, description: '2-3 business days' },
|
||||||
|
{ id: 3, name: 'Priority Delivery', price: 30, description: 'Next business day' }
|
||||||
|
])
|
||||||
|
|
||||||
|
function initMockData() {
|
||||||
|
items.value = [
|
||||||
|
{ id: 1, productId: 101, name: 'Premium Widget Pro', product_number: 'NC209/7000', image: '/img/product-1.jpg', price: 129.99, quantity: 2 },
|
||||||
|
{ id: 2, productId: 102, name: 'Ultra Gadget X', product_number: 'NC234/6453', image: '/img/product-2.jpg', price: 89.50, quantity: 1 },
|
||||||
|
{ id: 3, productId: 103, name: 'Mega Tool Set', product_number: 'NC324/9030', image: '/img/product-3.jpg', price: 249.00, quantity: 3 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const productsTotal = computed(() => {
|
||||||
|
return items.value.reduce((sum, item) => sum + (item.price * item.quantity), 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
const vatAmount = computed(() => {
|
||||||
|
return productsTotal.value * vatRate.value
|
||||||
|
})
|
||||||
|
|
||||||
|
const orderTotal = computed(() => {
|
||||||
|
return productsTotal.value + shippingCost.value + vatAmount.value
|
||||||
|
})
|
||||||
|
|
||||||
|
const itemCount = computed(() => {
|
||||||
|
return items.value.reduce((sum, item) => sum + item.quantity, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
function updateQuantity(itemId: number, quantity: number) {
|
||||||
|
const item = items.value.find(i => i.id === itemId)
|
||||||
|
if (item) {
|
||||||
|
if (quantity <= 0) {
|
||||||
|
removeItem(itemId)
|
||||||
|
} else {
|
||||||
|
item.quantity = quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteProduct(id: number): boolean {
|
||||||
|
const index = items.value.findIndex(a => a.id === id)
|
||||||
|
if (index === -1) return false
|
||||||
|
|
||||||
|
items.value.splice(index, 1)
|
||||||
|
resetProductPagination()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetProductPagination() {
|
||||||
|
currentPage.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeItem(itemId: number) {
|
||||||
|
const index = items.value.findIndex(i => i.id === itemId)
|
||||||
|
if (index !== -1) {
|
||||||
|
items.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCart() {
|
||||||
|
items.value = []
|
||||||
|
selectedAddressId.value = null
|
||||||
|
selectedDeliveryMethodId.value = null
|
||||||
|
shippingCost.value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSelectedAddress(addressId: number | null) {
|
||||||
|
selectedAddressId.value = addressId
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDeliveryMethod(methodId: number) {
|
||||||
|
selectedDeliveryMethodId.value = methodId
|
||||||
|
const method = deliveryMethods.value.find(m => m.id === methodId)
|
||||||
|
if (method) {
|
||||||
|
shippingCost.value = method.price
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initMockData()
|
||||||
|
|
||||||
|
return {
|
||||||
|
items,
|
||||||
|
selectedAddressId,
|
||||||
|
selectedDeliveryMethodId,
|
||||||
|
shippingCost,
|
||||||
|
vatRate,
|
||||||
|
deliveryMethods,
|
||||||
|
productsTotal,
|
||||||
|
vatAmount,
|
||||||
|
orderTotal,
|
||||||
|
itemCount,
|
||||||
|
deleteProduct,
|
||||||
|
updateQuantity,
|
||||||
|
removeItem,
|
||||||
|
clearCart,
|
||||||
|
setSelectedAddress,
|
||||||
|
setDeliveryMethod
|
||||||
|
}
|
||||||
|
})
|
||||||
46
bo/src/stores/customer.ts
Normal file
46
bo/src/stores/customer.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import type { Address } from './address'
|
||||||
|
|
||||||
|
export interface CustomerData {
|
||||||
|
companyName: string
|
||||||
|
companyEmail: string
|
||||||
|
companyAddress: string
|
||||||
|
regon: string
|
||||||
|
nip: string
|
||||||
|
vat: string
|
||||||
|
billingAddressId: number | null
|
||||||
|
companyAddressId: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useCustomerStore = defineStore('customer', () => {
|
||||||
|
const customer = ref<CustomerData | null>(null)
|
||||||
|
const loading = ref(false)
|
||||||
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
|
const hasAccount = computed(() => customer.value !== null)
|
||||||
|
|
||||||
|
function setCustomer(data: CustomerData) {
|
||||||
|
customer.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCustomer() {
|
||||||
|
customer.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCustomer(data: Partial<CustomerData>) {
|
||||||
|
if (customer.value) {
|
||||||
|
customer.value = { ...customer.value, ...data }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
customer,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
hasAccount,
|
||||||
|
setCustomer,
|
||||||
|
clearCustomer,
|
||||||
|
updateCustomer
|
||||||
|
}
|
||||||
|
})
|
||||||
97
bo/src/stores/product.ts
Normal file
97
bo/src/stores/product.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useFetchJson } from '@/composable/useFetchJson'
|
||||||
|
|
||||||
|
export interface Product {
|
||||||
|
id: number
|
||||||
|
image: string
|
||||||
|
name: string
|
||||||
|
code: string
|
||||||
|
inStock: boolean
|
||||||
|
priceFrom: number
|
||||||
|
priceTo: number
|
||||||
|
count: number
|
||||||
|
description?: string
|
||||||
|
howToUse?: string
|
||||||
|
productDetails?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProductResponse {
|
||||||
|
items: Product[]
|
||||||
|
items_count: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useProductStore = defineStore('product', () => {
|
||||||
|
const productDescription = ref()
|
||||||
|
const currentProduct = ref<Product | null>(null)
|
||||||
|
const loading = ref(false)
|
||||||
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
|
async function getProductDescription(langId: number = 1) {
|
||||||
|
loading.value = true
|
||||||
|
error.value = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await useFetchJson(`/api/v1/restricted/product-description/get-product-description?productID=51&productShopID=1&productLangID=${langId}`)
|
||||||
|
productDescription.value = response
|
||||||
|
} catch (e: any) {
|
||||||
|
error.value = e?.message || 'Failed to load product description'
|
||||||
|
console.error('Failed to fetch product description:', e)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveProductDescription() {
|
||||||
|
try {
|
||||||
|
const data = await useFetchJson(
|
||||||
|
`/api/v1/restricted/product-description/save-product-description?productID=1&productShopID=1&productLangID=1`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(
|
||||||
|
{
|
||||||
|
description: productDescription.value.description,
|
||||||
|
description_short: productDescription.value.description_short,
|
||||||
|
meta_description: productDescription.value.meta_description,
|
||||||
|
available_now: productDescription.value.available_now,
|
||||||
|
usage: productDescription.value.usage
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return data
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function translateProductDescription(fromLangId: number, toLangId: number) {
|
||||||
|
loading.value = true
|
||||||
|
error.value = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await useFetchJson(`/api/v1/restricted/product-description/translate-product-description?productID=51&productShopID=1&productFromLangID=${fromLangId}&productToLangID=${toLangId}&model=OpenAI`)
|
||||||
|
productDescription.value = response
|
||||||
|
return response
|
||||||
|
} catch (e: any) {
|
||||||
|
error.value = e?.message || 'Failed to translate product description'
|
||||||
|
console.error('Failed to translate product description:', e)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCurrentProduct() {
|
||||||
|
currentProduct.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
productDescription,
|
||||||
|
currentProduct,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
getProductDescription,
|
||||||
|
clearCurrentProduct,
|
||||||
|
saveProductDescription,
|
||||||
|
translateProductDescription,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -51,8 +51,6 @@ const PrivacyComponent = computed(() =>
|
|||||||
defineAsyncComponent(() =>
|
defineAsyncComponent(() =>
|
||||||
import(`@/components/terms/${i18n.locale.value}_PrivacyPolicyView.vue`).catch(() => import('@/components/terms/en_PrivacyPolicyView.vue')),
|
import(`@/components/terms/${i18n.locale.value}_PrivacyPolicyView.vue`).catch(() => import('@/components/terms/en_PrivacyPolicyView.vue')),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -65,7 +63,6 @@ const PrivacyComponent = computed(() =>
|
|||||||
<UButton @click="showTherms = false" class="mx-auto px-12">{{ $t('general.close') }}</UButton>
|
<UButton @click="showTherms = false" class="mx-auto px-12">{{ $t('general.close') }}</UButton>
|
||||||
</template>
|
</template>
|
||||||
</UDrawer>
|
</UDrawer>
|
||||||
<!-- PrivacyPolicyView -->
|
|
||||||
<UDrawer v-model:open="showPrivacy" :overlay="false">
|
<UDrawer v-model:open="showPrivacy" :overlay="false">
|
||||||
<template #body>
|
<template #body>
|
||||||
<component :is="PrivacyComponent" />
|
<component :is="PrivacyComponent" />
|
||||||
@@ -78,9 +75,9 @@ const PrivacyComponent = computed(() =>
|
|||||||
<div class="text-center mb-15">
|
<div class="text-center mb-15">
|
||||||
<div
|
<div
|
||||||
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
||||||
<UIcon name="i-heroicons-clock" class="w-8 h-8" />
|
<UIcon name="carbon:ibm-webmethods-b2b-integration" class="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">TimeTracker</h1>
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">B2B</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-md flex flex-col gap-4">
|
<div class="w-full max-w-md flex flex-col gap-4">
|
||||||
<UForm :validate="validate" @submit="handleLogin" class="space-y-5">
|
<UForm :validate="validate" @submit="handleLogin" class="space-y-5">
|
||||||
@@ -96,7 +93,8 @@ const PrivacyComponent = computed(() =>
|
|||||||
|
|
||||||
<UFormField :label="$t('general.password')" name="password" required class="w-full dark:text-white text-black">
|
<UFormField :label="$t('general.password')" name="password" required class="w-full dark:text-white text-black">
|
||||||
<UInput v-model="password" :placeholder="$t('general.enter_your_password')"
|
<UInput v-model="password" :placeholder="$t('general.enter_your_password')"
|
||||||
:type="showPassword ? 'text' : 'password'" class="w-full placeholder:text-(--placeholder)" :ui="{ trailing: 'pe-1' }">
|
:type="showPassword ? 'text' : 'password'" class="w-full placeholder:text-(--placeholder)"
|
||||||
|
:ui="{ trailing: 'pe-1' }">
|
||||||
<template #trailing>
|
<template #trailing>
|
||||||
<UIcon color="neutral" variant="link" size="sm" :name="showPassword ? 'i-lucide-eye-off' : 'i-lucide-eye'"
|
<UIcon color="neutral" variant="link" size="sm" :name="showPassword ? 'i-lucide-eye-off' : 'i-lucide-eye'"
|
||||||
:aria-label="showPassword ? 'Hide password' : 'Show password'" :aria-pressed="showPassword"
|
:aria-label="showPassword ? 'Hide password' : 'Show password'" :aria-pressed="showPassword"
|
||||||
@@ -107,24 +105,20 @@ const PrivacyComponent = computed(() =>
|
|||||||
|
|
||||||
<div class="flex items-center justify-between w-full dark:text-white text-black">
|
<div class="flex items-center justify-between w-full dark:text-white text-black">
|
||||||
<button variant="link" size="sm" @click="goToPasswordRecovery"
|
<button variant="link" size="sm" @click="goToPasswordRecovery"
|
||||||
class="text-[15px] w-full flex justify-end text-(--color-blue-600) dark:text-(--color-blue-500) cursor-pointer">
|
class="text-[15px] w-full flex justify-end text-(--accent-blue-light) dark:text-(--accent-blue-dark) cursor-pointer">
|
||||||
{{ $t('general.forgot_password') }}?
|
{{ $t('general.forgot_password') }}?
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<UButton type="submit" :loading="authStore.loading"
|
<UButton type="submit" :loading="authStore.loading"
|
||||||
class="w-full flex justify-center text-white bg-(--color-blue-600) dark:bg-(--color-blue-500) cursor-pointer">
|
class="w-full flex justify-center text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) cursor-pointer">
|
||||||
{{ $t('general.sign_in') }}
|
{{ $t('general.sign_in') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
</UForm>
|
</UForm>
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<div class="flex items-center gap-3 my-1">
|
<div class="flex items-center gap-3 my-1">
|
||||||
<div class="flex-1 h-px bg-gray-200 dark:bg-gray-700" />
|
<div class="flex-1 h-px bg-gray-200 dark:dark:hover:bg-(--gray-dark)" />
|
||||||
<span class="text-xs text-gray-400 dark:text-gray-500">{{ $t('general.or') }}</span>
|
<span class="text-xs text-gray-400 dark:text-gray-500">{{ $t('general.or') }}</span>
|
||||||
<div class="flex-1 h-px bg-gray-200 dark:bg-gray-700" />
|
<div class="flex-1 h-px bg-gray-200 dark:dark:hover:bg-(--gray-dark)" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Google Sign In -->
|
|
||||||
<UButton type="button" color="neutral" variant="outline" size="lg" block :disabled="authStore.loading"
|
<UButton type="button" color="neutral" variant="outline" size="lg" block :disabled="authStore.loading"
|
||||||
@click="authStore.loginWithGoogle()"
|
@click="authStore.loginWithGoogle()"
|
||||||
class="flex items-center justify-center gap-2 dark:text-white text-black cursor-pointer">
|
class="flex items-center justify-center gap-2 dark:text-white text-black cursor-pointer">
|
||||||
@@ -149,18 +143,18 @@ const PrivacyComponent = computed(() =>
|
|||||||
<p class="dark:text-white text-black">
|
<p class="dark:text-white text-black">
|
||||||
{{ $t('general.dont_have_an_account') }}?
|
{{ $t('general.dont_have_an_account') }}?
|
||||||
<button variant="link" size="sm"
|
<button variant="link" size="sm"
|
||||||
class="text-[15px] text-(--color-blue-600) dark:text-(--color-blue-500) cursor-pointer"
|
class="text-[15px] text-(--accent-blue-light) dark:text-(--accent-blue-dark) cursor-pointer"
|
||||||
@click="goToRegister">{{ $t('general.create_account_now') }}</button>
|
@click="goToRegister">{{ $t('general.create_account_now') }}</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-8 text-center text-xs dark:text-white text-black">
|
<p class="mt-8 text-center text-xs dark:text-white text-black">
|
||||||
{{ $t('general.by_signing_in_you_agree_to_our') }}
|
{{ $t('general.by_signing_in_you_agree_to_our') }}
|
||||||
<span @click="showTherms = !showTherms"
|
<span @click="showTherms = !showTherms"
|
||||||
class="cursor-pointer underline text-(--color-blue-600) dark:text-(--color-blue-500) cursor-pointer">{{
|
class="cursor-pointer underline text-(--accent-blue-light) dark:text-(--accent-blue-dark) cursor-pointer">{{
|
||||||
$t('general.terms_of_service') }}</span>
|
$t('general.terms_of_service') }}</span>
|
||||||
{{ $t('general.and') }}
|
{{ $t('general.and') }}
|
||||||
<span @click="showPrivacy = !showPrivacy"
|
<span @click="showPrivacy = !showPrivacy"
|
||||||
class="cursor-pointer underline text-(--color-blue-600) dark:text-(--color-blue-500) cursor-pointer">{{
|
class="cursor-pointer underline text-(--accent-blue-light) dark:text-(--accent-blue-dark) cursor-pointer">{{
|
||||||
$t('general.privacy_policy') }}</span>
|
$t('general.privacy_policy') }}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ function validate(): FormError[] {
|
|||||||
<div class="text-center mb-15">
|
<div class="text-center mb-15">
|
||||||
<div
|
<div
|
||||||
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
||||||
<UIcon name="i-heroicons-clock" class="w-8 h-8" />
|
<UIcon name="carbon:ibm-webmethods-b2b-integration" class="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">TimeTracker</h1>
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">B2B</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-md flex flex-col gap-4">
|
<div class="w-full max-w-md flex flex-col gap-4">
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ function validate(): FormError[] {
|
|||||||
</UFormField>
|
</UFormField>
|
||||||
|
|
||||||
<UButton type="submit" block :loading="authStore.loading"
|
<UButton type="submit" block :loading="authStore.loading"
|
||||||
class="text-white bg-(--color-blue-600) dark:bg-(--color-blue-500) cursor-pointer">
|
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) cursor-pointer">
|
||||||
{{ $t('general.send_password_reset_link') }}
|
{{ $t('general.send_password_reset_link') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
</UForm>
|
</UForm>
|
||||||
@@ -88,13 +88,13 @@ function validate(): FormError[] {
|
|||||||
<button color="neutral" variant="outline" :loading="authStore.loading"
|
<button color="neutral" variant="outline" :loading="authStore.loading"
|
||||||
class="w-full flex items-center gap-2 justify-center text-[15px] dark:text-white text-black cursor-pointer"
|
class="w-full flex items-center gap-2 justify-center text-[15px] dark:text-white text-black cursor-pointer"
|
||||||
@click="goToLogin">
|
@click="goToLogin">
|
||||||
<UIcon name="mingcute:arrow-left-line" class="text-(--color-blue-600) dark:text-(--color-blue-500) text-[16px]" />
|
<UIcon name="mingcute:arrow-left-line" class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) text-[16px]" />
|
||||||
{{ $t('general.back_to_sign_in') }}
|
{{ $t('general.back_to_sign_in') }}
|
||||||
</button>
|
</button>
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-400">
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
{{ $t('general.dont_have_an_account') }}
|
{{ $t('general.dont_have_an_account') }}
|
||||||
<button variant="link" size="sm" @click="goToRegister"
|
<button variant="link" size="sm" @click="goToRegister"
|
||||||
class=" text-[15px] text-(--color-blue-600) dark:text-(--color-blue-500) cursor-pointer">{{
|
class=" text-[15px] text-(--accent-blue-light) dark:text-(--accent-blue-dark) cursor-pointer">{{
|
||||||
$t('general.create_account_now') }}
|
$t('general.create_account_now') }}
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
<div class="text-center mb-15">
|
<div class="text-center mb-15">
|
||||||
<div
|
<div
|
||||||
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
||||||
<UIcon name="i-heroicons-clock" class="w-8 h-8" />
|
<UIcon name="carbon:ibm-webmethods-b2b-integration" class="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">TimeTracker</h1>
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">B2B</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-md">
|
<div class="w-full max-w-md">
|
||||||
<UForm :validate="validate" @submit="handleRegister" class="flex flex-col gap-3">
|
<UForm :validate="validate" @submit="handleRegister" class="flex flex-col gap-3">
|
||||||
@@ -82,12 +82,12 @@
|
|||||||
<span class="dark:text-white text-black">
|
<span class="dark:text-white text-black">
|
||||||
{{ $t('general.i_agree_to_the') }}
|
{{ $t('general.i_agree_to_the') }}
|
||||||
<span @click="showTherms = !showTherms"
|
<span @click="showTherms = !showTherms"
|
||||||
class="cursor-pointer underline text-(--color-blue-600) dark:text-(--color-blue-500)">{{
|
class="cursor-pointer underline text-(--accent-blue-light) dark:text-(--accent-blue-dark)">{{
|
||||||
$t('general.terms_of_service')
|
$t('general.terms_of_service')
|
||||||
}}</span>
|
}}</span>
|
||||||
{{ $t('general.and') }}
|
{{ $t('general.and') }}
|
||||||
<span @click="showPrivacy = !showPrivacy"
|
<span @click="showPrivacy = !showPrivacy"
|
||||||
class="cursor-pointer underline text-(--color-blue-600) dark:text-(--color-blue-500)">{{
|
class="cursor-pointer underline text-(--accent-blue-light) dark:text-(--accent-blue-dark)">{{
|
||||||
$t('general.privacy_policy')
|
$t('general.privacy_policy')
|
||||||
}}</span>
|
}}</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
</UCheckbox>
|
</UCheckbox>
|
||||||
|
|
||||||
<UButton type="submit" block :loading="authStore.loading" :disabled="!acceptTerms"
|
<UButton type="submit" block :loading="authStore.loading" :disabled="!acceptTerms"
|
||||||
class="text-white bg-(--color-blue-600) dark:bg-(--color-blue-500) cursor-pointer">
|
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) cursor-pointer">
|
||||||
{{ $t('general.create_account') }}
|
{{ $t('general.create_account') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
{{ $t('general.already_have_an_account') }}
|
{{ $t('general.already_have_an_account') }}
|
||||||
</p>
|
</p>
|
||||||
<UButton color="neutral" variant="outline" :loading="authStore.loading"
|
<UButton color="neutral" variant="outline" :loading="authStore.loading"
|
||||||
class="w-full flex justify-center dark:text-white hover:text-white cursor-pointer hover:bg-(--color-blue-600) dark:hover:bg-(--color-blue-500) border border-(--border-light)! dark:border-(--border-dark)!"
|
class="w-full flex justify-center dark:text-white hover:text-white cursor-pointer hover:bg-(--accent-blue-light) dark:hover:bg-(--accent-blue-dark) border border-(--border-light)! dark:border-(--border-dark)!"
|
||||||
@click="goToLogin">{{ $t('general.sign_in') }}</UButton>
|
@click="goToLogin">{{ $t('general.sign_in') }}</UButton>
|
||||||
</div>
|
</div>
|
||||||
</UForm>
|
</UForm>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch, onMounted, type Ref } from 'vue'
|
import { ref, computed, watch, type Ref } from 'vue'
|
||||||
import { Bar } from 'vue-chartjs'
|
import { Bar } from 'vue-chartjs'
|
||||||
import {
|
import {
|
||||||
Chart as ChartJS,
|
Chart as ChartJS,
|
||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
CategoryScale,
|
CategoryScale,
|
||||||
LinearScale,
|
LinearScale,
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import { getRepos, getYears, getQuarters, getIssues, type QuarterData, type IssueTimeSummary } from '@/composable/useRepoApi'
|
import { getYears, getQuarters, getIssues, type QuarterData, type IssueTimeSummary } from '@/composable/useRepoApi'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { i18n } from '@/plugins/02_i18n'
|
import { i18n } from '@/plugins/02_i18n'
|
||||||
import type { TableColumn } from '@nuxt/ui'
|
import type { TableColumn } from '@nuxt/ui'
|
||||||
@@ -49,7 +49,7 @@ async function loadData<T>(fetchFn: () => Promise<any>, target: Ref<T[]>, errorM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => loadData(() => getRepos(), repos, t('repo_chart.failed_to_load_repositories')))
|
// onMounted(() => loadData(() => getRepos(), repos, t('repo_chart.failed_to_load_repositories')))
|
||||||
|
|
||||||
watch(selectedRepo, async (newRepo) => {
|
watch(selectedRepo, async (newRepo) => {
|
||||||
selectedYear.value = null
|
selectedYear.value = null
|
||||||
@@ -181,8 +181,8 @@ const columns = computed<TableColumn<IssueTimeSummary>[]>(() => [
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container mx-auto">
|
||||||
<div class="p-6 bg-white dark:bg-(--black) min-h-screen font-sans">
|
<div class="p-6 bg-(--main-light) dark:bg-(--black) font-sans">
|
||||||
<h1 class="text-2xl font-bold mb-6 text-black dark:text-white">{{ $t('repo_chart.repository_work_chart') }}
|
<h1 class="text-2xl font-bold mb-6 text-black dark:text-white">{{ $t('repo_chart.repository_work_chart') }}
|
||||||
</h1>
|
</h1>
|
||||||
<div v-if="error" class="mb-4 p-3 bg-red-100 text-red-700 rounded">{{ error }}</div>
|
<div v-if="error" class="mb-4 p-3 bg-red-100 text-red-700 rounded">{{ error }}</div>
|
||||||
@@ -195,14 +195,14 @@ const columns = computed<TableColumn<IssueTimeSummary>[]>(() => [
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="authStore.isAuthenticated" class="flex flex-wrap gap-4 mb-6">
|
<div v-if="authStore.isAuthenticated" class="flex flex-wrap gap-4 mb-6">
|
||||||
<div class="flex flex-col min-w-[192px]">
|
<div class="flex flex-col">
|
||||||
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ $t('repo_chart.repository')
|
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ $t('repo_chart.repository')
|
||||||
}}</label>
|
}}</label>
|
||||||
<USelect v-model="selectedRepo" :items="items" :disabled="loading"
|
<USelect v-model="selectedRepo" :items="items" :disabled="loading"
|
||||||
:placeholder="$t('repo_chart.select_a_repository')" class="dark:text-white text-black " />
|
:placeholder="$t('repo_chart.select_a_repository')" class="dark:text-white text-black " />
|
||||||
<!-- Select a repository -->
|
<!-- Select a repository -->
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col min-w-[160px]">
|
<div class="flex flex-col">
|
||||||
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ $t('repo_chart.year')
|
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ $t('repo_chart.year')
|
||||||
}}</label>
|
}}</label>
|
||||||
<USelect v-model="selectedYear" :items="yearItems"
|
<USelect v-model="selectedYear" :items="yearItems"
|
||||||
@@ -210,7 +210,7 @@ const columns = computed<TableColumn<IssueTimeSummary>[]>(() => [
|
|||||||
:placeholder="$t('repo_chart.select_a_year')"
|
:placeholder="$t('repo_chart.select_a_year')"
|
||||||
class="dark:text-white text-black placeholder:text-(--placeholder)" />
|
class="dark:text-white text-black placeholder:text-(--placeholder)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col min-w-[192px]">
|
<div class="flex flex-col">
|
||||||
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ $t('repo_chart.quarter')
|
<label class="mb-1 text-sm font-medium text-black dark:text-white">{{ $t('repo_chart.quarter')
|
||||||
}}</label>
|
}}</label>
|
||||||
<USelect v-model="selectedQuarter" :items="quarterItems"
|
<USelect v-model="selectedQuarter" :items="quarterItems"
|
||||||
@@ -241,12 +241,12 @@ const columns = computed<TableColumn<IssueTimeSummary>[]>(() => [
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="selectedQuarter && !loading && authStore.isAuthenticated && !hasIssues"
|
<div v-else-if="selectedQuarter && !loading && authStore.isAuthenticated && !hasIssues"
|
||||||
class="mt-4 p-3 dark:bg-(--black) bg-white border border-(--border-light) dark:border-(--border-dark) dark:text-white! text-black rounded">
|
class="mt-4 p-3 dark:bg-(--black) bg-(--main-light) border border-(--border-light) dark:border-(--border-dark) dark:text-white! text-black rounded">
|
||||||
{{ $t('validate_error.no_issues_for_quarter') }}.
|
{{ $t('validate_error.no_issues_for_quarter') }}.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="!loading && authStore.isAuthenticated"
|
<div v-else-if="!loading && authStore.isAuthenticated"
|
||||||
class="p-3 dark:bg-(--black) bg-white border border-(--border-light) dark:border-(--border-dark) rounded dark:text-white! text-black">
|
class="p-3 dark:bg-(--black) bg-(--main-light) border border-(--border-light) dark:border-(--border-dark) rounded dark:text-white! text-black">
|
||||||
<span v-if="!selectedRepo">{{ $t('repo_chart.select_repo_to_view_data') }}</span>
|
<span v-if="!selectedRepo">{{ $t('repo_chart.select_repo_to_view_data') }}</span>
|
||||||
<span v-else-if="!selectedYear">{{ $t('repo_chart.select_year_to_view_data') }}</span>
|
<span v-else-if="!selectedYear">{{ $t('repo_chart.select_year_to_view_data') }}</span>
|
||||||
<span v-else-if="!selectedQuarter">{{ $t('repo_chart.select_quarter_to_view_issues') }}</span>
|
<span v-else-if="!selectedQuarter">{{ $t('repo_chart.select_quarter_to_view_issues') }}</span>
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ function validate(): FormError[] {
|
|||||||
<div class="text-center mb-15">
|
<div class="text-center mb-15">
|
||||||
<div
|
<div
|
||||||
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
||||||
<UIcon name="i-heroicons-clock" class="w-8 h-8" />
|
<UIcon name="carbon:ibm-webmethods-b2b-integration" class="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">TimeTracker</h1>
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">B2B</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-md flex flex-col gap-4">
|
<div class="w-full max-w-md flex flex-col gap-4">
|
||||||
|
|
||||||
@@ -110,13 +110,13 @@ function validate(): FormError[] {
|
|||||||
</UFormField>
|
</UFormField>
|
||||||
|
|
||||||
<UButton type="submit" block :loading="authStore.loading"
|
<UButton type="submit" block :loading="authStore.loading"
|
||||||
class="text-white! bg-(--color-blue-600) dark:bg-(--color-blue-500) cursor-pointer">
|
class="text-white! bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) cursor-pointer">
|
||||||
{{ $t('general.reset_password') }}
|
{{ $t('general.reset_password') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
|
|
||||||
<div class="text-center border-t dark:border-(--border-dark) border-(--border-light) pt-4">
|
<div class="text-center border-t dark:border-(--border-dark) border-(--border-light) pt-4">
|
||||||
<button color="neutral" variant="ghost" @click="goToLogin"
|
<button color="neutral" variant="ghost" @click="goToLogin"
|
||||||
class="text-[15px] flex items-center gap-2 text-(--color-blue-600) dark:text-(--color-blue-500) cursor-pointer">
|
class="text-[15px] flex items-center gap-2 text-(--accent-blue-light) dark:text-(--accent-blue-dark) cursor-pointer">
|
||||||
<UIcon name="mingcute:arrow-left-line" />
|
<UIcon name="mingcute:arrow-left-line" />
|
||||||
{{ $t('general.back_to_sign_in') }}
|
{{ $t('general.back_to_sign_in') }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ function goToLogin() {
|
|||||||
<div class="text-center mb-8">
|
<div class="text-center mb-8">
|
||||||
<div
|
<div
|
||||||
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary-500 text-white mb-4 shadow-lg shadow-primary-500/30">
|
||||||
<UIcon name="i-heroicons-clock" class="w-8 h-8" />
|
<UIcon name="carbon:ibm-webmethods-b2b-integration" class="w-8 h-8" />
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">TimeTracker</h1>
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">B2B</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<UCard class="shadow-xl shadow-gray-200/50 dark:shadow-gray-900/50">
|
<UCard class="shadow-xl shadow-gray-200/50 dark:shadow-gray-900/50">
|
||||||
@@ -133,7 +133,7 @@ function goToLogin() {
|
|||||||
<p class="text-sm text-gray-600 dark:text-gray-400">
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
{{ $t('verify_email.already_registered') }}
|
{{ $t('verify_email.already_registered') }}
|
||||||
<button variant="link" size="sm" @click="goToLogin"
|
<button variant="link" size="sm" @click="goToLogin"
|
||||||
class="cursor-pointer text-(--color-blue-600) dark:text-(--color-blue-500)"> {{ $t('general.sign_in')
|
class="cursor-pointer text-(--accent-blue-light) dark:text-(--accent-blue-dark)"> {{ $t('general.sign_in')
|
||||||
}}
|
}}
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
719
bun.lock
Normal file
719
bun.lock
Normal file
@@ -0,0 +1,719 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 0,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/ui": "^4.5.1",
|
||||||
|
"chart.js": "^4.5.1",
|
||||||
|
"dompurify": "^3.3.3",
|
||||||
|
"vue-chartjs": "^5.3.3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||||
|
|
||||||
|
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
||||||
|
|
||||||
|
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
|
||||||
|
|
||||||
|
"@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
|
||||||
|
|
||||||
|
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
||||||
|
|
||||||
|
"@capsizecss/unpack": ["@capsizecss/unpack@4.0.0", "", { "dependencies": { "fontkitten": "^1.0.0" } }, "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA=="],
|
||||||
|
|
||||||
|
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
|
||||||
|
|
||||||
|
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
|
||||||
|
|
||||||
|
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
|
||||||
|
|
||||||
|
"@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
|
||||||
|
|
||||||
|
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
|
||||||
|
|
||||||
|
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
|
||||||
|
|
||||||
|
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
|
||||||
|
|
||||||
|
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
|
||||||
|
|
||||||
|
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
|
||||||
|
|
||||||
|
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
|
||||||
|
|
||||||
|
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
|
||||||
|
|
||||||
|
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
|
||||||
|
|
||||||
|
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
|
||||||
|
|
||||||
|
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
|
||||||
|
|
||||||
|
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
|
||||||
|
|
||||||
|
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
|
||||||
|
|
||||||
|
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
|
||||||
|
|
||||||
|
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
|
||||||
|
|
||||||
|
"@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="],
|
||||||
|
|
||||||
|
"@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="],
|
||||||
|
|
||||||
|
"@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
|
||||||
|
|
||||||
|
"@floating-ui/vue": ["@floating-ui/vue@1.1.11", "", { "dependencies": { "@floating-ui/dom": "^1.7.6", "@floating-ui/utils": "^0.2.11", "vue-demi": ">=0.13.0" } }, "sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw=="],
|
||||||
|
|
||||||
|
"@iconify/collections": ["@iconify/collections@1.0.656", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-X17vsrStihw4gEdgT2+46E+ioM506JJh/Jp/reJGZ2URcWhhS4aMnsi9onoGTQ8ppydZ0GJrPuvOyhySiteKsA=="],
|
||||||
|
|
||||||
|
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||||
|
|
||||||
|
"@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="],
|
||||||
|
|
||||||
|
"@iconify/vue": ["@iconify/vue@5.0.0", "", { "dependencies": { "@iconify/types": "^2.0.0" }, "peerDependencies": { "vue": ">=3" } }, "sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg=="],
|
||||||
|
|
||||||
|
"@internationalized/date": ["@internationalized/date@3.11.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q=="],
|
||||||
|
|
||||||
|
"@internationalized/number": ["@internationalized/number@3.6.5", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g=="],
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
|
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||||
|
|
||||||
|
"@kurkle/color": ["@kurkle/color@0.3.4", "", {}, "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="],
|
||||||
|
|
||||||
|
"@nuxt/devtools-kit": ["@nuxt/devtools-kit@3.2.2", "", { "dependencies": { "@nuxt/kit": "^4.3.1", "execa": "^8.0.1" }, "peerDependencies": { "vite": ">=6.0" } }, "sha512-07E1phqoVPNlexlkrYuOMPhTzLIRjcl9iEqyc/vZLH2zWeH/T1X3v+RLTVW5Oio40f/XBp9yQuyihmX34ddjgQ=="],
|
||||||
|
|
||||||
|
"@nuxt/fonts": ["@nuxt/fonts@0.14.0", "", { "dependencies": { "@nuxt/devtools-kit": "^3.2.1", "@nuxt/kit": "^4.2.2", "consola": "^3.4.2", "defu": "^6.1.4", "fontless": "^0.2.1", "h3": "^1.15.5", "magic-regexp": "^0.10.0", "ofetch": "^1.5.1", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unifont": "^0.7.4", "unplugin": "^3.0.0", "unstorage": "^1.17.4" } }, "sha512-4uXQl9fa5F4ibdgU8zomoOcyMdnwgdem+Pi8JEqeDYI5yPR32Kam6HnuRr47dTb97CstaepAvXPWQUUHMtjsFQ=="],
|
||||||
|
|
||||||
|
"@nuxt/icon": ["@nuxt/icon@2.2.1", "", { "dependencies": { "@iconify/collections": "^1.0.641", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.0", "@iconify/vue": "^5.0.0", "@nuxt/devtools-kit": "^3.1.1", "@nuxt/kit": "^4.2.2", "consola": "^3.4.2", "local-pkg": "^1.1.2", "mlly": "^1.8.0", "ohash": "^2.0.11", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinyglobby": "^0.2.15" } }, "sha512-GI840yYGuvHI0BGDQ63d6rAxGzG96jQcWrnaWIQKlyQo/7sx9PjXkSHckXUXyX1MCr9zY6U25Td6OatfY6Hklw=="],
|
||||||
|
|
||||||
|
"@nuxt/kit": ["@nuxt/kit@4.3.1", "", { "dependencies": { "c12": "^3.3.3", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.8", "ignore": "^7.0.5", "jiti": "^2.6.1", "klona": "^2.0.6", "mlly": "^1.8.0", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "rc9": "^3.0.0", "scule": "^1.3.0", "semver": "^7.7.4", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unctx": "^2.5.0", "untyped": "^2.0.0" } }, "sha512-UjBFt72dnpc+83BV3OIbCT0YHLevJtgJCHpxMX0YRKWLDhhbcDdUse87GtsQBrjvOzK7WUNUYLDS/hQLYev5rA=="],
|
||||||
|
|
||||||
|
"@nuxt/schema": ["@nuxt/schema@4.3.1", "", { "dependencies": { "@vue/shared": "^3.5.27", "defu": "^6.1.4", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "std-env": "^3.10.0" } }, "sha512-S+wHJdYDuyk9I43Ej27y5BeWMZgi7R/UVql3b3qtT35d0fbpXW7fUenzhLRCCDC6O10sjguc6fcMcR9sMKvV8g=="],
|
||||||
|
|
||||||
|
"@nuxt/ui": ["@nuxt/ui@4.5.1", "", { "dependencies": { "@floating-ui/dom": "^1.7.5", "@iconify/vue": "^5.0.0", "@internationalized/date": "^3.11.0", "@internationalized/number": "^3.6.5", "@nuxt/fonts": "^0.14.0", "@nuxt/icon": "^2.2.1", "@nuxt/kit": "^4.3.1", "@nuxt/schema": "^4.3.1", "@nuxtjs/color-mode": "^3.5.2", "@standard-schema/spec": "^1.1.0", "@tailwindcss/postcss": "^4.2.1", "@tailwindcss/vite": "^4.2.1", "@tanstack/vue-table": "^8.21.3", "@tanstack/vue-virtual": "^3.13.19", "@tiptap/core": "^3.20.0", "@tiptap/extension-bubble-menu": "^3.20.0", "@tiptap/extension-code": "^3.20.0", "@tiptap/extension-collaboration": "^3.20.0", "@tiptap/extension-drag-handle": "^3.20.0", "@tiptap/extension-drag-handle-vue-3": "^3.20.0", "@tiptap/extension-floating-menu": "^3.20.0", "@tiptap/extension-horizontal-rule": "^3.20.0", "@tiptap/extension-image": "^3.20.0", "@tiptap/extension-mention": "^3.20.0", "@tiptap/extension-node-range": "^3.20.0", "@tiptap/extension-placeholder": "^3.20.0", "@tiptap/markdown": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/starter-kit": "^3.20.0", "@tiptap/suggestion": "^3.20.0", "@tiptap/vue-3": "^3.20.0", "@unhead/vue": "^2.1.10", "@vueuse/core": "^14.2.1", "@vueuse/integrations": "^14.2.1", "@vueuse/shared": "^14.2.1", "colortranslator": "^5.0.0", "consola": "^3.4.2", "defu": "^6.1.4", "embla-carousel-auto-height": "^8.6.0", "embla-carousel-auto-scroll": "^8.6.0", "embla-carousel-autoplay": "^8.6.0", "embla-carousel-class-names": "^8.6.0", "embla-carousel-fade": "^8.6.0", "embla-carousel-vue": "^8.6.0", "embla-carousel-wheel-gestures": "^8.1.0", "fuse.js": "^7.1.0", "hookable": "^5.5.3", "knitwork": "^1.3.0", "magic-string": "^0.30.21", "mlly": "^1.8.0", "motion-v": "^1.10.3", "ohash": "^2.0.11", "pathe": "^2.0.3", "reka-ui": "2.8.2", "scule": "^1.3.0", "tailwind-merge": "^3.5.0", "tailwind-variants": "^3.2.2", "tailwindcss": "^4.2.1", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unplugin": "^3.0.0", "unplugin-auto-import": "^21.0.0", "unplugin-vue-components": "^31.0.0", "vaul-vue": "0.4.1", "vue-component-type-helpers": "^3.2.5" }, "peerDependencies": { "@inertiajs/vue3": "^2.0.7", "@nuxt/content": "^3.0.0", "joi": "^18.0.0", "superstruct": "^2.0.0", "tailwindcss": "^4.0.0", "typescript": "^5.9.3", "valibot": "^1.0.0", "vue-router": "^4.5.0", "yup": "^1.7.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["@inertiajs/vue3", "@nuxt/content", "joi", "superstruct", "valibot", "vue-router", "yup", "zod"], "bin": { "nuxt-ui": "cli/index.mjs" } }, "sha512-5hWgreVPX6EsNCZNoOd2o7m9fTA3fwUMDw+zeYTSAjhSKtAuvkZrBtmez4MUeTv+LO1gknesgvErdIvlUnElTg=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode": ["@nuxtjs/color-mode@3.5.2", "", { "dependencies": { "@nuxt/kit": "^3.13.2", "pathe": "^1.1.2", "pkg-types": "^1.2.1", "semver": "^7.6.3" } }, "sha512-cC6RfgZh3guHBMLLjrBB2Uti5eUoGM9KyauOaYS9ETmxNWBMTvpgjvSiSJp1OFljIXPIqVTJ3xtJpSNZiO3ZaA=="],
|
||||||
|
|
||||||
|
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
||||||
|
|
||||||
|
"@remirror/core-constants": ["@remirror/core-constants@3.0.0", "", {}, "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg=="],
|
||||||
|
|
||||||
|
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||||
|
|
||||||
|
"@swc/helpers": ["@swc/helpers@0.5.19", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.2.1", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "postcss": "^8.5.6", "tailwindcss": "4.2.1" } }, "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="],
|
||||||
|
|
||||||
|
"@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="],
|
||||||
|
|
||||||
|
"@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.19", "", {}, "sha512-/BMP7kNhzKOd7wnDeB8NrIRNLwkf5AhCYCvtfZV2GXWbBieFm/el0n6LOAXlTi6ZwHICSNnQcIxRCWHrLzDY+g=="],
|
||||||
|
|
||||||
|
"@tanstack/vue-table": ["@tanstack/vue-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "vue": ">=3.2" } }, "sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw=="],
|
||||||
|
|
||||||
|
"@tanstack/vue-virtual": ["@tanstack/vue-virtual@3.13.19", "", { "dependencies": { "@tanstack/virtual-core": "3.13.19" }, "peerDependencies": { "vue": "^2.7.0 || ^3.0.0" } }, "sha512-07Fp1TYuIziB4zIDA/moeDKHODePy3K1fN4c4VIAGnkxo1+uOvBJP7m54CoxKiQX6Q9a1dZnznrwOg9C86yvvA=="],
|
||||||
|
|
||||||
|
"@tiptap/core": ["@tiptap/core@3.20.0", "", { "peerDependencies": { "@tiptap/pm": "^3.20.0" } }, "sha512-aC9aROgia/SpJqhsXFiX9TsligL8d+oeoI8W3u00WI45s0VfsqjgeKQLDLF7Tu7hC+7F02teC84SAHuup003VQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-blockquote": ["@tiptap/extension-blockquote@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-LQzn6aGtL4WXz2+rYshl/7/VnP2qJTpD7fWL96GXAzhqviPEY1bJES7poqJb3MU/gzl8VJUVzVzU1VoVfUKlbA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-bold": ["@tiptap/extension-bold@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-sQklEWiyf58yDjiHtm5vmkVjfIc/cBuSusmCsQ0q9vGYnEF1iOHKhGpvnCeEXNeqF3fiJQRlquzt/6ymle3Iwg=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-bubble-menu": ["@tiptap/extension-bubble-menu@3.20.0", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-MDosUfs8Tj+nwg8RC+wTMWGkLJORXmbR6YZgbiX4hrc7G90Gopdd6kj6ht5/T8t7dLLaX7N0+DEHdUEPGED7dw=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-bullet-list": ["@tiptap/extension-bullet-list@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-OcKMeopBbqWzhSi6o8nNz0aayogg1sfOAhto3NxJu3Ya32dwBFqmHXSYM6uW4jOphNvVPyjiq9aNRh3qTdd1dw=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-code": ["@tiptap/extension-code@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-TYDWFeSQ9umiyrqsT6VecbuhL8XIHkUhO+gEk0sVvH67ZLwjFDhAIIgWIr1/dbIGPcvMZM19E7xUUhAdIaXaOQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-code-block": ["@tiptap/extension-code-block@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-lBbmNek14aCjrHcBcq3PRqWfNLvC6bcRa2Osc6e/LtmXlcpype4f6n+Yx+WZ+f2uUh0UmDRCz7BEyUETEsDmlQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-collaboration": ["@tiptap/extension-collaboration@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/y-tiptap": "^3.0.2", "yjs": "^13" } }, "sha512-JItmI4U0i4kqorO114u24hM9k945IdaQ6Uc2DEtPBFFuS8cepJf2zw+ulAT1kAx6ZRiNvNpT9M7w+J0mWRn+Sg=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-document": ["@tiptap/extension-document@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-oJfLIG3vAtZo/wg29WiBcyWt22KUgddpP8wqtCE+kY5Dw8znLR9ehNmVWlSWJA5OJUMO0ntAHx4bBT+I2MBd5w=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-drag-handle": ["@tiptap/extension-drag-handle@3.20.0", "", { "dependencies": { "@floating-ui/dom": "^1.6.13" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/extension-collaboration": "^3.20.0", "@tiptap/extension-node-range": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/y-tiptap": "^3.0.2" } }, "sha512-CzLRyxZe5QddQey0RUWJUvICyhuRnU/jvzMIYlFvMxM7W97sZ2ggk0cRThlRt2pRUoSr8mmmUnobiorpISmksA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-drag-handle-vue-3": ["@tiptap/extension-drag-handle-vue-3@3.20.0", "", { "peerDependencies": { "@tiptap/extension-drag-handle": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/vue-3": "^3.20.0", "vue": "^3.0.0" } }, "sha512-Jx6LHYRI5uRaJVNQGkQsTFQkAM84rYQh3Q+WBePhGF4yPBUJQFn7Nv+5fQhKKV3A5PVQ6kTAjvW6SSUcD6ON8A=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-dropcursor": ["@tiptap/extension-dropcursor@3.20.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.0" } }, "sha512-d+cxplRlktVgZPwatnc34IArlppM0IFKS1J5wLk+ba1jidizsbMVh45tP/BTK2flhyfRqcNoB5R0TArhUpbkNQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-floating-menu": ["@tiptap/extension-floating-menu@3.20.0", "", { "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-rYs4Bv5pVjqZ/2vvR6oe7ammZapkAwN51As/WDbemvYDjfOGRqK58qGauUjYZiDzPOEIzI2mxGwsZ4eJhPW4Ig=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-gapcursor": ["@tiptap/extension-gapcursor@3.20.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.0" } }, "sha512-P/LasfvG9/qFq43ZAlNbAnPnXC+/RJf49buTrhtFvI9Zg0+Lbpjx1oh6oMHB19T88Y28KtrckfFZ8aTSUWDq6w=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-hard-break": ["@tiptap/extension-hard-break@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-rqvhMOw4f+XQmEthncbvDjgLH6fz8L9splnKZC7OeS0eX8b0qd7+xI1u5kyxF3KA2Z0BnigES++jjWuecqV6mA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-heading": ["@tiptap/extension-heading@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-JgJhurnCe3eN6a0lEsNQM/46R1bcwzwWWZEFDSb1P9dR8+t1/5v7cMZWsSInpD7R4/74iJn0+M5hcXLwCmBmYA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-horizontal-rule": ["@tiptap/extension-horizontal-rule@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-6uvcutFMv+9wPZgptDkbRDjAm3YVxlibmkhWD5GuaWwS9L/yUtobpI3GycujRSUZ8D3q6Q9J7LqpmQtQRTalWA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-image": ["@tiptap/extension-image@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-0t7HYncV0kYEQS79NFczxdlZoZ8zu8X4VavDqt+mbSAUKRq3gCvgtZ5Zyd778sNmtmbz3arxkEYMIVou2swD0g=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-italic": ["@tiptap/extension-italic@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-/DhnKQF8yN8RxtuL8abZ28wd5281EaGoE2Oha35zXSOF1vNYnbyt8Ymkv/7u1BcWEWTvRPgaju0YCGXisPRLYw=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-link": ["@tiptap/extension-link@3.20.0", "", { "dependencies": { "linkifyjs": "^4.3.2" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-qI/5A+R0ZWBxo/8HxSn1uOyr7odr3xHBZ/gzOR1GUJaZqjlJxkWFX0RtXMbLKEGEvT25o345cF7b0wFznEh8qA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-list": ["@tiptap/extension-list@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-+V0/gsVWAv+7vcY0MAe6D52LYTIicMSHw00wz3ISZgprSb2yQhJ4+4gurOnUrQ4Du3AnRQvxPROaofwxIQ66WQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-list-item": ["@tiptap/extension-list-item@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-qEtjaaGPuqaFB4VpLrGDoIe9RHnckxPfu6d3rc22ap6TAHCDyRv05CEyJogqccnFceG/v5WN4znUBER8RWnWHA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-list-keymap": ["@tiptap/extension-list-keymap@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-Z4GvKy04Ms4cLFN+CY6wXswd36xYsT2p/YL0V89LYFMZTerOeTjFYlndzn6svqL8NV1PRT5Diw4WTTxJSmcJPA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-mention": ["@tiptap/extension-mention@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/suggestion": "^3.20.0" } }, "sha512-wUjsq7Za0JJdJzrGNG+g8nrCpek/85GQ0Rm9bka3PynIVRwus+xQqW6IyWVPBdl1BSkrbgMAUqtrfoh1ymznbg=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-node-range": ["@tiptap/extension-node-range@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-XeKKTV88VuJ4Mh0Rxvc/PPzG76cb44sE+rB4u0J/ms63R/WFTm6yJQlCgUVGnGeHleSlrWuZY8gGSuoljmQzqg=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-ordered-list": ["@tiptap/extension-ordered-list@3.20.0", "", { "peerDependencies": { "@tiptap/extension-list": "^3.20.0" } }, "sha512-jVKnJvrizLk7etwBMfyoj6H2GE4M+PD4k7Bwp6Bh1ohBWtfIA1TlngdS842Mx5i1VB2e3UWIwr8ZH46gl6cwMA=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-paragraph": ["@tiptap/extension-paragraph@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-mM99zK4+RnEXIMCv6akfNATAs0Iija6FgyFA9J9NZ6N4o8y9QiNLLa6HjLpAC+W+VoCgQIekyoF/Q9ftxmAYDQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-placeholder": ["@tiptap/extension-placeholder@3.20.0", "", { "peerDependencies": { "@tiptap/extensions": "^3.20.0" } }, "sha512-ZhYD3L5m16ydSe2z8vqz+RdtAG/iOQaFHHedFct70tKRoLqi2ajF5kgpemu8DwpaRTcyiCN4G99J/+MqehKNjQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-strike": ["@tiptap/extension-strike@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-0vcTZRRAiDfon3VM1mHBr9EFmTkkUXMhm0Xtdtn0bGe+sIqufyi+hUYTEw93EQOD9XNsPkrud6jzQNYpX2H3AQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-text": ["@tiptap/extension-text@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-tf8bE8tSaOEWabCzPm71xwiUhyMFKqY9jkP5af3Kr1/F45jzZFIQAYZooHI/+zCHRrgJ99MQHKHe1ZNvODrKHQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extension-underline": ["@tiptap/extension-underline@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0" } }, "sha512-LzNXuy2jwR/y+ymoUqC72TiGzbOCjioIjsDu0MNYpHuHqTWPK5aV9Mh0nbZcYFy/7fPlV1q0W139EbJeYBZEAQ=="],
|
||||||
|
|
||||||
|
"@tiptap/extensions": ["@tiptap/extensions@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-HIsXX942w3nbxEQBlMAAR/aa6qiMBEP7CsSMxaxmTIVAmW35p6yUASw6GdV1u0o3lCZjXq2OSRMTskzIqi5uLg=="],
|
||||||
|
|
||||||
|
"@tiptap/markdown": ["@tiptap/markdown@3.20.0", "", { "dependencies": { "marked": "^17.0.1" }, "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-3vUxs8tsVIf/KWKLWjFsTqrjuaTYJY9rawDL5sio9NwlqFWDuWpHEVJcqbQXJUrgQSh12AZoTKyfgiEqkAGI3Q=="],
|
||||||
|
|
||||||
|
"@tiptap/pm": ["@tiptap/pm@3.20.0", "", { "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.6.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", "prosemirror-history": "^1.4.1", "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", "prosemirror-markdown": "^1.13.1", "prosemirror-menu": "^1.2.4", "prosemirror-model": "^1.24.1", "prosemirror-schema-basic": "^1.2.3", "prosemirror-schema-list": "^1.5.0", "prosemirror-state": "^1.4.3", "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", "prosemirror-view": "^1.38.1" } }, "sha512-jn+2KnQZn+b+VXr8EFOJKsnjVNaA4diAEr6FOazupMt8W8ro1hfpYtZ25JL87Kao/WbMze55sd8M8BDXLUKu1A=="],
|
||||||
|
|
||||||
|
"@tiptap/starter-kit": ["@tiptap/starter-kit@3.20.0", "", { "dependencies": { "@tiptap/core": "^3.20.0", "@tiptap/extension-blockquote": "^3.20.0", "@tiptap/extension-bold": "^3.20.0", "@tiptap/extension-bullet-list": "^3.20.0", "@tiptap/extension-code": "^3.20.0", "@tiptap/extension-code-block": "^3.20.0", "@tiptap/extension-document": "^3.20.0", "@tiptap/extension-dropcursor": "^3.20.0", "@tiptap/extension-gapcursor": "^3.20.0", "@tiptap/extension-hard-break": "^3.20.0", "@tiptap/extension-heading": "^3.20.0", "@tiptap/extension-horizontal-rule": "^3.20.0", "@tiptap/extension-italic": "^3.20.0", "@tiptap/extension-link": "^3.20.0", "@tiptap/extension-list": "^3.20.0", "@tiptap/extension-list-item": "^3.20.0", "@tiptap/extension-list-keymap": "^3.20.0", "@tiptap/extension-ordered-list": "^3.20.0", "@tiptap/extension-paragraph": "^3.20.0", "@tiptap/extension-strike": "^3.20.0", "@tiptap/extension-text": "^3.20.0", "@tiptap/extension-underline": "^3.20.0", "@tiptap/extensions": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-W4+1re35pDNY/7rpXVg+OKo/Fa4Gfrn08Bq3E3fzlJw6gjE3tYU8dY9x9vC2rK9pd9NOp7Af11qCFDaWpohXkw=="],
|
||||||
|
|
||||||
|
"@tiptap/suggestion": ["@tiptap/suggestion@3.20.0", "", { "peerDependencies": { "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0" } }, "sha512-OA9Fe+1Q/Ex0ivTcpRcVFiLnNsVdIBmiEoctt/gu4H2ayCYmZ906veioXNdc1m/3MtVVUIuEnvwwsrOZXlfDEw=="],
|
||||||
|
|
||||||
|
"@tiptap/vue-3": ["@tiptap/vue-3@3.20.0", "", { "optionalDependencies": { "@tiptap/extension-bubble-menu": "^3.20.0", "@tiptap/extension-floating-menu": "^3.20.0" }, "peerDependencies": { "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.20.0", "@tiptap/pm": "^3.20.0", "vue": "^3.0.0" } }, "sha512-u8UfDKsbIOF+mVsXwJ946p1jfrLGFUyqp9i/DAeGGg2I85DPOkhZgz67bUPVXkpossoEk+jKCkRN0eBHl9+eZQ=="],
|
||||||
|
|
||||||
|
"@tiptap/y-tiptap": ["@tiptap/y-tiptap@3.0.2", "", { "dependencies": { "lib0": "^0.2.100" }, "peerDependencies": { "prosemirror-model": "^1.7.1", "prosemirror-state": "^1.2.3", "prosemirror-view": "^1.9.10", "y-protocols": "^1.0.1", "yjs": "^13.5.38" } }, "sha512-flMn/YW6zTbc6cvDaUPh/NfLRTXDIqgpBUkYzM74KA1snqQwhOMjnRcnpu4hDFrTnPO6QGzr99vRyXEA7M44WA=="],
|
||||||
|
|
||||||
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
|
"@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="],
|
||||||
|
|
||||||
|
"@types/markdown-it": ["@types/markdown-it@14.1.2", "", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog=="],
|
||||||
|
|
||||||
|
"@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],
|
||||||
|
|
||||||
|
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||||
|
|
||||||
|
"@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="],
|
||||||
|
|
||||||
|
"@unhead/vue": ["@unhead/vue@2.1.10", "", { "dependencies": { "hookable": "^6.0.1", "unhead": "2.1.10" }, "peerDependencies": { "vue": ">=3.5.18" } }, "sha512-VP78Onh2HNezLPfhYjfHqn4dxlcQsE6PJgTTs61NksO/thvilNswtgBq0N0MWCLtn43N5akEPGW2y2zxM3PWgQ=="],
|
||||||
|
|
||||||
|
"@vue/compiler-core": ["@vue/compiler-core@3.5.29", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/shared": "3.5.29", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-cuzPhD8fwRHk8IGfmYaR4eEe4cAyJEL66Ove/WZL7yWNL134nqLddSLwNRIsFlnnW1kK+p8Ck3viFnC0chXCXw=="],
|
||||||
|
|
||||||
|
"@vue/compiler-dom": ["@vue/compiler-dom@3.5.29", "", { "dependencies": { "@vue/compiler-core": "3.5.29", "@vue/shared": "3.5.29" } }, "sha512-n0G5o7R3uBVmVxjTIYcz7ovr8sy7QObFG8OQJ3xGCDNhbG60biP/P5KnyY8NLd81OuT1WJflG7N4KWYHaeeaIg=="],
|
||||||
|
|
||||||
|
"@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.29", "", { "dependencies": { "@babel/parser": "^7.29.0", "@vue/compiler-core": "3.5.29", "@vue/compiler-dom": "3.5.29", "@vue/compiler-ssr": "3.5.29", "@vue/shared": "3.5.29", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-oJZhN5XJs35Gzr50E82jg2cYdZQ78wEwvRO6Y63TvLVTc+6xICzJHP1UIecdSPPYIbkautNBanDiWYa64QSFIA=="],
|
||||||
|
|
||||||
|
"@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.29", "", { "dependencies": { "@vue/compiler-dom": "3.5.29", "@vue/shared": "3.5.29" } }, "sha512-Y/ARJZE6fpjzL5GH/phJmsFwx3g6t2KmHKHx5q+MLl2kencADKIrhH5MLF6HHpRMmlRAYBRSvv347Mepf1zVNw=="],
|
||||||
|
|
||||||
|
"@vue/reactivity": ["@vue/reactivity@3.5.29", "", { "dependencies": { "@vue/shared": "3.5.29" } }, "sha512-zcrANcrRdcLtmGZETBxWqIkoQei8HaFpZWx/GHKxx79JZsiZ8j1du0VUJtu4eJjgFvU/iKL5lRXFXksVmI+5DA=="],
|
||||||
|
|
||||||
|
"@vue/runtime-core": ["@vue/runtime-core@3.5.29", "", { "dependencies": { "@vue/reactivity": "3.5.29", "@vue/shared": "3.5.29" } }, "sha512-8DpW2QfdwIWOLqtsNcds4s+QgwSaHSJY/SUe04LptianUQ/0xi6KVsu/pYVh+HO3NTVvVJjIPL2t6GdeKbS4Lg=="],
|
||||||
|
|
||||||
|
"@vue/runtime-dom": ["@vue/runtime-dom@3.5.29", "", { "dependencies": { "@vue/reactivity": "3.5.29", "@vue/runtime-core": "3.5.29", "@vue/shared": "3.5.29", "csstype": "^3.2.3" } }, "sha512-AHvvJEtcY9tw/uk+s/YRLSlxxQnqnAkjqvK25ZiM4CllCZWzElRAoQnCM42m9AHRLNJ6oe2kC5DCgD4AUdlvXg=="],
|
||||||
|
|
||||||
|
"@vue/server-renderer": ["@vue/server-renderer@3.5.29", "", { "dependencies": { "@vue/compiler-ssr": "3.5.29", "@vue/shared": "3.5.29" }, "peerDependencies": { "vue": "3.5.29" } }, "sha512-G/1k6WK5MusLlbxSE2YTcqAAezS+VuwHhOvLx2KnQU7G2zCH6KIb+5Wyt6UjMq7a3qPzNEjJXs1hvAxDclQH+g=="],
|
||||||
|
|
||||||
|
"@vue/shared": ["@vue/shared@3.5.29", "", {}, "sha512-w7SR0A5zyRByL9XUkCfdLs7t9XOHUyJ67qPGQjOou3p6GvBeBW+AVjUUmlxtZ4PIYaRvE+1LmK44O4uajlZwcg=="],
|
||||||
|
|
||||||
|
"@vueuse/core": ["@vueuse/core@14.2.1", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "14.2.1", "@vueuse/shared": "14.2.1" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ=="],
|
||||||
|
|
||||||
|
"@vueuse/integrations": ["@vueuse/integrations@14.2.1", "", { "dependencies": { "@vueuse/core": "14.2.1", "@vueuse/shared": "14.2.1" }, "peerDependencies": { "async-validator": "^4", "axios": "^1", "change-case": "^5", "drauu": "^0.4", "focus-trap": "^7 || ^8", "fuse.js": "^7", "idb-keyval": "^6", "jwt-decode": "^4", "nprogress": "^0.2", "qrcode": "^1.5", "sortablejs": "^1", "universal-cookie": "^7 || ^8", "vue": "^3.5.0" }, "optionalPeers": ["async-validator", "axios", "change-case", "drauu", "focus-trap", "idb-keyval", "jwt-decode", "nprogress", "qrcode", "sortablejs", "universal-cookie"] }, "sha512-2LIUpBi/67PoXJGqSDQUF0pgQWpNHh7beiA+KG2AbybcNm+pTGWT6oPGlBgUoDWmYwfeQqM/uzOHqcILpKL7nA=="],
|
||||||
|
|
||||||
|
"@vueuse/metadata": ["@vueuse/metadata@14.2.1", "", {}, "sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw=="],
|
||||||
|
|
||||||
|
"@vueuse/shared": ["@vueuse/shared@14.2.1", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw=="],
|
||||||
|
|
||||||
|
"acorn": ["acorn@8.16.0", "", { "bin": "bin/acorn" }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
|
||||||
|
|
||||||
|
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
|
||||||
|
|
||||||
|
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||||
|
|
||||||
|
"aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
|
||||||
|
|
||||||
|
"c12": ["c12@3.3.3", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q=="],
|
||||||
|
|
||||||
|
"chart.js": ["chart.js@4.5.1", "", { "dependencies": { "@kurkle/color": "^0.3.0" } }, "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="],
|
||||||
|
|
||||||
|
"chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="],
|
||||||
|
|
||||||
|
"citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="],
|
||||||
|
|
||||||
|
"colortranslator": ["colortranslator@5.0.0", "", {}, "sha512-Z3UPUKasUVDFCDYAjP2fmlVRf1jFHJv1izAmPjiOa0OCIw1W7iC8PZ2GsoDa8uZv+mKyWopxxStT9q05+27h7w=="],
|
||||||
|
|
||||||
|
"confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="],
|
||||||
|
|
||||||
|
"consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
|
||||||
|
|
||||||
|
"cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="],
|
||||||
|
|
||||||
|
"crelt": ["crelt@1.0.6", "", {}, "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="],
|
||||||
|
|
||||||
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
|
"crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="],
|
||||||
|
|
||||||
|
"css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="],
|
||||||
|
|
||||||
|
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||||
|
|
||||||
|
"defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
|
||||||
|
|
||||||
|
"destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="],
|
||||||
|
|
||||||
|
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
|
"dompurify": ["dompurify@3.3.3", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA=="],
|
||||||
|
|
||||||
|
"dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
|
||||||
|
|
||||||
|
"embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
|
||||||
|
|
||||||
|
"embla-carousel-auto-height": ["embla-carousel-auto-height@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-/HrJQOEM6aol/oF33gd2QlINcXy3e19fJWvHDuHWp2bpyTa+2dm9tVVJak30m2Qy6QyQ6Fc8DkImtv7pxWOJUQ=="],
|
||||||
|
|
||||||
|
"embla-carousel-auto-scroll": ["embla-carousel-auto-scroll@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-WT9fWhNXFpbQ6kP+aS07oF5IHYLZ1Dx4DkwgCY8Hv2ZyYd2KMCPfMV1q/cA3wFGuLO7GMgKiySLX90/pQkcOdQ=="],
|
||||||
|
|
||||||
|
"embla-carousel-autoplay": ["embla-carousel-autoplay@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA=="],
|
||||||
|
|
||||||
|
"embla-carousel-class-names": ["embla-carousel-class-names@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-l1hm1+7GxQ+zwdU2sea/LhD946on7XO2qk3Xq2XWSwBaWfdgchXdK567yzLtYSHn4sWYdiX+x4nnaj+saKnJkw=="],
|
||||||
|
|
||||||
|
"embla-carousel-fade": ["embla-carousel-fade@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg=="],
|
||||||
|
|
||||||
|
"embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="],
|
||||||
|
|
||||||
|
"embla-carousel-vue": ["embla-carousel-vue@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "vue": "^3.2.37" } }, "sha512-v8UO5UsyLocZnu/LbfQA7Dn2QHuZKurJY93VUmZYP//QRWoCWOsionmvLLAlibkET3pGPs7++03VhJKbWD7vhQ=="],
|
||||||
|
|
||||||
|
"embla-carousel-wheel-gestures": ["embla-carousel-wheel-gestures@8.1.0", "", { "dependencies": { "wheel-gestures": "^2.2.5" }, "peerDependencies": { "embla-carousel": "^8.0.0 || ~8.0.0-rc03" } }, "sha512-J68jkYrxbWDmXOm2n2YHl+uMEXzkGSKjWmjaEgL9xVvPb3HqVmg6rJSKfI3sqIDVvm7mkeTy87wtG/5263XqHQ=="],
|
||||||
|
|
||||||
|
"enhanced-resolve": ["enhanced-resolve@5.20.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="],
|
||||||
|
|
||||||
|
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||||
|
|
||||||
|
"errx": ["errx@0.1.0", "", {}, "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q=="],
|
||||||
|
|
||||||
|
"esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": "bin/esbuild" }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
|
||||||
|
|
||||||
|
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||||
|
|
||||||
|
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||||
|
|
||||||
|
"execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
||||||
|
|
||||||
|
"exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
|
||||||
|
|
||||||
|
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||||
|
|
||||||
|
"fontaine": ["fontaine@0.8.0", "", { "dependencies": { "@capsizecss/unpack": "^4.0.0", "css-tree": "^3.1.0", "magic-regexp": "^0.10.0", "magic-string": "^0.30.21", "pathe": "^2.0.3", "ufo": "^1.6.1", "unplugin": "^2.3.10" } }, "sha512-eek1GbzOdWIj9FyQH/emqW1aEdfC3lYRCHepzwlFCm5T77fBSRSyNRKE6/antF1/B1M+SfJXVRQTY9GAr7lnDg=="],
|
||||||
|
|
||||||
|
"fontkitten": ["fontkitten@1.0.2", "", { "dependencies": { "tiny-inflate": "^1.0.3" } }, "sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q=="],
|
||||||
|
|
||||||
|
"fontless": ["fontless@0.2.1", "", { "dependencies": { "consola": "^3.4.2", "css-tree": "^3.1.0", "defu": "^6.1.4", "esbuild": "^0.27.0", "fontaine": "0.8.0", "jiti": "^2.6.1", "lightningcss": "^1.30.2", "magic-string": "^0.30.21", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1", "unifont": "^0.7.4", "unstorage": "^1.17.1" }, "peerDependencies": { "vite": "*" } }, "sha512-mUWZ8w91/mw2KEcZ6gHNoNNmsAq9Wiw2IypIux5lM03nhXm+WSloXGUNuRETNTLqZexMgpt7Aj/v63qqrsWraQ=="],
|
||||||
|
|
||||||
|
"framer-motion": ["framer-motion@12.34.4", "", { "dependencies": { "motion-dom": "^12.34.3", "motion-utils": "^12.29.2", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-q1PwNhc1XJ3qYG7nc9+pEU5P3tnjB6Eh9vv5gGzy61nedDLB4+xk5peMCWhKM0Zn6sfhgunf/q9n0UgCoyKOBA=="],
|
||||||
|
|
||||||
|
"fuse.js": ["fuse.js@7.1.0", "", {}, "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ=="],
|
||||||
|
|
||||||
|
"get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
||||||
|
|
||||||
|
"giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": "dist/cli.mjs" }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="],
|
||||||
|
|
||||||
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||||
|
|
||||||
|
"h3": ["h3@1.15.5", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg=="],
|
||||||
|
|
||||||
|
"hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="],
|
||||||
|
|
||||||
|
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
|
||||||
|
|
||||||
|
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
||||||
|
|
||||||
|
"ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||||
|
|
||||||
|
"iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="],
|
||||||
|
|
||||||
|
"is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
|
||||||
|
|
||||||
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||||
|
|
||||||
|
"isomorphic.js": ["isomorphic.js@0.2.5", "", {}, "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw=="],
|
||||||
|
|
||||||
|
"jiti": ["jiti@2.6.1", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
||||||
|
|
||||||
|
"js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
|
||||||
|
|
||||||
|
"klona": ["klona@2.0.6", "", {}, "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="],
|
||||||
|
|
||||||
|
"knitwork": ["knitwork@1.3.0", "", {}, "sha512-4LqMNoONzR43B1W0ek0fhXMsDNW/zxa1NdFAVMY+k28pgZLovR4G3PB5MrpTxCy1QaZCqNoiaKPr5w5qZHfSNw=="],
|
||||||
|
|
||||||
|
"lib0": ["lib0@0.2.117", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", "0gentesthtml": "bin/gentesthtml.js", "0serve": "bin/0serve.js" } }, "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw=="],
|
||||||
|
|
||||||
|
"lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
|
||||||
|
|
||||||
|
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
|
||||||
|
|
||||||
|
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
|
||||||
|
|
||||||
|
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
|
||||||
|
|
||||||
|
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
|
||||||
|
|
||||||
|
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
|
||||||
|
|
||||||
|
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
|
||||||
|
|
||||||
|
"linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="],
|
||||||
|
|
||||||
|
"linkifyjs": ["linkifyjs@4.3.2", "", {}, "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA=="],
|
||||||
|
|
||||||
|
"local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="],
|
||||||
|
|
||||||
|
"lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
|
||||||
|
|
||||||
|
"magic-regexp": ["magic-regexp@0.10.0", "", { "dependencies": { "estree-walker": "^3.0.3", "magic-string": "^0.30.12", "mlly": "^1.7.2", "regexp-tree": "^0.1.27", "type-level-regexp": "~0.1.17", "ufo": "^1.5.4", "unplugin": "^2.0.0" } }, "sha512-Uly1Bu4lO1hwHUW0CQeSWuRtzCMNO00CmXtS8N6fyvB3B979GOEEeAkiTUDsmbYLAbvpUS/Kt5c4ibosAzVyVg=="],
|
||||||
|
|
||||||
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
|
|
||||||
|
"markdown-it": ["markdown-it@14.1.1", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": "bin/markdown-it.mjs" }, "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA=="],
|
||||||
|
|
||||||
|
"marked": ["marked@17.0.3", "", { "bin": "bin/marked.js" }, "sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A=="],
|
||||||
|
|
||||||
|
"mdn-data": ["mdn-data@2.12.2", "", {}, "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA=="],
|
||||||
|
|
||||||
|
"mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="],
|
||||||
|
|
||||||
|
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
|
||||||
|
|
||||||
|
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
||||||
|
|
||||||
|
"mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="],
|
||||||
|
|
||||||
|
"motion-dom": ["motion-dom@12.34.3", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-sYgFe+pR9aIM7o4fhs2aXtOI+oqlUd33N9Yoxcgo1Fv7M20sRkHtCmzE/VRNIcq7uNJ+qio+Xubt1FXH3pQ+eQ=="],
|
||||||
|
|
||||||
|
"motion-utils": ["motion-utils@12.29.2", "", {}, "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A=="],
|
||||||
|
|
||||||
|
"motion-v": ["motion-v@1.10.3", "", { "dependencies": { "framer-motion": "^12.25.0", "hey-listen": "^1.0.8", "motion-dom": "^12.23.23" }, "peerDependencies": { "@vueuse/core": ">=10.0.0", "vue": ">=3.0.0" } }, "sha512-9Ewo/wwGv7FO3PqYJpllBF/Efc7tbeM1iinVrM73s0RUQrnXHwMZCaRX98u4lu0PQCrZghPPfCsQ14pWKIEbnQ=="],
|
||||||
|
|
||||||
|
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
||||||
|
|
||||||
|
"nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
|
"node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
|
||||||
|
|
||||||
|
"node-mock-http": ["node-mock-http@1.0.4", "", {}, "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ=="],
|
||||||
|
|
||||||
|
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
||||||
|
|
||||||
|
"npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
|
||||||
|
|
||||||
|
"nypm": ["nypm@0.6.5", "", { "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", "tinyexec": "^1.0.2" }, "bin": "dist/cli.mjs" }, "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ=="],
|
||||||
|
|
||||||
|
"obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
|
||||||
|
|
||||||
|
"ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="],
|
||||||
|
|
||||||
|
"ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="],
|
||||||
|
|
||||||
|
"onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
|
||||||
|
|
||||||
|
"orderedmap": ["orderedmap@2.1.1", "", {}, "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g=="],
|
||||||
|
|
||||||
|
"package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="],
|
||||||
|
|
||||||
|
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
|
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
|
"perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="],
|
||||||
|
|
||||||
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||||
|
|
||||||
|
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||||
|
|
||||||
|
"pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
|
||||||
|
|
||||||
|
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
|
||||||
|
|
||||||
|
"prosemirror-changeset": ["prosemirror-changeset@2.4.0", "", { "dependencies": { "prosemirror-transform": "^1.0.0" } }, "sha512-LvqH2v7Q2SF6yxatuPP2e8vSUKS/L+xAU7dPDC4RMyHMhZoGDfBC74mYuyYF4gLqOEG758wajtyhNnsTkuhvng=="],
|
||||||
|
|
||||||
|
"prosemirror-collab": ["prosemirror-collab@1.3.1", "", { "dependencies": { "prosemirror-state": "^1.0.0" } }, "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ=="],
|
||||||
|
|
||||||
|
"prosemirror-commands": ["prosemirror-commands@1.7.1", "", { "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.10.2" } }, "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w=="],
|
||||||
|
|
||||||
|
"prosemirror-dropcursor": ["prosemirror-dropcursor@1.8.2", "", { "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0", "prosemirror-view": "^1.1.0" } }, "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw=="],
|
||||||
|
|
||||||
|
"prosemirror-gapcursor": ["prosemirror-gapcursor@1.4.0", "", { "dependencies": { "prosemirror-keymap": "^1.0.0", "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", "prosemirror-view": "^1.0.0" } }, "sha512-z00qvurSdCEWUIulij/isHaqu4uLS8r/Fi61IbjdIPJEonQgggbJsLnstW7Lgdk4zQ68/yr6B6bf7sJXowIgdQ=="],
|
||||||
|
|
||||||
|
"prosemirror-history": ["prosemirror-history@1.5.0", "", { "dependencies": { "prosemirror-state": "^1.2.2", "prosemirror-transform": "^1.0.0", "prosemirror-view": "^1.31.0", "rope-sequence": "^1.3.0" } }, "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg=="],
|
||||||
|
|
||||||
|
"prosemirror-inputrules": ["prosemirror-inputrules@1.5.1", "", { "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.0.0" } }, "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw=="],
|
||||||
|
|
||||||
|
"prosemirror-keymap": ["prosemirror-keymap@1.2.3", "", { "dependencies": { "prosemirror-state": "^1.0.0", "w3c-keyname": "^2.2.0" } }, "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw=="],
|
||||||
|
|
||||||
|
"prosemirror-markdown": ["prosemirror-markdown@1.13.4", "", { "dependencies": { "@types/markdown-it": "^14.0.0", "markdown-it": "^14.0.0", "prosemirror-model": "^1.25.0" } }, "sha512-D98dm4cQ3Hs6EmjK500TdAOew4Z03EV71ajEFiWra3Upr7diytJsjF4mPV2dW+eK5uNectiRj0xFxYI9NLXDbw=="],
|
||||||
|
|
||||||
|
"prosemirror-menu": ["prosemirror-menu@1.3.0", "", { "dependencies": { "crelt": "^1.0.0", "prosemirror-commands": "^1.0.0", "prosemirror-history": "^1.0.0", "prosemirror-state": "^1.0.0" } }, "sha512-TImyPXCHPcDsSka2/lwJ6WjTASr4re/qWq1yoTTuLOqfXucwF6VcRa2LWCkM/EyTD1UO3CUwiH8qURJoWJRxwg=="],
|
||||||
|
|
||||||
|
"prosemirror-model": ["prosemirror-model@1.25.4", "", { "dependencies": { "orderedmap": "^2.0.0" } }, "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA=="],
|
||||||
|
|
||||||
|
"prosemirror-schema-basic": ["prosemirror-schema-basic@1.2.4", "", { "dependencies": { "prosemirror-model": "^1.25.0" } }, "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ=="],
|
||||||
|
|
||||||
|
"prosemirror-schema-list": ["prosemirror-schema-list@1.5.1", "", { "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.7.3" } }, "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q=="],
|
||||||
|
|
||||||
|
"prosemirror-state": ["prosemirror-state@1.4.4", "", { "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-transform": "^1.0.0", "prosemirror-view": "^1.27.0" } }, "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw=="],
|
||||||
|
|
||||||
|
"prosemirror-tables": ["prosemirror-tables@1.8.5", "", { "dependencies": { "prosemirror-keymap": "^1.2.3", "prosemirror-model": "^1.25.4", "prosemirror-state": "^1.4.4", "prosemirror-transform": "^1.10.5", "prosemirror-view": "^1.41.4" } }, "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw=="],
|
||||||
|
|
||||||
|
"prosemirror-trailing-node": ["prosemirror-trailing-node@3.0.0", "", { "dependencies": { "@remirror/core-constants": "3.0.0", "escape-string-regexp": "^4.0.0" }, "peerDependencies": { "prosemirror-model": "^1.22.1", "prosemirror-state": "^1.4.2", "prosemirror-view": "^1.33.8" } }, "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ=="],
|
||||||
|
|
||||||
|
"prosemirror-transform": ["prosemirror-transform@1.11.0", "", { "dependencies": { "prosemirror-model": "^1.21.0" } }, "sha512-4I7Ce4KpygXb9bkiPS3hTEk4dSHorfRw8uI0pE8IhxlK2GXsqv5tIA7JUSxtSu7u8APVOTtbUBxTmnHIxVkIJw=="],
|
||||||
|
|
||||||
|
"prosemirror-view": ["prosemirror-view@1.41.6", "", { "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0" } }, "sha512-mxpcDG4hNQa/CPtzxjdlir5bJFDlm0/x5nGBbStB2BWX+XOQ9M8ekEG+ojqB5BcVu2Rc80/jssCMZzSstJuSYg=="],
|
||||||
|
|
||||||
|
"punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="],
|
||||||
|
|
||||||
|
"quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="],
|
||||||
|
|
||||||
|
"radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="],
|
||||||
|
|
||||||
|
"rc9": ["rc9@3.0.0", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.5" } }, "sha512-MGOue0VqscKWQ104udASX/3GYDcKyPI4j4F8gu/jHHzglpmy9a/anZK3PNe8ug6aZFl+9GxLtdhe3kVZuMaQbA=="],
|
||||||
|
|
||||||
|
"readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="],
|
||||||
|
|
||||||
|
"regexp-tree": ["regexp-tree@0.1.27", "", { "bin": "bin/regexp-tree" }, "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA=="],
|
||||||
|
|
||||||
|
"reka-ui": ["reka-ui@2.8.2", "", { "dependencies": { "@floating-ui/dom": "^1.6.13", "@floating-ui/vue": "^1.1.6", "@internationalized/date": "^3.5.0", "@internationalized/number": "^3.5.0", "@tanstack/vue-virtual": "^3.12.0", "@vueuse/core": "^14.1.0", "@vueuse/shared": "^14.1.0", "aria-hidden": "^1.2.4", "defu": "^6.1.4", "ohash": "^2.0.11" }, "peerDependencies": { "vue": ">= 3.2.0" } }, "sha512-8lTKcJhmG+D3UyJxhBnNnW/720sLzm0pbA9AC1MWazmJ5YchJAyTSl+O00xP/kxBmEN0fw5JqWVHguiFmsGjzA=="],
|
||||||
|
|
||||||
|
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "bin": "dist/bin/rollup" }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
|
||||||
|
|
||||||
|
"rope-sequence": ["rope-sequence@1.3.4", "", {}, "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="],
|
||||||
|
|
||||||
|
"scule": ["scule@1.3.0", "", {}, "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="],
|
||||||
|
|
||||||
|
"semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
|
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
|
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||||
|
|
||||||
|
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
||||||
|
|
||||||
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
|
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
|
||||||
|
|
||||||
|
"strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
||||||
|
|
||||||
|
"strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
|
||||||
|
|
||||||
|
"tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="],
|
||||||
|
|
||||||
|
"tailwind-variants": ["tailwind-variants@3.2.2", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" } }, "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg=="],
|
||||||
|
|
||||||
|
"tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="],
|
||||||
|
|
||||||
|
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
||||||
|
|
||||||
|
"tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="],
|
||||||
|
|
||||||
|
"tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
|
||||||
|
|
||||||
|
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||||
|
|
||||||
|
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||||
|
|
||||||
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
|
"type-level-regexp": ["type-level-regexp@0.1.17", "", {}, "sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
"uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
|
||||||
|
|
||||||
|
"ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
|
||||||
|
|
||||||
|
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
|
||||||
|
|
||||||
|
"unctx": ["unctx@2.5.0", "", { "dependencies": { "acorn": "^8.15.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.21", "unplugin": "^2.3.11" } }, "sha512-p+Rz9x0R7X+CYDkT+Xg8/GhpcShTlU8n+cf9OtOEf7zEQsNcCZO1dPKNRDqvUTaq+P32PMMkxWHwfrxkqfqAYg=="],
|
||||||
|
|
||||||
|
"unhead": ["unhead@2.1.10", "", { "dependencies": { "hookable": "^6.0.1" } }, "sha512-We8l9uNF8zz6U8lfQaVG70+R/QBfQx1oPIgXin4BtZnK2IQpz6yazQ0qjMNVBDw2ADgF2ea58BtvSK+XX5AS7g=="],
|
||||||
|
|
||||||
|
"unifont": ["unifont@0.7.4", "", { "dependencies": { "css-tree": "^3.1.0", "ofetch": "^1.5.1", "ohash": "^2.0.11" } }, "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg=="],
|
||||||
|
|
||||||
|
"unimport": ["unimport@5.7.0", "", { "dependencies": { "acorn": "^8.16.0", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "pathe": "^2.0.3", "picomatch": "^4.0.3", "pkg-types": "^2.3.0", "scule": "^1.3.0", "strip-literal": "^3.1.0", "tinyglobby": "^0.2.15", "unplugin": "^2.3.11", "unplugin-utils": "^0.3.1" } }, "sha512-njnL6sp8lEA8QQbZrt+52p/g4X0rw3bnGGmUcJnt1jeG8+iiqO779aGz0PirCtydAIVcuTBRlJ52F0u46z309Q=="],
|
||||||
|
|
||||||
|
"unplugin": ["unplugin@3.0.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg=="],
|
||||||
|
|
||||||
|
"unplugin-auto-import": ["unplugin-auto-import@21.0.0", "", { "dependencies": { "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "picomatch": "^4.0.3", "unimport": "^5.6.0", "unplugin": "^2.3.11", "unplugin-utils": "^0.3.1" }, "peerDependencies": { "@nuxt/kit": "^4.0.0", "@vueuse/core": "*" } }, "sha512-vWuC8SwqJmxZFYwPojhOhOXDb5xFhNNcEVb9K/RFkyk/3VnfaOjzitWN7v+8DEKpMjSsY2AEGXNgt6I0yQrhRQ=="],
|
||||||
|
|
||||||
|
"unplugin-utils": ["unplugin-utils@0.3.1", "", { "dependencies": { "pathe": "^2.0.3", "picomatch": "^4.0.3" } }, "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog=="],
|
||||||
|
|
||||||
|
"unplugin-vue-components": ["unplugin-vue-components@31.0.0", "", { "dependencies": { "chokidar": "^5.0.0", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "obug": "^2.1.1", "picomatch": "^4.0.3", "tinyglobby": "^0.2.15", "unplugin": "^2.3.11", "unplugin-utils": "^0.3.1" }, "peerDependencies": { "@nuxt/kit": "^3.2.2 || ^4.0.0", "vue": "^3.0.0" } }, "sha512-4ULwfTZTLuWJ7+S9P7TrcStYLsSRkk6vy2jt/WTfgUEUb0nW9//xxmrfhyHUEVpZ2UKRRwfRb8Yy15PDbVZf+Q=="],
|
||||||
|
|
||||||
|
"unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="],
|
||||||
|
|
||||||
|
"untyped": ["untyped@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "defu": "^6.1.4", "jiti": "^2.4.2", "knitwork": "^1.2.0", "scule": "^1.3.0" }, "bin": "dist/cli.mjs" }, "sha512-nwNCjxJTjNuLCgFr42fEak5OcLuB3ecca+9ksPFNvtfYSLpjf+iJqSIaSnIile6ZPbKYxI5k2AfXqeopGudK/g=="],
|
||||||
|
|
||||||
|
"vaul-vue": ["vaul-vue@0.4.1", "", { "dependencies": { "@vueuse/core": "^10.8.0", "reka-ui": "^2.0.0", "vue": "^3.4.5" }, "peerDependencies": { "reka-ui": "^2.0.0", "vue": "^3.3.0" } }, "sha512-A6jOWOZX5yvyo1qMn7IveoWN91mJI5L3BUKsIwkg6qrTGgHs1Sb1JF/vyLJgnbN1rH4OOOxFbtqL9A46bOyGUQ=="],
|
||||||
|
|
||||||
|
"vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
|
||||||
|
|
||||||
|
"vue": ["vue@3.5.29", "", { "dependencies": { "@vue/compiler-dom": "3.5.29", "@vue/compiler-sfc": "3.5.29", "@vue/runtime-dom": "3.5.29", "@vue/server-renderer": "3.5.29", "@vue/shared": "3.5.29" }, "peerDependencies": { "typescript": "*" } }, "sha512-BZqN4Ze6mDQVNAni0IHeMJ5mwr8VAJ3MQC9FmprRhcBYENw+wOAAjRj8jfmN6FLl0j96OXbR+CjWhmAmM+QGnA=="],
|
||||||
|
|
||||||
|
"vue-chartjs": ["vue-chartjs@5.3.3", "", { "peerDependencies": { "chart.js": "^4.1.1", "vue": "^3.0.0-0 || ^2.7.0" } }, "sha512-jqxtL8KZ6YJ5NTv6XzrzLS7osyegOi28UGNZW0h9OkDL7Sh1396ht4Dorh04aKrl2LiSalQ84WtqiG0RIJb0tA=="],
|
||||||
|
|
||||||
|
"vue-component-type-helpers": ["vue-component-type-helpers@3.2.5", "", {}, "sha512-tkvNr+bU8+xD/onAThIe7CHFvOJ/BO6XCOrxMzeytJq40nTfpGDJuVjyCM8ccGZKfAbGk2YfuZyDMXM56qheZQ=="],
|
||||||
|
|
||||||
|
"vue-demi": ["vue-demi@0.14.10", "", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="],
|
||||||
|
|
||||||
|
"w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="],
|
||||||
|
|
||||||
|
"webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="],
|
||||||
|
|
||||||
|
"wheel-gestures": ["wheel-gestures@2.2.48", "", {}, "sha512-f+Gy33Oa5Z14XY9679Zze+7VFhbsQfBFXodnU2x589l4kxGM9L5Y8zETTmcMR5pWOPQyRv4Z0lNax6xCO0NSlA=="],
|
||||||
|
|
||||||
|
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
|
"y-protocols": ["y-protocols@1.0.7", "", { "dependencies": { "lib0": "^0.2.85" }, "peerDependencies": { "yjs": "^13.0.0" } }, "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw=="],
|
||||||
|
|
||||||
|
"yjs": ["yjs@13.6.29", "", { "dependencies": { "lib0": "^0.2.99" } }, "sha512-kHqDPdltoXH+X4w1lVmMtddE3Oeqq48nM40FD5ojTd8xYhQpzIDcfE2keMSU5bAgRPJBe225WTUdyUgj1DtbiQ=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode/@nuxt/kit": ["@nuxt/kit@3.21.1", "", { "dependencies": { "c12": "^3.3.3", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.8", "ignore": "^7.0.5", "jiti": "^2.6.1", "klona": "^2.0.6", "knitwork": "^1.3.0", "mlly": "^1.8.0", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "rc9": "^3.0.0", "scule": "^1.3.0", "semver": "^7.7.4", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unctx": "^2.5.0", "untyped": "^2.0.0" } }, "sha512-QORZRjcuTKgo++XP1Pc2c2gqwRydkaExrIRfRI9vFsPA3AzuHVn5Gfmbv1ic8y34e78mr5DMBvJlelUaeOuajg=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||||
|
|
||||||
|
"@unhead/vue/hookable": ["hookable@6.0.1", "", {}, "sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw=="],
|
||||||
|
|
||||||
|
"@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
|
||||||
|
|
||||||
|
"@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
|
"@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
|
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
|
|
||||||
|
"c12/rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="],
|
||||||
|
|
||||||
|
"fontaine/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
|
||||||
|
|
||||||
|
"magic-regexp/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
|
||||||
|
|
||||||
|
"mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||||
|
|
||||||
|
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||||
|
|
||||||
|
"nypm/citty": ["citty@0.2.1", "", {}, "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg=="],
|
||||||
|
|
||||||
|
"unctx/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
|
||||||
|
|
||||||
|
"unhead/hookable": ["hookable@6.0.1", "", {}, "sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw=="],
|
||||||
|
|
||||||
|
"unimport/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||||
|
|
||||||
|
"unimport/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
|
||||||
|
|
||||||
|
"unplugin-auto-import/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
|
||||||
|
|
||||||
|
"unplugin-vue-components/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
|
||||||
|
|
||||||
|
"vaul-vue/@vueuse/core": ["@vueuse/core@10.11.1", "", { "dependencies": { "@types/web-bluetooth": "^0.0.20", "@vueuse/metadata": "10.11.1", "@vueuse/shared": "10.11.1", "vue-demi": ">=0.14.8" } }, "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode/@nuxt/kit/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode/@nuxt/kit/pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
||||||
|
|
||||||
|
"@nuxtjs/color-mode/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
|
"mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
||||||
|
|
||||||
|
"vaul-vue/@vueuse/core/@types/web-bluetooth": ["@types/web-bluetooth@0.0.20", "", {}, "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="],
|
||||||
|
|
||||||
|
"vaul-vue/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@10.11.1", "", {}, "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw=="],
|
||||||
|
|
||||||
|
"vaul-vue/@vueuse/core/@vueuse/shared": ["@vueuse/shared@10.11.1", "", { "dependencies": { "vue-demi": ">=0.14.8" } }, "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA=="],
|
||||||
|
|
||||||
|
"vaul-vue/@vueuse/core/vue-demi": ["vue-demi@0.14.10", "", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="],
|
||||||
|
|
||||||
|
"vaul-vue/@vueuse/core/@vueuse/shared/vue-demi": ["vue-demi@0.14.10", "", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
34
go.mod
34
go.mod
@@ -3,22 +3,49 @@ module git.ma-al.com/goc_daniel/b2b
|
|||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cloud.google.com/go/auth v0.16.4
|
||||||
|
cloud.google.com/go/translate v1.12.7
|
||||||
github.com/a-h/templ v0.3.1001
|
github.com/a-h/templ v0.3.1001
|
||||||
github.com/dlclark/regexp2 v1.11.5
|
github.com/dlclark/regexp2 v1.11.5
|
||||||
github.com/go-git/go-git/v5 v5.17.0
|
github.com/go-git/go-git/v5 v5.17.0
|
||||||
github.com/gofiber/fiber/v3 v3.1.0
|
github.com/gofiber/fiber/v3 v3.1.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
|
github.com/openai/openai-go/v3 v3.28.0
|
||||||
|
github.com/samber/lo v1.53.0
|
||||||
golang.org/x/crypto v0.48.0
|
golang.org/x/crypto v0.48.0
|
||||||
golang.org/x/oauth2 v0.36.0
|
golang.org/x/oauth2 v0.36.0
|
||||||
|
google.golang.org/api v0.247.0
|
||||||
gorm.io/gorm v1.31.1
|
gorm.io/gorm v1.31.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cloud.google.com/go v0.121.6 // indirect
|
||||||
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||||
|
cloud.google.com/go/longrunning v0.6.7 // indirect
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
|
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||||
|
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||||
|
github.com/meilisearch/meilisearch-go v0.36.1 // indirect
|
||||||
github.com/tidwall/gjson v1.18.0 // indirect
|
github.com/tidwall/gjson v1.18.0 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/tidwall/sjson v1.2.5 // indirect
|
github.com/tidwall/sjson v1.2.5 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||||
|
golang.org/x/time v0.12.0 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
|
||||||
|
google.golang.org/grpc v1.74.2 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.7 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -40,10 +67,6 @@ require (
|
|||||||
github.com/gofiber/utils/v2 v2.0.2 // indirect
|
github.com/gofiber/utils/v2 v2.0.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
|
||||||
github.com/jackc/pgx/v5 v5.8.0 // indirect
|
|
||||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
@@ -53,7 +76,6 @@ require (
|
|||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/onsi/gomega v1.39.1 // indirect
|
github.com/onsi/gomega v1.39.1 // indirect
|
||||||
github.com/openai/openai-go/v3 v3.26.0
|
|
||||||
github.com/philhofer/fwd v1.2.0 // indirect
|
github.com/philhofer/fwd v1.2.0 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
@@ -69,5 +91,5 @@ require (
|
|||||||
golang.org/x/sys v0.42.0 // indirect
|
golang.org/x/sys v0.42.0 // indirect
|
||||||
golang.org/x/text v0.35.0 // indirect
|
golang.org/x/text v0.35.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gorm.io/driver/mysql v1.6.0 // indirect
|
gorm.io/driver/mysql v1.6.0
|
||||||
)
|
)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user