Skip to content

Commit 8cad9ec

Browse files
committed
feat: udpate customFilters and latest publications sections
1 parent ad155d9 commit 8cad9ec

7 files changed

Lines changed: 258 additions & 57 deletions

File tree

apps/studio/components/custom-filters-config/custom-filters-config-view.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3131
import type { SanityDocument } from "sanity";
3232
import { useClient } from "sanity";
3333

34-
import { computeFilterKeys } from "../../utils/denormalize-product";
3534
import { SortableFilterItem } from "../custom-filters-config/filter-item";
3635
import type { FilterConfigItem, RangeFilterStats } from "./types";
3736

@@ -411,20 +410,13 @@ export function CustomFiltersConfigView({
411410
// Check if we're working with a draft or need to create one
412411
const isCurrentlyDraft = currentProduct._id.startsWith("drafts.");
413412

414-
// Compute denormalized filter keys for dropdown filters
415-
const denormFilterKeys = computeFilterKeys(newFilterValues);
416-
417413
if (isCurrentlyDraft) {
418414
// Draft exists - just patch it
419415
await client
420416
.patch(draftProductId)
421417
.set({
422418
customFilterValues:
423419
newFilterValues.length > 0 ? newFilterValues : [],
424-
// Update denormalized filter keys
425-
denormFilterKeys:
426-
denormFilterKeys.length > 0 ? denormFilterKeys : [],
427-
denormLastSync: new Date().toISOString(),
428420
})
429421
.commit();
430422
} else {
@@ -440,14 +432,11 @@ export function CustomFiltersConfigView({
440432
_id: draftProductId,
441433
});
442434

443-
// Patch the customFilterValues and denormalized filter keys
435+
// Patch the customFilterValues
444436
transaction.patch(draftProductId, (patch) =>
445437
patch.set({
446438
customFilterValues:
447439
newFilterValues.length > 0 ? newFilterValues : [],
448-
denormFilterKeys:
449-
denormFilterKeys.length > 0 ? denormFilterKeys : [],
450-
denormLastSync: new Date().toISOString(),
451440
}),
452441
);
453442

apps/studio/schemaTypes/blocks/featured-products.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,28 @@ export const featuredProducts = defineType({
3838
description: "Główny przycisk wezwania do działania sekcji",
3939
validation: (Rule) => Rule.required().error("Przycisk CTA jest wymagany"),
4040
}),
41+
defineField({
42+
name: "newProductsMode",
43+
title: "Tryb wyboru nowych produktów",
44+
type: "string",
45+
description:
46+
"Wybierz, czy automatycznie pobrać 10 najnowszych produktów, czy wybrać ręcznie",
47+
options: {
48+
list: [
49+
{ title: "Automatycznie (10 najnowszych)", value: "automatic" },
50+
{ title: "Ręcznie wybrane", value: "manual" },
51+
],
52+
layout: "radio",
53+
},
54+
initialValue: "automatic",
55+
validation: (Rule) => Rule.required(),
56+
}),
4157
defineField({
4258
name: "newProducts",
4359
title: "Nowe produkty",
4460
type: "array",
4561
description: "Wybierz nowe produkty do wyświetlenia (3-8 elementów)",
62+
hidden: ({ parent }) => parent?.newProductsMode !== "manual",
4663
of: [
4764
{
4865
type: "reference",
@@ -76,12 +93,19 @@ export const featuredProducts = defineType({
7693
},
7794
},
7895
],
79-
validation: (Rule) => [
80-
Rule.min(3).error("Minimum 3 produkty"),
81-
Rule.max(8).error("Maksimum 8 produktów"),
82-
Rule.required().error("Produkty są wymagane"),
83-
Rule.unique().error("Każdy produkt może być wybrany tylko raz"),
84-
],
96+
validation: (Rule) =>
97+
Rule.custom((value, context) => {
98+
const parent = context.parent as { newProductsMode?: string };
99+
if (parent?.newProductsMode === "manual") {
100+
if (!value || !Array.isArray(value) || value.length < 3) {
101+
return "Minimum 3 produkty są wymagane";
102+
}
103+
if (value.length > 8) {
104+
return "Maksimum 8 produktów";
105+
}
106+
}
107+
return true;
108+
}),
85109
}),
86110
defineField({
87111
name: "bestsellers",
@@ -134,14 +158,18 @@ export const featuredProducts = defineType({
134158
select: {
135159
heading: "heading",
136160
description: "description",
161+
newProductsMode: "newProductsMode",
162+
newProductsCount: "newProducts",
137163
},
138-
prepare: ({ heading, description }) => {
164+
prepare: ({ heading, description, newProductsMode, newProductsCount }) => {
165+
const modeLabel =
166+
newProductsMode === "manual"
167+
? `Ręcznie (${Array.isArray(newProductsCount) ? newProductsCount.length : 0})`
168+
: "Auto (10 najnowszych)";
169+
139170
return {
140171
title,
141-
subtitle:
142-
toPlainText(heading) ||
143-
toPlainText(description) ||
144-
"Nowości i bestsellery",
172+
subtitle: `${toPlainText(heading) || toPlainText(description) || "Nowości i bestsellery"} | Nowości: ${modeLabel}`,
145173
media: Speaker,
146174
};
147175
},

apps/studio/schemaTypes/blocks/featured-publications.ts

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,39 @@ export const featuredPublications = defineType({
2121
'Główny nagłówek sekcji wyróżnionych publikacji (np. "Wyróżnione publikacje")',
2222
type: "heading",
2323
}),
24+
defineField({
25+
name: "selectionMode",
26+
title: "Tryb wyboru publikacji",
27+
type: "string",
28+
description:
29+
"Wybierz sposób wyświetlania publikacji: automatycznie od najnowszej, od 2. najnowszej lub ręcznie wybrane",
30+
options: {
31+
list: [
32+
{
33+
title: "Najnowsze publikacje (od najnowszej)",
34+
value: "latest",
35+
},
36+
{
37+
title: "Najnowsze publikacje (od 2. najnowszej)",
38+
value: "secondLatest",
39+
},
40+
{
41+
title: "Ręcznie wybrane publikacje",
42+
value: "manual",
43+
},
44+
],
45+
layout: "radio",
46+
},
47+
initialValue: "secondLatest",
48+
validation: (Rule) => Rule.required().error("Tryb wyboru jest wymagany"),
49+
}),
2450
defineField({
2551
name: "publications",
2652
title: "Wyróżnione publikacje",
2753
type: "array",
2854
description:
2955
"Wybierz publikacje do wyświetlenia w karuzeli (5-10 elementów). Produkty mogą być dodane tylko jeśli mają ustawiony obraz publikacji lub krótki opis.",
56+
hidden: ({ parent }) => parent?.selectionMode !== "manual",
3057
of: [
3158
{
3259
type: "reference",
@@ -50,22 +77,40 @@ export const featuredPublications = defineType({
5077
},
5178
},
5279
],
53-
validation: (Rule) => [
54-
Rule.min(5).error("Minimum 5 publikacji"),
55-
Rule.max(10).error("Maksimum 10 publikacji"),
56-
Rule.required().error("Publikacje są wymagane"),
57-
Rule.unique().error("Każda publikacja może być wybrana tylko raz"),
58-
],
80+
validation: (Rule) =>
81+
Rule.custom((value, context) => {
82+
const parent = context.parent as { selectionMode?: string };
83+
if (parent?.selectionMode === "manual") {
84+
if (!value || value.length === 0) {
85+
return "Publikacje są wymagane w trybie ręcznego wyboru";
86+
}
87+
if (value.length < 5) {
88+
return "Minimum 5 publikacji";
89+
}
90+
if (value.length > 10) {
91+
return "Maksimum 10 publikacji";
92+
}
93+
}
94+
return true;
95+
}),
5996
}),
6097
],
6198
preview: {
6299
select: {
63100
heading: "heading",
101+
selectionMode: "selectionMode",
102+
publicationsCount: "publications.length",
64103
},
65-
prepare: ({ heading }) => {
104+
prepare: ({ heading, selectionMode, publicationsCount }) => {
105+
const modeLabels: Record<string, string> = {
106+
latest: "Automatycznie: od najnowszej (20 publikacji)",
107+
secondLatest: "Automatycznie: od 2. najnowszej (20 publikacji)",
108+
manual: `Ręcznie: ${publicationsCount || 0} publikacji`,
109+
};
110+
66111
return {
67112
title,
68-
subtitle: toPlainText(heading),
113+
subtitle: `${toPlainText(heading) || "Brak nagłówka"}${modeLabels[selectionMode || "secondLatest"]}`,
69114
media: Highlighter,
70115
};
71116
},

apps/studio/schemaTypes/blocks/latest-publication.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,28 @@ export const latestPublication = defineType({
2020
type: "heading",
2121
maxLength: 60,
2222
}),
23+
defineField({
24+
name: "selectionMode",
25+
title: "Tryb wyboru publikacji",
26+
type: "string",
27+
description: "Wybierz, czy wyświetlić najnowszą publikację automatycznie, czy ręcznie wybraną",
28+
options: {
29+
list: [
30+
{ title: "Najnowsza publikacja (automatycznie)", value: "latest" },
31+
{ title: "Ręcznie wybrana publikacja", value: "manual" },
32+
],
33+
layout: "radio",
34+
},
35+
initialValue: "latest",
36+
validation: (Rule) => Rule.required().error("Tryb wyboru jest wymagany"),
37+
}),
2338
defineField({
2439
name: "publication",
2540
title: "Wybierz publikację",
2641
type: "reference",
2742
description:
28-
"Wybierz najnowszą publikację do wyświetlenia - może być to artykuł blogowy, recenzja lub produkt (z obrazem publikacji lub krótkim opisem)",
43+
"Wybierz publikację do wyświetlenia - może być to artykuł blogowy, recenzja lub produkt (z obrazem publikacji lub krótkim opisem)",
44+
hidden: ({ parent }) => parent?.selectionMode !== "manual",
2945
to: [{ type: "blog-article" }, { type: "review" }, { type: "product" }],
3046
options: {
3147
filter: `!(_id in path("drafts.**")) && (
@@ -34,21 +50,38 @@ export const latestPublication = defineType({
3450
defined(shortDescription))
3551
)`,
3652
},
37-
validation: (Rule) => Rule.required().error("Publikacja jest wymagana"),
53+
validation: (Rule) =>
54+
Rule.custom((value, context) => {
55+
const parent = context.parent as { selectionMode?: string };
56+
if (parent?.selectionMode === "manual" && !value) {
57+
return "Publikacja jest wymagana w trybie ręcznego wyboru";
58+
}
59+
return true;
60+
}),
3861
}),
3962
],
4063
preview: {
4164
select: {
4265
heading: "heading",
66+
selectionMode: "selectionMode",
4367
publication: "publication",
4468
publicationType: "publication._type",
4569
title: "publication.title",
4670
name: "publication.name",
4771
},
48-
prepare: ({ heading, publication, publicationType, title, name }) => {
72+
prepare: ({ heading, selectionMode, publication, publicationType, title, name }) => {
4973
// Get heading text if available
5074
const headingText = toPlainText(heading) || "Najnowsza publikacja";
5175

76+
// Handle automatic latest mode
77+
if (selectionMode === "latest" || !selectionMode) {
78+
return {
79+
title: headingText,
80+
subtitle: "Automatycznie: najnowsza publikacja",
81+
media: Newspaper,
82+
};
83+
}
84+
5285
// Get display name - prefer title if it's portable text, fallback to name
5386
const displayName = toPlainText(title) || name || "Brak tytułu";
5487

@@ -63,7 +96,7 @@ export const latestPublication = defineType({
6396
return {
6497
title: headingText,
6598
subtitle: publication
66-
? `${typeLabel}: ${displayName}`
99+
? `Ręcznie: ${typeLabel} - ${displayName}`
67100
: "Nie wybrano publikacji",
68101
media: Newspaper,
69102
};

apps/studio/tools/newsletter/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ type SanityAsset = {
7777
};
7878

7979
const NEWSLETTER_API_URL =
80-
"http://localhost:3000/api/newsletter/generate/";
80+
"http://audiofast.vercel.app/api/newsletter/generate/";
8181

8282
export default function NewsletterTool() {
8383
const client = useClient({ apiVersion: "2024-01-01" });

apps/web/src/components/products/ProductsListing/index.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,6 @@ export default async function ProductsListing({
122122
maxValue: rf.maxValue ?? null,
123123
}));
124124

125-
// Convert dropdown custom filters to filter key format for denormalized matching
126-
// The denormalized field denormFilterKeys stores strings like ["kolor:czarny", "material:drewno"]
127-
const customFilterKeys = customFilters.map(({ filterName, value }) => {
128-
const slug = slugifyFilterName(filterName);
129-
return `${slug}:${value.toLowerCase()}`;
130-
});
131-
132125
// Calculate offset/limit
133126
const offset = (currentPage - 1) * itemsPerPage;
134127
const limit = offset + itemsPerPage;
@@ -149,7 +142,7 @@ export default async function ProductsListing({
149142
brands: effectiveBrands,
150143
minPrice,
151144
maxPrice,
152-
customFilters: customFilterKeys, // Now uses denormalized filter key format
145+
customFilters, // Original format: [{filterName, value}]
153146
rangeFilters,
154147
isCPO,
155148
embeddingResults: embeddingResults || [],

0 commit comments

Comments
 (0)