-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/product page #83
Conversation
WalkthroughThis pull request introduces several updates across various files, including the addition of new Vue components for product display and options, enhancements to the README with a new link, and the introduction of new interfaces in TypeScript for product management. It also includes a new CSS variable for danger states, updates to the Nuxt configuration for runtime settings, and the addition of documentation for new products and sensors. Overall, the changes enhance the functionality and structure of the Wiren Board website. Changes
Possibly related PRs
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 19
🧹 Outside diff range and nitpick comments (37)
utils/toTriads.ts (1)
1-3
: Add JSDoc documentation and unit testsPlease add documentation and tests to ensure reliability:
- Add JSDoc to describe the function's purpose, parameters, and return value
- Add unit tests for various scenarios
Here's a suggested documentation:
/** * Formats a number by adding space separators between groups of thousands * @param sum - The number to format * @returns The formatted string with spaces as thousand separators * @throws {Error} If the input is not a finite number * @example * toTriads(1234567.89) // returns "1 234 567.89" * toTriads(1000) // returns "1 000" */Would you like me to help create comprehensive unit tests for this utility function?
composables/useApi.ts (2)
10-11
: Consider handling missing user ID and validate base URL construction.The code assumes the API URL will always form a valid URL when combined with locale and path segments.
- const userId = useRequestHeader('x-wb-user-id'); - const baseURL = `${config.apiUrl || ''}/${locale.value}/ng/api/v1`; + const userId = useRequestHeader('x-wb-user-id') || undefined; + const apiUrl = config.apiUrl?.replace(/\/$/, ''); // Remove trailing slash if present + const baseURL = apiUrl ? `${apiUrl}/${locale.value}/ng/api/v1` : ''; + + if (!baseURL) { + throw new Error('API URL is not configured'); + }
1-14
: Consider adding retry logic and timeout configuration.For improved reliability, consider implementing retry logic for failed requests and configurable timeouts.
You could enhance the implementation by:
- Adding retry logic for transient failures
- Implementing request timeouts
- Adding request interceptors for common error handling
Would you like me to provide an example implementation with these features?
components/content/ProductSection.vue (3)
1-3
: Consider enhancing prop definition with validation and documentation.While the current implementation is functional, it could benefit from additional prop validation and documentation.
Consider applying these enhancements:
<script setup lang="ts"> +/** + * Section component for organizing product information + */ -defineProps<{ title: string; }>(); +interface Props { + /** Section title to be displayed in the header */ + title: string; +} + +const props = withDefaults(defineProps<Props>(), { + title: '', +}); </script>
9-9
: Consider modern CSS layout alternatives.The use of float clearing suggests a float-based layout. Modern CSS provides better alternatives.
Consider using Flexbox or Grid instead:
<template> <section class="productSection"> <h3>{{ title }}</h3> <ContentSlot :use="$slots.default" /> - <div class="productSection-clear" /> </section> </template> <style> .productSection { + display: flex; + flex-direction: column; padding: 20px 0; font-size: 16px; border-bottom: 1px solid var(--border-color); line-height: 24px; } -.productSection-clear { - clear: both; -} </style>Also applies to: 30-32
13-28
: Consider style improvements for better maintainability.While the styling is clean, there are a few improvements that could enhance maintainability.
Consider these enhancements:
-<style> +<style scoped> .productSection { padding: 20px 0; font-size: 16px; border-bottom: 1px solid var(--border-color); - line-height: 24px; + line-height: 1.5; } .productSection:first-of-type { padding: 0; } .productSection:last-of-type { border-bottom: 0; padding-bottom: 0; } </style>Key improvements:
- Added
scoped
attribute to prevent style leaking- Changed line-height to relative units for better scaling
package.json (1)
21-21
: Consider bundle size optimization for SwiperSince Swiper is a relatively large library (~140KB minified), consider:
- Using dynamic imports to load it only when needed
- Importing only the required modules instead of the full bundle
Example optimization in your Vue component:
// Instead of import { Swiper, SwiperSlide } from 'swiper'; // Use const { Swiper, SwiperSlide } = await import('swiper'); // Or for specific modules const { Swiper, SwiperSlide } = await import('swiper/core');pages/contents/product/[slug].vue (4)
3-3
: Consider making the boolean parameter more explicitThe second parameter
true
inuseLocalizedData
lacks clarity. Consider using a named parameter or constant to improve code readability.-const { data } = await useLocalizedData(`_catalog`, true, { _file: { $icontains: route.params.slug } }); +const PRERENDER_ENABLED = true; +const { data } = await useLocalizedData(`_catalog`, PRERENDER_ENABLED, { _file: { $icontains: route.params.slug } });
5-10
: Enhance error handling with more specific messagesThe error message could be more descriptive about what type of resource wasn't found.
if (!data.value) { throw createError({ statusCode: 404, - statusMessage: `Page not found: ${route.path}`, + statusMessage: `Product page not found for slug: ${route.params.slug}`, }); }
20-20
: Document the purpose of the custom meta tagThe
wb-hide-heading
meta tag's purpose is not immediately clear. Consider adding a comment explaining its functionality.+ // This meta tag controls the visibility of the default page heading { name: 'wb-hide-heading', content: 'true' },
12-23
: Consider adding structured data for better SEOProduct pages benefit from implementing JSON-LD structured data for better search engine visibility.
Consider adding Product schema:
useContentHead({ ...data.value, title: `${data.value.type} ${data.value.name}`, head: { meta: [ { name: 'description', content: data.value.meta }, { name: 'keywords', content: data.value.keywords }, { name: 'wb-hide-heading', content: 'true' }, - ] + ], + script: [ + { + type: 'application/ld+json', + children: JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'Product', + name: data.value.name, + description: data.value.meta, + }) + } + ] } });nuxt.config.ts (1)
7-11
: Consider Implementing a Proper Authentication ArchitectureThe current setup suggests implementing basic auth directly in client-side API calls, which is not a recommended approach for production applications.
Recommendations:
- Implement a proper authentication service:
- Use session-based auth or JWT tokens
- Handle authentication through secure HTTP-only cookies
- Implement proper CSRF protection
- Create dedicated API endpoints for authentication
- Consider using auth modules like
@nuxtjs/auth-next
for a more secure implementation- If the API requires basic auth, implement it in a server-side proxy to protect credentials
Would you like assistance in implementing a more secure authentication architecture?
components/content/VideoGallery.vue (1)
Line range hint
4-7
: Consider using an interface instead of tuple typeThe current tuple type
Video = [Url, Title, Cover]
could be refactored to an interface for better maintainability and readability.Consider this refactor:
-type Url = string; -type Title = string; -type Cover = string; -type Video = [Url, Title, Cover]; +interface Video { + url: string; + title: string; + cover: string; +}Then update the template accordingly:
-<VideoPlayer - :url="video[0]" - :cover="video[2]" - :height="162" - width="100%" -/> -<div class="videoGallery-title" v-if="video[1]">{{ video[1] }}</div> +<VideoPlayer + :url="video.url" + :cover="video.cover" + :height="162" + width="100%" +/> +<div class="videoGallery-title" v-if="video.title">{{ video.title }}</div>This would:
- Make the code more self-documenting
- Provide better TypeScript type checking
- Make it easier to add new properties in the future
- Improve maintainability
components/content/ProductSolutions.vue (1)
22-35
: Enhance styles with variables and transitionsConsider using CSS variables for consistent sizing and adding smooth transitions for responsive changes.
.productSolutions-list { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 32px; - font-size: 18px; + font-size: var(--text-lg, 18px); + transition: grid-template-columns 0.3s ease; @media (max-width: 1024px) { grid-template-columns: 1fr 1fr; } @media (max-width: 940px) { grid-template-columns: 1fr; } } + +.loading-skeleton { + height: 200px; + background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: loading 1.5s infinite; +}common/types.ts (2)
47-54
: Extract items object into a separate interfaceThe nested items object should be extracted into a separate interface for better reusability and maintainability.
Consider refactoring to:
+export interface ProductInventory { + available: number; + scheduled: number; + schedule_unit: 'days' | 'weeks' | 'months'; + inv_final_assembly: number; + inv_ready_to_assembly: number; + inv_scheduled: number; +} export interface Product { // ... other properties ... - items: { - available: number; - scheduled: number; - schedule_unit: 'days' | 'weeks' | 'months'; - inv_final_assembly: number; - inv_ready_to_assembly: number; - inv_scheduled: number; - }, + items: ProductInventory;
55-57
: Consider adding type constraints for arraysThe arrays
options
andcomponents
might benefit from non-empty array constraints if they are required to have at least one item.If these arrays should never be empty, consider using:
- options: ProductOption[]; - components: ProductOption[]; + options: [ProductOption, ...ProductOption[]]; + components: [ProductOption, ...ProductOption[]];components/content/ProductOptions.vue (2)
2-7
: Consider making some Option properties optionalThe Option interface currently requires all properties. Consider making
description
optional as not all options might need it.interface Option { id: number; name: string; image: string; - description: string; + description?: string; }
35-47
: Consider using CSS custom properties for layout valuesExtract magic numbers into CSS custom properties for better maintainability.
+:root { + --grid-gap: 24px; + --breakpoint-tablet: 800px; + --breakpoint-mobile: 520px; +} + .product-options { display: grid; grid-template-columns: repeat(3, 1fr); - gap: 24px; + gap: var(--grid-gap); - @media (max-width: 800px) { + @media (max-width: var(--breakpoint-tablet)) { grid-template-columns: repeat(2, 1fr); } - @media (max-width: 520px) { + @media (max-width: var(--breakpoint-mobile)) { grid-template-columns: 1fr; } }doc/catalog.md (5)
3-6
: Enhance directory structure documentation with additional details.Consider adding:
- A list of valid/supported TYPE values (controllers, sensors, wb-extensions, etc.)
- Guidelines for creating URL-safe SLUG values (e.g., allowed characters, format recommendations)
TYPE это тип товара, например controllers, sensors, wb-extensions... SLUG это то, что попадет в url в конечном итоге. + +Поддерживаемые значения TYPE: +* controllers +* sensors +* wb-extensions +* ... + +SLUG должен содержать только латинские буквы, цифры и дефисы, например: wb-8-all, temperature-sensor
11-12
: Add language specification to the code block and mark required fields.The fenced code block should specify the language (yaml) and indicate which fields are required vs optional.
-### Шаблон товара: -``` +### Шаблон товара +```yamlConsider adding a note about required fields:
### Обязательные поля * article * name * type * title * cover * documentationAlso applies to: 46-46
🧰 Tools
🪛 Markdownlint (0.35.0)
11-11: Punctuation: ':'
Trailing punctuation in heading(MD026, no-trailing-punctuation)
12-12: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
23-29
: Enhance media field documentation.Consider adding:
- Image format requirements (dimensions, file size limits)
- Video embed format specifications
images: - 1.webp (фотография товара №1 из папки `public/img/catalog/TYPE/SLUG`) - 2.webp (фотография товара №2 из папки `public/img/catalog/TYPE/SLUG`) + # Требования к изображениям: + # - Формат: WebP + # - Размеры: минимум 800x600px + # - Размер файла: до 500KB video: - https://peertube.wirenboard.com/w/bX7A9UTvBaNzx2Qm1pe7ms?start=1s (видео № 1) - https://peertube.wirenboard.com/w/bX7A9UTvBaNzx2Qm1pe7ms?start=1s (видео № 2) + # Поддерживаются только ссылки на PeerTube
11-11
: Fix markdown formatting issues and enhance component reference.
- Remove trailing punctuation from heading
- Add more context about available components
-### Шаблон товара: +### Шаблон товара -В описании товара можно использовать [компоненты](./components.md). +В описании товара можно использовать [компоненты](./components.md): +* `::product` - основной компонент страницы товара +* `::product-section` - секция с характеристиками +* Другие доступные компоненты описаны в документацииAlso applies to: 51-51
🧰 Tools
🪛 Markdownlint (0.35.0)
11-11: Punctuation: ':'
Trailing punctuation in heading(MD026, no-trailing-punctuation)
53-56
: Enhance preview instructions and fix bare URLs.The preview section should include development setup context and properly formatted URLs.
## Предпросмотр -Если вы редактируете и запускаете сайт локально на компьютере, вот ссылки для предпросмотра: -* http://localhost:3000/ru/contents/catalog/TYPE/SLUG страница товара на русском языке -* http://localhost:3000/en/contents/catalog/TYPE/SLUG страница товара на английском языке +Для локального предпросмотра: + +1. Убедитесь, что локальный сервер разработки запущен (`npm run dev`) +2. Откройте страницу товара: + * Русская версия: [`http://localhost:3000/ru/contents/catalog/TYPE/SLUG`](http://localhost:3000/ru/contents/catalog/TYPE/SLUG) + * English version: [`http://localhost:3000/en/contents/catalog/TYPE/SLUG`](http://localhost:3000/en/contents/catalog/TYPE/SLUG)🧰 Tools
🪛 Markdownlint (0.35.0)
55-55: null
Bare URL used(MD034, no-bare-urls)
56-56: null
Bare URL used(MD034, no-bare-urls)
content/ru/_catalog/controllers/wiren-board-8.md (4)
19-19
: Fix markdown header formattingAdd a space after the hash symbol in headers for better markdown compliance.
-#description +# description -#info +# infoAlso applies to: 27-27
🧰 Tools
🪛 Markdownlint (0.35.0)
19-19: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
24-25
: Consider restructuring hardware limitation noticeThe critical hardware limitation notice about MOD1-4 is buried within the differences section. Consider moving it to a separate "Important Notes" or "Limitations" section for better visibility.
66-66
: Consider removing or restructuring "in development" featuresThe line "CAN and HDMI (в разработке, если нужно, напишите нам)" mixes current features with future possibilities. Consider:
- Moving in-development features to a separate "Roadmap" section
- Or removing them entirely until they're available
69-75
: Consider enhancing compatibility informationThe compatibility section could be more helpful with:
- Version-specific compatibility notes
- Links to compatibility documentation for each listed model
- Any known limitations or exceptions
README.md (1)
7-7
: Consider adding English translations for documentation linksFor better accessibility and consistency, consider adding English translations for documentation links in parentheses, similar to how it's done in other parts of the documentation.
-[Товары из каталога](/doc/catalog.md); +[Товары из каталога (Products from catalog)](/doc/catalog.md);content/ru/_catalog/sensors/wb-msw-v4.md (5)
10-10
: Fix formatting in keywords metadataThere's a missing space between "RTU" and "ПЛК" in the keywords.
-keywords: Настенный комбинированный датчик, Modbus RTUПЛК +keywords: Настенный комбинированный датчик, Modbus RTU ПЛК
35-35
: Fix ATX heading formattingAdd a space after the hash symbol in headings for better markdown consistency.
-#description +# description -#info +# infoAlso applies to: 45-45
🧰 Tools
🪛 Markdownlint (0.35.0)
35-35: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
137-137
: Fix hyphenation in Russian textAccording to Russian grammar rules, certain phrases should be hyphenated.
-будет работать с устройством по Быстрому Modbus, если устройство ничего про расширение не знает — оно будет работать по стандартному Modbus RTU +будет работать с устройством по-быстрому Modbus, если устройство ничего про расширение не знает — оно будет работать по-стандартному Modbus RTU🧰 Tools
🪛 LanguageTool
[uncategorized] ~137-~137: Слово пишется через дефис: «по-Быстрому».
Context: ...онтроллера будет работать с устройством по Быстрому Modbus, если устройство ничего про расш...(Pravopisanie_po-prezhnemu)
[uncategorized] ~137-~137: Слово пишется через дефис: «по-стандартному».
Context: ...асширение не знает — оно будет работать по стандартному Modbus RTU. :: ::product-section{title...(Pravopisanie_po-prezhnemu)
194-194
: Consider using a more reliable link formatThe current Google redirect URL for the PDF might expire. Consider hosting the PDF file in the repository or using a direct link to the official source.
33-197
: Consider enhancing document structureThe document is well-organized but could benefit from additional semantic structure:
- Consider adding anchor links at the top for quick navigation to sections
- Consider adding a table of contents for better navigation in long documents
- Consider adding technical specifications in a structured table format for better readability
Would you like me to provide examples of these enhancements?
🧰 Tools
🪛 LanguageTool
[uncategorized] ~137-~137: Слово пишется через дефис: «по-Быстрому».
Context: ...онтроллера будет работать с устройством по Быстрому Modbus, если устройство ничего про расш...(Pravopisanie_po-prezhnemu)
[uncategorized] ~137-~137: Слово пишется через дефис: «по-стандартному».
Context: ...асширение не знает — оно будет работать по стандартному Modbus RTU. :: ::product-section{title...(Pravopisanie_po-prezhnemu)
🪛 Markdownlint (0.35.0)
35-35: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
45-45: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
components/content/Product.vue (4)
15-15
: Clarify the usage ofslice(4)
inimageFolder
pathThe expression
data.value._stem.slice(4)
removes the first four characters from_stem
. This may not be immediately clear to others. Consider adding a comment or refactoring to improve readability.
17-17
: Specify the type ofproduct
instead of usingany
Using
any
for theproduct
variable bypasses TypeScript's type checking, potentially leading to runtime errors. Since you're already importing theProduct
type, you can use it here for better type safety.Apply this change to specify the type:
-const product: any = await useApi<Product>(`/product/${data.value.article}/?locale=${locale.value}`); +const product = await useApi<Product>(`/product/${data.value.article}/?locale=${locale.value}`);
68-71
: Handle potential undefined properties in product availability displayWhen accessing
product?.items.available
andproduct?.items.inv_final_assembly
, there is a possibility thatitems
could be undefined, leading to display issues. Consider adding additional null checks to ensure robustness.Apply this change to add safe navigation:
-{{ t('inStock') }} {{ toTriads(product?.items.available) }} {{ t('pcs') }}<span v-if="product?.items.inv_final_assembly">, {{ t('more') }} {{ toTriads(product.items.inv_final_assembly) }} {{ t('pcs') }} {{ t(product.items.schedule_unit) }}</span> +{{ t('inStock') }} {{ toTriads(product?.items?.available) }} {{ t('pcs') }}<span v-if="product?.items?.inv_final_assembly">, {{ t('more') }} {{ toTriads(product.items.inv_final_assembly) }} {{ t('pcs') }} {{ t(product.items.schedule_unit) }}</span>
156-156
: Provide a fallback for thedvh
unit in CSSThe
dvh
unit may not be supported in all browsers. To ensure consistent layout across different browsers, consider adding a fallback using thevh
unit.Apply this change to include a fallback:
-height: calc(100dvh - var(--nav-height) - var(--app-bar-height) - var(--nav-margin)); +height: calc(100dvh - var(--nav-height) - var(--app-bar-height) - var(--nav-margin)); +height: calc(100vh - var(--nav-height) - var(--app-bar-height) - var(--nav-margin));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (30)
assets/icons/external-link.svg
is excluded by!**/*.svg
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
public/img/catalog/controllers/wiren-board-8/interface.png
is excluded by!**/*.png
public/img/catalog/controllers/wiren-board-8/po.png
is excluded by!**/*.png
public/img/catalog/controllers/wiren-board-8/wide.png
is excluded by!**/*.png
public/img/catalog/sensors/wb-msw-v4/10.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/11.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/2.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/3.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/4.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/5.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/6.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/7.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/8.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/9.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/advantages.png
is excluded by!**/*.png
public/img/catalog/sensors/wb-msw-v4/cert.png
is excluded by!**/*.png
public/img/catalog/sensors/wb-msw-v4/co2.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/commands.png
is excluded by!**/*.png
public/img/catalog/sensors/wb-msw-v4/hardware.png
is excluded by!**/*.png
public/img/catalog/sensors/wb-msw-v4/modbus.png
is excluded by!**/*.png
public/img/catalog/sensors/wb-msw-v4/quality.jpg
is excluded by!**/*.jpg
public/img/catalog/sensors/wb-msw-v4/settings.png
is excluded by!**/*.png
public/img/catalog/sensors/wb-msw-v4/voc.jpg
is excluded by!**/*.jpg
public/img/catalog/wb-extensions/WBIO-DI-WD-14/1.jpg
is excluded by!**/*.jpg
public/img/catalog/wb-extensions/WBIO-DI-WD-14/2.jpg
is excluded by!**/*.jpg
public/img/catalog/wb-extensions/WBIO-DI-WD-14/3.jpg
is excluded by!**/*.jpg
public/img/catalog/wb-extensions/WBIO-DI-WD-14/4.jpg
is excluded by!**/*.jpg
public/img/catalog/wb-extensions/WBIO-DI-WD-14/5.jpg
is excluded by!**/*.jpg
public/img/catalog/wb-extensions/WBIO-DI-WD-14/6.jpg
is excluded by!**/*.jpg
📒 Files selected for processing (17)
README.md
(1 hunks)assets/css/variables.css
(1 hunks)common/types.ts
(1 hunks)components/content/Product.vue
(1 hunks)components/content/ProductOptions.vue
(1 hunks)components/content/ProductSection.vue
(1 hunks)components/content/ProductSolutions.vue
(1 hunks)components/content/VideoGallery.vue
(1 hunks)composables/useApi.ts
(1 hunks)content/ru/_catalog/controllers/wiren-board-8.md
(1 hunks)content/ru/_catalog/sensors/wb-msw-v4.md
(1 hunks)content/ru/_catalog/wb-extensions/WBIO-DI-WD-14.md
(1 hunks)doc/catalog.md
(1 hunks)nuxt.config.ts
(1 hunks)package.json
(1 hunks)pages/contents/product/[slug].vue
(1 hunks)utils/toTriads.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- assets/css/variables.css
🧰 Additional context used
🪛 Markdownlint (0.35.0)
content/ru/_catalog/controllers/wiren-board-8.md
19-19: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
27-27: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
28-28: null
Images should have alternate text (alt text)
(MD045, no-alt-text)
content/ru/_catalog/sensors/wb-msw-v4.md
35-35: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
45-45: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
content/ru/_catalog/wb-extensions/WBIO-DI-WD-14.md
24-24: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
30-30: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
doc/catalog.md
11-11: Punctuation: ':'
Trailing punctuation in heading
(MD026, no-trailing-punctuation)
55-55: null
Bare URL used
(MD034, no-bare-urls)
56-56: null
Bare URL used
(MD034, no-bare-urls)
12-12: null
Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🪛 LanguageTool
content/ru/_catalog/sensors/wb-msw-v4.md
[uncategorized] ~137-~137: Слово пишется через дефис: «по-Быстрому».
Context: ...онтроллера будет работать с устройством по Быстрому Modbus, если устройство ничего про расш...
(Pravopisanie_po-prezhnemu)
[uncategorized] ~137-~137: Слово пишется через дефис: «по-стандартному».
Context: ...асширение не знает — оно будет работать по стандартному Modbus RTU. :: ::product-section{title...
(Pravopisanie_po-prezhnemu)
🔇 Additional comments (14)
utils/toTriads.ts (1)
1-3
: Verify usage in product price formatting
Since this utility is likely used for formatting product prices, we should verify its integration.
✅ Verification successful
Function is correctly used for number formatting in Product component
The toTriads
utility is being used appropriately in the Product component for formatting:
- Product prices (both regular and maximum prices)
- Stock quantities (available items and scheduled assembly)
All usages follow a consistent pattern of formatting numbers with thousand separators, followed by their respective units (₽ for prices, pcs for quantities). The implementation matches its usage context.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for usage of toTriads in product-related components
rg -l "toTriads" --type vue
Length of output: 55
Script:
#!/bin/bash
# Search for usage of toTriads in all files
rg "toTriads" -l
# Also search for any price formatting patterns that might use this utility
rg -i "price.*format|format.*price" -l
Length of output: 106
Script:
#!/bin/bash
# Let's check how toTriads is used in Product.vue
rg "toTriads" -A 5 -B 5 components/content/Product.vue
# Also check if there are any other number formatting utilities
rg -l "\.replace.*\d.*\d.*\d"
Length of output: 1093
composables/useApi.ts (1)
1-14
: Verify the impact on existing API calls.
Since this is a new file that will be used for API calls, we should verify its integration with existing components.
✅ Verification successful
No migration needed - useApi is a new addition
The verification shows that:
- The only existing
useFetch
call is within the newuseApi
composable itself - The only component using the new
useApi
isProduct.vue
, which appears to be a new implementation - The API URL configuration is properly set up in
nuxt.config.ts
This indicates that useApi
is a new addition rather than a replacement of existing code, and there are no existing API calls that need migration.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for existing useFetch calls that might need migration
echo "Searching for direct useFetch calls that might need to be migrated to useApi:"
rg "useFetch\(" --type vue --type ts
# Look for existing API URL construction patterns
echo -e "\nSearching for existing API URL construction patterns:"
rg "api/v1" --type vue --type ts
Length of output: 415
Script:
#!/bin/bash
# Search for existing useFetch calls that might need migration, using file extensions
echo "Searching for direct useFetch calls that might need to be migrated to useApi:"
rg "useFetch\(" -g "*.vue" -g "*.ts"
# Look for existing API URL construction patterns
echo -e "\nSearching for existing API URL construction patterns:"
rg "api/v1" -g "*.vue" -g "*.ts"
# Look for any existing API-related composables
echo -e "\nSearching for existing API-related composables:"
fd -e ts -e vue --exec grep -l "useApi\|apiUrl\|api/v1"
Length of output: 855
Script:
#!/bin/bash
# Check the content of the files that might be using the API
echo "Content of nuxt.config.ts:"
cat nuxt.config.ts
echo -e "\nContent of components/content/Product.vue:"
cat components/content/Product.vue
# Look for any other potential API-related patterns
echo -e "\nSearching for other API-related patterns:"
rg "apiUrl|baseURL|fetch\(" -g "*.vue" -g "*.ts" -g "*.js"
Length of output: 12429
components/content/ProductSection.vue (2)
6-8
: Good use of semantic HTML structure!
The use of <section>
with a proper heading hierarchy (<h3>
) follows accessibility best practices.
1-33
: Verify component integration with parent components.
As this is part of a new product page feature, let's verify its usage pattern.
✅ Verification successful
Let me try a different approach to verify the component integration.
Let me try one final search strategy to find any usage patterns.
Based on the search results, I can now provide a final response:
Component integration appears to be properly structured
The ProductSection
component follows the established patterns in the codebase:
- It's correctly placed in the
components/content
directory alongside other content components - It uses
ContentSlot
consistently with other components likeProduct
,Vacancy
, andSpoiler
- The component is part of a product-related feature set including
Product
,ProductOptions
, andProductSolutions
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for usage of ProductSection component
echo "Checking ProductSection usage patterns..."
rg -l "ProductSection" --type vue
# Check for potential parent components
echo "Checking potential parent components..."
ast-grep --pattern 'import { ProductSection } from $_'
Length of output: 300
Script:
#!/bin/bash
# Search for ProductSection usage across all files
echo "Checking ProductSection usage patterns..."
rg "ProductSection" -A 3 -B 3
# Search for files containing both ContentSlot and ProductSection
echo "Checking related component usage..."
rg "ContentSlot.*ProductSection|ProductSection.*ContentSlot" -A 3 -B 3
Length of output: 276
Script:
#!/bin/bash
# Find all Vue files in the repository
echo "Finding all Vue files..."
fd -e vue
# Search for any file containing 'product' case-insensitive
echo "Searching for product-related files..."
rg -i "product" -l
# Look for ContentSlot usage
echo "Checking ContentSlot usage..."
rg "ContentSlot" -A 2 -B 2
Length of output: 5246
package.json (1)
21-21
: Verify swiper version and security status
Let's check if version 11.1.15 is secure and up-to-date.
✅ Verification successful
Swiper dependency version is secure and up-to-date
The version 11.1.15 is currently the latest available version on npm, and there are no known vulnerabilities affecting versions above 6.5.1. The only reported vulnerability is for versions below 6.5.1 (we're using 11.1.15).
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check latest version and security advisories for swiper
echo "Latest version from npm:"
curl -s https://registry.npmjs.org/swiper/latest | jq '.version'
echo "\nChecking for known vulnerabilities:"
gh api graphql -f query='
{
securityVulnerabilities(first: 5, ecosystem: NPM, package: "swiper") {
nodes {
advisory {
summary
severity
publishedAt
}
vulnerableVersionRange
firstPatchedVersion {
identifier
}
}
}
}'
Length of output: 753
pages/contents/product/[slug].vue (1)
26-30
: 🛠️ Refactor suggestion
Add loading and error states to improve user experience
The template should handle loading and error states gracefully.
<template>
- <ContentRenderer>
- <ContentRendererMarkdown :value="data" />
- </ContentRenderer>
+ <div>
+ <template v-if="pending">
+ <LoadingSpinner />
+ </template>
+ <template v-else-if="error">
+ <ErrorDisplay :error="error" />
+ </template>
+ <template v-else>
+ <ContentRenderer>
+ <ContentRendererMarkdown :value="data" />
+ </ContentRenderer>
+ </template>
+ </div>
Consider implementing error boundaries and loading states to handle various data fetching scenarios.
Let's verify if these components exist in the codebase:
components/content/VideoGallery.vue (1)
9-9
: LGTM! Props definition improvement
The removal of the unused props
constant is a good practice since props are automatically injected into the template scope when using <script setup>
.
common/types.ts (1)
44-46
: Add validation for price ranges
The relationship between price
and optional price_min
/price_max
should be validated at runtime to ensure logical consistency.
Consider adding runtime validation to ensure:
- If
price_min
exists, it should be less than or equal toprice
- If
price_max
exists, it should be greater than or equal toprice
- If both exist,
price_min
should be less than or equal toprice_max
Would you like me to provide a validation utility function for these constraints?
components/content/ProductOptions.vue (1)
9-10
: Verify basket integration functionality
The component uses classes for basket integration. Ensure that the required basket functionality is properly implemented and documented.
content/ru/_catalog/controllers/wiren-board-8.md (1)
42-42
: Verify kernel version accuracy
The document mentions "kernel 6.8" with Debian 11, which seems unusually high as Debian 11 typically ships with a much lower kernel version. Please verify this information.
README.md (1)
7-7
: Verify the linked documentation file exists
The link addition is well-placed within the content editing instructions. Let's verify the referenced documentation file exists.
✅ Verification successful
Link to catalog documentation is valid
The referenced documentation file /doc/catalog.md
exists in the expected location.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the catalog.md documentation file exists
# Expected: File should exist at doc/catalog.md
fd --type f "catalog.md$" doc/
Length of output: 47
content/ru/_catalog/sensors/wb-msw-v4.md (2)
26-26
:
Fix incomplete video URL
The video URL appears to be truncated.
✅ Verification successful
Video URL is valid and accessible
The video URL is complete and functional. The HTTP 200 response confirms that the video embed URL is accessible and correctly formatted.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Verify if the video URL is accessible
curl -I "https://peertube.wirenboard.com/videos/embed/629d95d8-7ce8-4bad-83ad-7718ececeb9"
Length of output: 887
11-22
: Verify image assets existence
Let's ensure all referenced images exist in the repository.
✅ Verification successful
All referenced images exist in the repository
All images referenced in content/ru/_catalog/sensors/wb-msw-v4.md
are present in the public/img/catalog/sensors/wb-msw-v4/
directory with the correct filenames and extensions.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if all referenced images exist
for img in {1..11}; do
fd -t f "${img}.(webp|jpg)" || echo "Missing image: ${img}"
done
Length of output: 3795
components/content/Product.vue (1)
71-71
: Verify that product.items.schedule_unit
corresponds to valid translation keys
Using t(product.items.schedule_unit)
assumes that schedule_unit
contains a key like 'days'
, 'weeks'
, or 'months'
. Ensure all possible values of schedule_unit
are defined in the i18n messages to prevent translation issues.
Run the following script to verify the presence of these keys:
✅ Verification successful
Translation keys for schedule_unit
are properly defined and type-safe
The verification shows that:
- The
schedule_unit
is properly typed incommon/types.ts
to only accept 'days', 'weeks', or 'months' - These exact translation keys are defined in
Product.vue
for both Russian and English translations - The type system ensures that only valid values can be assigned to
schedule_unit
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that 'days', 'weeks', and 'months' keys are defined in i18n messages.
# Search for these keys in the i18n sections of Vue components.
rg '"(days|weeks|months)"' components/content/*.vue
Length of output: 717
Script:
#!/bin/bash
# Let's verify what values schedule_unit actually contains in the codebase
rg -B 2 -A 2 "schedule_unit" --type vue
Length of output: 67
Script:
#!/bin/bash
# Let's try searching without file type restriction to find schedule_unit usage
rg -B 2 -A 2 "schedule_unit"
Length of output: 1056
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (2)
components/content/Product.vue (2)
68-69
: Improve price formatting for better internationalizationThe price formatting is hardcoded to use Russian Ruble (₽) and doesn't handle different currency formats properly.
Consider using the Intl.NumberFormat API:
-<div class="product-price" v-if="product?.price">{{ toTriads(product.price) }} <sup class="product-priceUnit">₽</sup></div> +<div class="product-price" v-if="product?.price"> + {{ new Intl.NumberFormat(locale.value, { + style: 'currency', + currency: 'RUB', + currencyDisplay: 'symbol' + }).format(product.price) }} +</div>
211-217
: Use CSS variables for z-index valuesHardcoded z-index values can lead to stacking context issues. Consider using CSS variables for better maintainability.
+:root { + --z-index-navigation: 100; +} .product-navigation { position: sticky; background: #fff; border-bottom: 4px solid #000; margin-bottom: 48px; - z-index: 100; + z-index: var(--z-index-navigation); padding: 8px 0; top: 0; }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (7)
composables/useApi.ts (1)
7-9
: Consider security implications of runtime config credentials.While the Basic Auth implementation is correct, storing credentials in runtime config might expose them to client-side code. Consider:
- Using environment variables for sensitive data
- Moving authentication to a server-side middleware
components/content/Product.vue (6)
19-19
: Simplify class computation logicThe class computation can be simplified using optional chaining and array length checks.
-const addToOrderClass = (product?.options?.length || product?.components?.length) ? 'add-to-basket-set' : 'add-to-basket'; +const addToOrderClass = [product?.options, product?.components].some(arr => arr?.length) ? 'add-to-basket-set' : 'add-to-basket';
37-41
: Enhance Swiper configuration for better UXConsider adding more Swiper options to improve the navigation experience.
<swiper slidesPerView="auto" :spaceBetween="24" simulate-touch + :freeMode="true" + :mousewheel="true" + :watchOverflow="true" >
71-71
: Simplify complex string interpolationThe availability text combines multiple conditions and translations, making it hard to maintain. Consider extracting this logic into a computed property.
+const availabilityText = computed(() => { + const base = `${t('inStock')} ${toTriads(product?.items.available)} ${t('pcs')}`; + if (!product?.items.inv_final_assembly) return base; + + return `${base}, ${t('more')} ${toTriads(product.items.inv_final_assembly)} ${t('pcs')} ${t('scheduled')} ${t(product.items.schedule_unit)}`; +}); -<div class="product-availability"> - {{ t('inStock') }} {{ toTriads(product?.items.available) }} {{ t('pcs') }}<span v-if="product?.items.inv_final_assembly">, {{ t('more') }} {{ toTriads(product.items.inv_final_assembly) }} {{ t('pcs') }} {{ t('scheduled') }} {{ t(product.items.schedule_unit) }}</span> +<div class="product-availability">{{ availabilityText }}</div>
89-89
: Improve type safety in gallery image mappingThe type assertion for image strings could be more explicit.
-<ContentGallery :data="data?.images.map((image: string) => [`/${imageFolder}/${image}`])" /> +<ContentGallery :data="data?.images?.map((image: string) => [`/${imageFolder}/${image}`] as [string])" />
156-156
: Add fallback for dvh unitThe
dvh
unit might not be supported in all browsers. Consider adding a fallback.-height: calc(100dvh - var(--nav-height) - var(--app-bar-height) - var(--nav-margin)); +height: calc(100vh - var(--nav-height) - var(--app-bar-height) - var(--nav-margin)); +height: calc(100dvh - var(--nav-height) - var(--app-bar-height) - var(--nav-margin));
294-299
: Improve responsive design for order infoInstead of switching between fixed and auto min-width, consider using clamp or percentage-based width.
.product-orderInfo { - min-width: 450px; + width: clamp(300px, 100%, 450px); @media (max-width: 768px) { - min-width: auto; + width: 100%; } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
components/content/Product.vue
(1 hunks)composables/useApi.ts
(1 hunks)
🔇 Additional comments (5)
composables/useApi.ts (5)
1-2
: LGTM!
The import statement correctly brings in the necessary type for fetch options.
3-3
: LGTM!
The function signature is well-typed with proper generic type parameter and return type.
4-5
: LGTM!
Configuration and locale setup follows Nuxt's best practices.
14-15
: LGTM!
The API call implementation aligns with the team's preferences and requirements.
11-12
: Verify apiUrl configuration across environments.
The fallback to empty string when config.apiUrl
is undefined could lead to invalid API calls.
✅ Verification successful
Let me check the configuration in nuxt.config.ts to verify how apiUrl is configured.
The apiUrl configuration is properly handled through runtime config
The apiUrl
is correctly configured in nuxt.config.ts
using Nuxt's runtime configuration system, sourced from the environment variable NUXT_API_URL
. The fallback to empty string in useApi.ts
is actually a valid defensive programming practice in this case, as it allows for development and testing scenarios where the API URL might be relative. The configuration setup follows Nuxt's best practices for runtime configuration management.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if apiUrl is properly configured in Nuxt config files
rg -l "apiUrl.*=|apiUrl.*:" --type ts --type js
Length of output: 64
Script:
#!/bin/bash
# Check apiUrl configuration in nuxt.config.ts
rg "apiUrl" nuxt.config.ts -C 5
Length of output: 285
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (2)
components/content/Product.vue (2)
68-69
: Consider extracting availability text construction to a computed propertyThe availability text construction is complex and combines multiple conditions and translations. Consider extracting it to a computed property for better maintainability.
+const availabilityText = computed(() => { + const base = `${t('inStock')} ${toTriads(product?.items.available)} ${t('pcs')}`; + if (!product?.items.inv_final_assembly) return base; + return `${base}, ${t('more')} ${toTriads(product.items.inv_final_assembly)} ${t('pcs')} ${t('scheduled')} ${t(product.items.schedule_unit)}`; +});Then use it in the template:
-<div class="product-availability"> - {{ t('inStock') }} {{ toTriads(product?.items.available) }} {{ t('pcs') }}<span v-if="product?.items.inv_final_assembly">, {{ t('more') }} {{ toTriads(product.items.inv_final_assembly) }} {{ t('pcs') }} {{ t('scheduled') }} {{ t(product.items.schedule_unit) }}</span> -</div> +<div class="product-availability">{{ availabilityText }}</div>
135-137
: Consider using CSS variables for breakpointsThe media query breakpoints (768px, 1024px) are hardcoded. Consider defining them as CSS variables for better maintainability.
:root { --nav-height: 48px; --nav-margin: 34px; + --breakpoint-mobile: 768px; + --breakpoint-tablet: 1024px; }Then update the media queries:
-@media (max-width: 768px) +@media (max-width: var(--breakpoint-mobile))Also applies to: 168-174, 195-197
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
components/content/Product.vue
(1 hunks)
🔇 Additional comments (2)
components/content/Product.vue (2)
34-53
: Verify scroll behavior with fixed navigation
The navigation uses position: sticky
and scrollToElementById
. Ensure the scroll offset accounts for both the app bar and navigation heights to prevent content from being hidden under the sticky header.
✅ Verification successful
Scroll behavior implementation is correct
The scroll behavior is properly implemented with appropriate scroll margins:
- Global
--app-bar-height
is defined as 80px inassets/css/variables.css
- Product component defines
--nav-height
as 48px - Scroll margin in Product component correctly accounts for both heights:
calc(var(--app-bar-height) + var(--nav-height))
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for scroll margin definitions that might affect the scroll behavior
rg "scroll-margin-top|scroll-padding-top"
Length of output: 458
Script:
#!/bin/bash
# Let's verify the CSS variables definition
rg "(--app-bar-height|--nav-height)" -A 2
Length of output: 1242
14-15
: Verify the image folder path construction
The path construction data.value._stem.slice(4)
seems fragile. Consider adding validation or using a more robust path construction method.
✅ Verification successful
Based on the examination of the codebase, I can now provide a final response:
The path construction is safe and follows the content structure convention
The path construction data.value._stem.slice(4)
is actually following the established content structure convention in the project. The _stem
property comes from Nuxt Content's ParsedContentInternalMeta
interface, and the slice(4)
operation is removing the prefix from catalog items which are stored in content/{locale}/_catalog/
directory structure. This is evident from the examined catalog files which show the consistent pattern where product images are stored relative to their content files.
For example:
- Content file:
content/ru/_catalog/controllers/wiren-board-8.md
- Images referenced:
img/catalog/controllers/wiren-board-8/...
The slice(4)
removes the leading ru/_
to construct the correct image path.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for potential path construction issues
# Look for other instances of similar path construction
rg -l "_stem.slice\(4\)" | while read -r file; do
echo "=== $file ==="
rg -A 2 "_stem.slice\(4\)" "$file"
done
Length of output: 358
Script:
#!/bin/bash
# Let's check how _stem is being used across the codebase and its structure
rg -A 3 "_stem"
# Also check for any related path construction patterns with /img/
rg -A 3 "\/img\/"
# Look for catalog data structure or type definitions
fd -e ts -e d.ts | xargs rg -l "catalog|Product" | while read -r file; do
echo "=== $file ==="
cat "$file"
done
Length of output: 1683
Script:
#!/bin/bash
# Let's check the content structure and how catalog data is organized
fd -e json -e yaml -e yml | xargs rg -l "_catalog" | while read -r file; do
echo "=== $file ==="
cat "$file"
done
# Also check for the actual catalog content files to understand the _stem structure
fd -g "*_catalog*" | while read -r file; do
echo "=== $file ==="
cat "$file"
done
Length of output: 252
Script:
#!/bin/bash
# Let's examine the content of the _catalog directory
find content -type f -path "*/_catalog/*" -exec sh -c 'echo "=== {} ==="; cat "{}"' \;
# Also check for any configuration or documentation about content structure
fd "nuxt.config|content.config" | while read -r file; do
echo "=== $file ==="
cat "$file"
done
# Look for any documentation about content structure
fd "README|CONTRIBUTING" | while read -r file; do
echo "=== $file ==="
cat "$file"
done
Length of output: 19738
2. Фотографии Фотографии хочется листать, мы про это как-то говорили в контексте статей и кейсов, там тоже галерея используется. Но видимо тикет так и не поставил я :( Хорошо бы сделать в рамках этого проекта, а то получается ухудшаем пользовательский опыт, сейчас листать можно на старом сайте. Ещё они много места занимают по вертикали, если фоток много. Предлагаю сделать три в ряд, всё равно они кликабельные. И может сверстать чуть покрасивее, например, если фон у фотки белый, то он сольётся с фоном страницы и будет выглядеть странно. Может переиспользовать функции галереи в статьях? |
3. Объявление видео и картинок Сейчас оно объявляется так:
С одной стороны удобно - меньше кода. С другой — ломает привычки в других разделах сайта, а ещё делает невозможным, например, сделать вместо встраиваемых роликов, обложки при клике на которые будет открываться страница с роликом. Предлагаю унифицировать. |
4. Примеры использования Сейчас объявляются так и это очень похоже с тем, как было на сайте, то есть надо указать именно кейс:
Это хорошее решение, но в старом варианте была ещё ссылка на страницу внедрений, чтобы пользователи могли почитать и другие примеры, да и вообще о них узнали. Предлагаю добавлять автоматом эту ссылку на список внедрений. Можно где-то в настройках сайта задавать такие штуки. |
6. Опции С одной стороны классно, что мы из вынесли на страницу и теперь их не пропустят. С другой, мне не очень понятен кейс их применений. Если сказать пользователю, что такие опции есть, то вроде ок, полезно. Но вот по клику оно открывает калькулятор и… всё, сделать там мы уже ничего не можем, только добавить датчик в корзину без опций. Странно тут. Предлагаю не пытаться дублировать функцию кнопки Опции под ценой и просто вывести карточки опций без клика по ним. |
8. Порядок блоков на странице товаров Порядок блоков немного сбивает с толку, а так как страница длинная, то есть риск, что пользователи до конца никогда не долистают. Не знаю, хорошо это или плохо. Может компромиссное решение? Например, можно сворачивать аккордионом опции, фото? Они занимают много места, но вроде как не очень нужно каждый раз показывать. В целом я бы ожидал такой порядок на странице:
Если сворачивать фоточки и опции/комплектацию в аккордион, то так:
Наверное, даже хотелось бы где-то в настройках сайта задавать порядок блоков для всех товаров в одном месте. Очевидно, что он будет везде одинковый. Просто, чтобы можно было самому подвигать туда/сюда, чтобы добиться лучшего результата. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Оставил комменты
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (13)
components/content/Gallery.vue (2)
52-52
: Consider enhancing the gallery layout based on feedback.The
withBorder
prop is correctly passed to Photo components. However, based on the PR feedback, consider:
- Implementing a 3-column layout for better space utilization
- Adding clickable thumbnails for a more interactive gallery experience
- Improving the visual separation from the page background
Here's a suggested enhancement for the grid layout:
.gallery { gap: 0 12px; max-width: 100%; clear: both; display: grid; - grid-template-columns: repeat(v-bind('numberOfColumns'), 1fr); + grid-template-columns: repeat(3, 1fr); width: fit-content; @media (max-width: 700px) { grid-template-columns: 1fr; } }
Line range hint
8-42
: Enhance event handling safety and cleanup.The keyboard navigation implementation has several potential issues:
- Event listener cleanup might leak if component is destroyed while photo is open
- The debounced function is recreated on each watch callback
- Type safety could be improved for event handling
Consider these improvements:
+ import { onBeforeUnmount } from 'vue'; + + const susbscribeKeyPress = debounce(function({ keyCode }: KeyboardEvent) { - const susbscribeKeyPress = debounce(function({ keyCode }) { // ... existing logic }, 500, true); + + onBeforeUnmount(() => { + document.removeEventListener('keyup', susbscribeKeyPress, false); + });components/content/Photo.vue (1)
15-15
: Consider renaming the CSS class for better clarityThe class name
photo-withCaption
is now used for both caption and border cases, which could be confusing for maintenance. Consider renaming it to something more generic likephoto-decorated
or splitting it into separate classes.- 'photo-withCaption': caption || withBorder, + 'photo-decorated': caption || withBorder, -.photo-withCaption { +.photo-decorated { background: var(--gray-color); border: 1px solid var(--border-color); border-bottom: 0; border-radius: 6px 6px 0 0; padding: 6px; }Also applies to: 91-96
doc/catalog.md (2)
12-48
: Add language specification to the code block.The template code block should specify the language for better syntax highlighting.
-``` +```yaml🧰 Tools
🪛 Markdownlint (0.35.0)
12-12: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
57-58
: Improve URL formatting in preview section.Consider wrapping the local preview URLs in code blocks for better readability.
-* http://localhost:3000/ru/contents/product/TYPE/SLUG страница товара на русском языке -* http://localhost:3000/en/contents/product/TYPE/SLUG страница товара на английском языке +* `http://localhost:3000/ru/contents/product/TYPE/SLUG` страница товара на русском языке +* `http://localhost:3000/en/contents/product/TYPE/SLUG` страница товара на английском языке🧰 Tools
🪛 Markdownlint (0.35.0)
57-57: null
Bare URL used(MD034, no-bare-urls)
58-58: null
Bare URL used(MD034, no-bare-urls)
content/ru/_catalog/controllers/wiren-board-8.md (2)
26-26
: Add space after # in headers for better markdown compatibility.Headers should have a space after the hash symbol.
-#description +# description -#info +# infoAlso applies to: 34-34
🧰 Tools
🪛 Markdownlint (0.35.0)
26-26: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
31-32
: Consider making hardware limitation notice more prominent.The important notice about MOD1 limitations could be moved to the beginning of the description section for better visibility, as it's crucial information for users.
components/content/Product.vue (3)
66-70
: Improve price and availability displayThe price and availability section has complex conditional logic that could be simplified.
Consider extracting the price range and availability logic into computed properties:
<script setup> const priceRange = computed(() => { if (!product?.price) return ''; if (!product.price_max) return toTriads(product.price); return `${t('from')} ${toTriads(product.price)} ${t('to')} ${toTriads(product.price_max)}`; }); const availabilityText = computed(() => { const available = toTriads(product?.items.available); const assembly = product?.items.inv_final_assembly ? `, ${t('more')} ${toTriads(product.items.inv_final_assembly)} ${t('pcs')} ${t('scheduled')} ${t(product.items.schedule_unit)}` : ''; return `${t('inStock')} ${available} ${t('pcs')}${assembly}`; }); </script> <template> <div class="product-price" v-if="product?.price"> {{ toTriads(product.price) }} <sup class="product-priceUnit">₽</sup> </div> <div class="product-note"> {{ t('retailPrice') }} <span v-if="product?.price_max">{{ priceRange }} ₽ {{ t('dependsOnOptions') }}</span> </div> <div class="product-availability">{{ availabilityText }}</div> </template>
71-82
: Enhance button accessibilityThe order button could benefit from improved accessibility.
Add ARIA attributes and keyboard interaction:
<button :class="{ 'product-orderButton': true, 'add-to-basket-set': (product?.options?.length || product?.components?.length), 'add-to-basket': !(product?.options?.length || product?.components?.length), }" :data-product_id="product?.id" data-count="1" type="button" + :aria-label="(product?.options?.length || product?.components?.length) ? t('chooseOptions') : t('addToBasket')" + @keydown.enter="$event.target.click()" > {{ (product?.options?.length || product?.components?.length) ? t('chooseOptions') : t('addToBasket') }} </button>
219-233
: Consider improving mobile navigationThe navigation becomes non-sticky on mobile which might affect user experience.
Consider keeping the navigation sticky on mobile but with a condensed height, or implementing a floating action button for quick section access.
content/ru/_catalog/sensors/wb-msw-v4.md (3)
37-37
: Fix markdown heading formattingAdd a space after the hash symbol in headings for better markdown compatibility:
-#description +# description -#info +# infoAlso applies to: 47-47
🧰 Tools
🪛 Markdownlint (0.35.0)
37-37: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
139-139
: Fix Russian language hyphenationCorrect the hyphenation in Russian text:
-по Быстрому Modbus +по-быстрому Modbus -по стандартному Modbus RTU +по-стандартному Modbus RTU🧰 Tools
🪛 LanguageTool
[uncategorized] ~139-~139: Слово пишется через дефис: «по-Быстрому».
Context: ...онтроллера будет работать с устройством по Быстрому Modbus, если устройство ничего про расш...(Pravopisanie_po-prezhnemu)
[uncategorized] ~139-~139: Слово пишется через дефис: «по-стандартному».
Context: ...асширение не знает — оно будет работать по стандартному Modbus RTU. :: ::product-section{title...(Pravopisanie_po-prezhnemu)
34-199
: Review page layout and block orderingBased on the PR feedback, several structural improvements are needed:
- Address the large empty space under the title and image
- Implement collapsible sections for images and options
- Review and optimize the block order for better user experience
Consider implementing these changes:
- Add CSS to control vertical spacing on different screen sizes
- Use the site's collapsible component for image gallery and options
- Allow customization of block order through site settings
Would you like assistance in implementing any of these improvements?
🧰 Tools
🪛 LanguageTool
[uncategorized] ~139-~139: Слово пишется через дефис: «по-Быстрому».
Context: ...онтроллера будет работать с устройством по Быстрому Modbus, если устройство ничего про расш...(Pravopisanie_po-prezhnemu)
[uncategorized] ~139-~139: Слово пишется через дефис: «по-стандартному».
Context: ...асширение не знает — оно будет работать по стандартному Modbus RTU. :: ::product-section{title...(Pravopisanie_po-prezhnemu)
🪛 Markdownlint (0.35.0)
37-37: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
47-47: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (5)
public/img/catalog/controllers/wiren-board-8/2.jpg
is excluded by!**/*.jpg
public/img/catalog/controllers/wiren-board-8/3.jpg
is excluded by!**/*.jpg
public/img/catalog/controllers/wiren-board-8/4.jpg
is excluded by!**/*.jpg
public/img/catalog/controllers/wiren-board-8/5.jpg
is excluded by!**/*.jpg
public/img/catalog/controllers/wiren-board-8/6.jpg
is excluded by!**/*.jpg
📒 Files selected for processing (9)
common/links.ts
(1 hunks)components/content/Gallery.vue
(2 hunks)components/content/Photo.vue
(2 hunks)components/content/Product.vue
(1 hunks)components/content/ProductSolutions.vue
(1 hunks)content/ru/_catalog/controllers/wiren-board-8.md
(1 hunks)content/ru/_catalog/sensors/wb-msw-v4.md
(1 hunks)content/ru/_catalog/wb-extensions/WBIO-DI-WD-14.md
(1 hunks)doc/catalog.md
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- common/links.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- components/content/ProductSolutions.vue
🧰 Additional context used
📓 Learnings (2)
components/content/Product.vue (1)
Learnt from: ninedev-i
PR: wirenboard/website#83
File: components/content/Product.vue:66-67
Timestamp: 2024-11-28T12:11:37.747Z
Learning: In the Nuxt 3 project, when using the `toTriads` function in TypeScript components like `components/content/Product.vue`, Nuxt's auto-import feature handles the import, so explicit import statements are unnecessary.
content/ru/_catalog/controllers/wiren-board-8.md (2)
Learnt from: ninedev-i
PR: wirenboard/website#83
File: content/ru/_catalog/controllers/wiren-board-8.md:4-4
Timestamp: 2024-11-26T05:10:25.069Z
Learning: The user prefers not to receive comments about typos in the 'type' field or suggestions to use absolute paths for images in `content/ru/_catalog/controllers/wiren-board-8.md`.
Learnt from: ninedev-i
PR: wirenboard/website#83
File: content/ru/_catalog/controllers/wiren-board-8.md:28-28
Timestamp: 2024-11-26T05:07:55.127Z
Learning: In the file `content/ru/_catalog/controllers/wiren-board-8.md`, the user prefers not to add alt text to images.
🪛 Markdownlint (0.35.0)
doc/catalog.md
11-11: Punctuation: ':'
Trailing punctuation in heading
(MD026, no-trailing-punctuation)
57-57: null
Bare URL used
(MD034, no-bare-urls)
58-58: null
Bare URL used
(MD034, no-bare-urls)
12-12: null
Fenced code blocks should have a language specified
(MD040, fenced-code-language)
content/ru/_catalog/sensors/wb-msw-v4.md
37-37: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
47-47: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
content/ru/_catalog/wb-extensions/WBIO-DI-WD-14.md
26-26: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
32-32: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
content/ru/_catalog/controllers/wiren-board-8.md
26-26: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
34-34: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
37-37: null
Images should have alternate text (alt text)
(MD045, no-alt-text)
🪛 LanguageTool
content/ru/_catalog/sensors/wb-msw-v4.md
[uncategorized] ~139-~139: Слово пишется через дефис: «по-Быстрому».
Context: ...онтроллера будет работать с устройством по Быстрому Modbus, если устройство ничего про расш...
(Pravopisanie_po-prezhnemu)
[uncategorized] ~139-~139: Слово пишется через дефис: «по-стандартному».
Context: ...асширение не знает — оно будет работать по стандартному Modbus RTU. :: ::product-section{title...
(Pravopisanie_po-prezhnemu)
🔇 Additional comments (8)
components/content/Gallery.vue (1)
4-4
: LGTM! Props definition is well-typed and maintains backward compatibility.
The optional withBorder
prop is correctly typed and follows Vue.js naming conventions.
components/content/Photo.vue (2)
2-2
: LGTM: Props definition is well-structured
The addition of the optional withBorder
prop enhances the component's flexibility while maintaining good TypeScript practices.
15-15
: Verify visual consistency with border-only cases
The class photo-withCaption
will now be applied when withBorder
is true, even without a caption. Please verify that this produces the desired visual effect in all scenarios:
- With caption, no border
- With border, no caption
- With both caption and border
✅ Verification successful
CSS styling is consistent for all border and caption scenarios
After examining the component implementation, the change to include withBorder
in the photo-withCaption
class condition is correct and produces consistent styling:
- The
photo-withCaption
class adds a background, border, and rounded corners (6px 6px 0 0) - For gallery photos (
.photo-fromGallery.photo-withCaption
), it properly handles both border-only and caption cases with full rounded corners (6px) - When a caption is present, the caption styling (
photo-imageCaption
) complements the border styling with matching rounded corners (0 0 6px 6px)
The Gallery component correctly passes the withBorder
prop, ensuring consistent styling across all photos in the gallery. The visual presentation will be consistent in all scenarios:
- With caption only: Background and border with split rounded corners between photo and caption
- With border only: Background and border with full rounded corners
- With both: Same as caption-only case
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for usage patterns of the Photo component to verify all scenarios
ast-grep --pattern 'Photo :withBorder="$_" caption="$_"'
ast-grep --pattern 'Photo :withBorder="$_"'
ast-grep --pattern 'Photo caption="$_"'
Length of output: 146
Script:
#!/bin/bash
# Let's try a different approach to find Photo component usage
# First, let's check the CSS class definition
rg -l "photo-withCaption" --type vue
# Then search for Photo component usage with different patterns
rg "<Photo" --type vue -A 3
# Also check the component's style definition
rg "\.photo-withCaption" --type vue -A 3
Length of output: 193
Script:
#!/bin/bash
# Search without specifying file type
# Look for Photo component usage
rg "<Photo" -A 3
# Check CSS class definition
rg "\.photo-withCaption" -A 3
# Find all files containing photo-withCaption
rg -l "photo-withCaption"
Length of output: 782
Script:
#!/bin/bash
# Let's examine the full Photo component implementation
cat components/content/Photo.vue
# And check the Gallery component to see how it uses Photo
cat components/content/Gallery.vue
Length of output: 7301
content/ru/_catalog/wb-extensions/WBIO-DI-WD-14.md (3)
1-21
: LGTM! Metadata section is well-structured.
All required fields are present and properly formatted according to the catalog documentation guidelines.
24-30
: Well-written description with helpful product recommendation!
Good practice to include alternative product recommendation (WB-MCM8) for specific use cases.
🧰 Tools
🪛 Markdownlint (0.35.0)
26-26: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
32-57
: Technical specifications are well-organized and comprehensive.
Good use of product-section components to structure the information into logical categories.
🧰 Tools
🪛 Markdownlint (0.35.0)
32-32: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
components/content/Product.vue (1)
377-432
: i18n translations look good!
The translations are comprehensive and well-structured for both Russian and English locales.
content/ru/_catalog/sensors/wb-msw-v4.md (1)
27-27
:
Fix incomplete video URL
The video URL on line 27 appears to be truncated and missing characters at the end.
Please verify and update the complete URL:
- ["https://peertube.wirenboard.com/videos/embed/629d95d8-7ce8-4bad-83ad-7718ececeb9"],
+ ["https://peertube.wirenboard.com/videos/embed/629d95d8-7ce8-4bad-83ad-7718ececeb9f"],
Likely invalid or redundant comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Контроллер для автоматизаци
буковку забыл в конце
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (3)
content/ru/_catalog/controllers/wiren-board-8.md (3)
19-21
: Update video link to specific playlistInstead of linking to individual videos, consider linking to a specific playlist that can be managed through site settings for consistency.
24-33
: Consider improving page layout and block orderThe current layout has several issues mentioned in the feedback:
- Large empty space under the title and image can be confusing, especially on larger screens
- Block order could be improved for better user experience
Consider:
- Adjusting the spacing to reduce empty areas
- Implementing collapsible sections for better space utilization
- Making block order configurable through site settings for consistency across products
🧰 Tools
🪛 Markdownlint (0.35.0)
26-26: null
No space after hash on atx style heading(MD018, no-missing-space-atx)
29-29
: Enhance use cases sectionWhile the link to implementation examples is good, consider adding more context about use cases directly on the product page to improve user awareness.
Consider expanding this section with:
- Brief examples of common use cases
- Success stories or case studies
- Industry-specific applications
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
content/ru/_catalog/controllers/wiren-board-8.md
(1 hunks)
🧰 Additional context used
📓 Learnings (1)
content/ru/_catalog/controllers/wiren-board-8.md (2)
Learnt from: ninedev-i
PR: wirenboard/website#83
File: content/ru/_catalog/controllers/wiren-board-8.md:4-4
Timestamp: 2024-11-26T05:10:25.069Z
Learning: The user prefers not to receive comments about typos in the 'type' field or suggestions to use absolute paths for images in `content/ru/_catalog/controllers/wiren-board-8.md`.
Learnt from: ninedev-i
PR: wirenboard/website#83
File: content/ru/_catalog/controllers/wiren-board-8.md:28-28
Timestamp: 2024-11-26T05:07:55.127Z
Learning: In the file `content/ru/_catalog/controllers/wiren-board-8.md`, the user prefers not to add alt text to images.
🪛 Markdownlint (0.35.0)
content/ru/_catalog/controllers/wiren-board-8.md
26-26: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
34-34: null
No space after hash on atx style heading
(MD018, no-missing-space-atx)
37-37: null
Images should have alternate text (alt text)
(MD045, no-alt-text)
Добавил страницу товара

Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Chores