feat (www): Add Wanted (wishlist) page (#15)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
deytenitandcopilot-swe-agent[bot] authored and GitHub committed 2026-05-04 18:58:46 +03:00
1 parent 07b16d404c
commit ef6ca40c72
29 files changed
+2232 -225

No files matched your search

+1
View File
@@ -29,6 +29,7 @@
"@ermnvldmr/i18n": "workspace:*",
"@ermnvldmr/stl": "workspace:*",
"@ermnvldmr/ui": "workspace:*",
"lucide-react": "^0.503.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tailwindcss": "^4.1.4"
+192
View File
@@ -0,0 +1,192 @@
import { createKeyset } from '@ermnvldmr/i18n';
export const { t } = createKeyset({
Wanted: {
en: 'Wanted',
ru: 'Разыскивается',
},
Home: {
en: 'Home',
ru: 'Главная'
},
'A quiet log of things I am planning to pick up eventually. It serves mostly as a personal reference, but also as a zero-pressure guide for friends.': {
en: 'A quiet log of things I am planning to pick up eventually. It serves mostly as a personal reference, but also as a zero-pressure guide for friends.',
ru: 'Список вещей, которые я планирую со временем приобрести. В основном это личная заметка, но также и ненавязчивый вишлист.',
},
'How this works': {
en: 'How this works',
ru: 'Как это работает',
},
'Think of this as a living list of things I plan to acquire over time. If you ever feel inspired to contribute, I would be genuinely thrilled, but please know it is never expected.': {
en: 'Think of this as a living list of things I plan to acquire over time. If you ever feel inspired to contribute, I would be genuinely thrilled, but please know it is never expected.',
ru: 'Считайте это живым списком вещей, которые я планирую приобрести. Если у вас когда-нибудь появится желание поучаствовать — я буду искренне рад, но, пожалуйста, знайте, что это абсолютно необязательно.',
},
'When it comes to the items themselves, authenticity and quality matter a lot to me. I would always prefer to have nothing at all rather than a replica or a knock-off.': {
en: 'When it comes to the items themselves, authenticity and quality matter a lot to me. I would always prefer to have nothing at all rather than a replica or a knock-off.',
ru: 'Когда дело доходит до самих вещей, подлинность и качество значат для меня очень много. Я всегда предпочту не иметь ничего, чем реплику или подделку.',
},
'And of course, if you are ever unsure about a specific edition or detail, we can always just talk about it.': {
en: 'And of course, if you are ever unsure about a specific edition or detail, we can always just talk about it.',
ru: 'И, конечно, если вы не уверены в каком-то конкретном издании или деталях, можно всегда это обсудить.',
},
'Figurines': {
en: 'Figurines',
ru: 'Фигурки',
},
'The specifics of the edition and its authenticity are quite important here. It is usually best to know the exact details to get it right.': {
en: 'The specifics of the edition and its authenticity are quite important here. It is usually best to know the exact details to get it right.',
ru: 'Специфика издания и его подлинность здесь довольно важны. Обычно лучше знать точные детали, чтобы не ошибиться.',
},
'Looking for': {
en: 'Looking for',
ru: 'Ищу',
},
'NENDOROID 1970 Jill Stingray (VA-11 Hall-A)': {
en: 'NENDOROID 1970 Jill Stingray (VA-11 Hall-A)',
ru: 'NENDOROID 1970 Jill Stingray (VA-11 Hall-A)',
},
'Mirror’s Edge Catalyst (Collector’s Edition)': {
en: 'Mirror’s Edge Catalyst (Collector’s Edition)',
ru: 'Mirror’s Edge Catalyst (Collector’s Edition)',
},
"Deus Ex: Mankind Divided (Collector's Edition)": {
en: "Deus Ex: Mankind Divided (Collector's Edition)",
ru: "Deus Ex: Mankind Divided (Collector's Edition)",
},
'Genshin Impact Pop! Aether (#160)': {
en: 'Genshin Impact Pop! Aether (#160)',
ru: 'Genshin Impact Pop! Aether (#160)',
},
'LEGO Sets': {
en: 'LEGO Sets',
ru: 'Наборы LEGO',
},
'I appreciate sets that focus on engineering and make for good display pieces, like Architecture, Technic, or the Botanical collection. I generally lean away from traditional play-sets.': {
en: 'I appreciate sets that focus on engineering and make for good display pieces, like Architecture, Technic, or the Botanical collection. I generally lean away from traditional play-sets.',
ru: 'Я ценю наборы, ориентированные на инженерию, которые хорошо смотрятся на полке — например, Architecture, Technic или Botanical. Обычно я избегаю традиционных игровых наборов (friends, city, и другие подобные).',
},
'Architectural landmarks or skylines': {
en: 'Architectural landmarks or skylines',
ru: 'Архитектурные наборы',
},
'NASA and space exploration sets (like the #92176 Ideas NASA Apollo Saturn V)': {
en: 'NASA and space exploration sets (like the #92176 Ideas NASA Apollo Saturn V)',
ru: 'Наборы NASA и иные аэрокосмические (например, #92176 Ideas NASA Apollo Saturn V)',
},
'High-fidelity Technic vehicles': {
en: 'High-fidelity Technic vehicles',
ru: 'Technic и другие высокотехнические наборы',
},
'Already Owned': {
en: 'Already Owned',
ru: 'Уже есть',
},
'Japanese Red Maple Bonsai (10348)': {
en: 'Japanese Red Maple Bonsai (10348)',
ru: 'Japanese Red Maple Bonsai (10348)',
},
'The Pig House (21170)': {
en: 'The Pig House (21170)',
ru: 'The Pig House (21170)',
},
'Die-cast Models': {
en: 'Die-cast Models',
ru: 'Дайкаст модели',
},
'I enjoy high-quality pre-assembled die-cast models. I am not much into plastic kits that require glue or paint to assemble.': {
en: 'I enjoy high-quality pre-assembled die-cast models. I am not much into plastic kits that require glue or paint to assemble.',
ru: 'Мне нравятся качественные предварительно собранные дайкаст модели. Я не особо увлекаюсь пластиковыми наборами, которые нужно собирать с помощью клея и красок.',
},
'Spacecraft scale replicas (SpaceX, NASA)': {
en: 'Spacecraft scale replicas (SpaceX, NASA)',
ru: 'Масштабные модели космических аппаратов (SpaceX, NASA)',
},
'Motorsport cars (Modern F1, GT3, Endurance Legends)': {
en: 'Motorsport cars (Modern F1, GT3, Endurance Legends)',
ru: 'Автоспорт (современные болиды Формулы-1, GT3, легенды эндуранс)',
},
'Aviation models (SR-71 Blackbird, Concorde)': {
en: 'Aviation models (SR-71 Blackbird, Concorde)',
ru: 'Авиационные модели (SR-71 Blackbird, Concorde)',
},
'Bburago – McLaren F1 MCL39 2025 #4 Norris': {
en: 'Bburago – McLaren F1 MCL39 2025 #4 Norris',
ru: 'Bburago – McLaren F1 MCL39 2025 #4 Norris',
},
'Coffee gear': {
en: 'Coffee gear',
ru: 'Всё для кофе',
},
'My current espresso setup uses a 51mm portafilter, so any accessories for it need to match that size perfectly.': {
en: 'My current espresso setup uses a 51mm portafilter, so any accessories for it need to match that size perfectly.',
ru: 'Мой текущий сетап для эспрессо использует 51-миллиметровый портафильтр, поэтому любые аксессуары для него должны идеально подходить по размеру.',
},
'AeroPress': {
en: 'AeroPress',
ru: 'AeroPress',
},
'Dedicated cold brewer (Hario or Toddy)': {
en: 'Dedicated cold brewer (Hario or Toddy)',
ru: 'Специализированная колба для колд-брю (Hario или Toddy)',
},
'51mm WDT Tool': {
en: '51mm WDT Tool',
ru: 'WDT-инструмент на 51 мм',
},
'Freshly roasted specialty coffee beans': {
en: 'Freshly roasted specialty coffee beans',
ru: 'Свежеобжаренные спешелти зерна',
},
'Espresso Machine': {
en: 'Espresso Machine',
ru: 'Эспрессо-машина',
},
'Hario V60': {
en: 'Hario V60',
ru: 'Hario V60',
},
'Manual Hand Grinder': {
en: 'Manual Hand Grinder',
ru: 'Ручная кофемолка',
},
'French Press': {
en: 'French Press',
ru: 'Френч-пресс',
},
'Hobby': {
en: 'Hobby',
ru: 'Хобби',
},
'Various tools and equipment for electronics and other side projects.': {
en: 'Various tools and equipment for electronics and other side projects.',
ru: 'Различные инструменты и оборудование для электроники и других проектов.',
},
'Alientek T90 Soldering Iron (or a similar compact, smart iron)': {
en: 'Alientek T90 Soldering Iron (or a similar compact, smart iron)',
ru: 'Паяльник Alientek T90 (или аналогичный компактный умный паяльник)',
},
'Other items': {
en: 'Other items',
ru: 'Другое',
},
'A few standalone pieces that caught my eye.': {
en: 'A few standalone pieces that caught my eye.',
ru: 'Несколько отдельных вещей, которые привлекли моё внимание.',
},
'TimePiece® 3D tear-off calendar': {
en: 'TimePiece® 3D tear-off calendar',
ru: 'Отрывной 3D-календарь TimePiece®',
},
'Seiko SSC813 Prospex watch': {
en: 'Seiko SSC813 Prospex watch',
ru: 'Часы Seiko SSC813 Prospex',
},
'Tag Heuer Carrera watch': {
en: 'Tag Heuer Carrera watch',
ru: 'Часы Tag Heuer Carrera',
},
'Cast Iron Cube 10x10x10cm (just for the tactile density)': {
en: 'Cast Iron Cube 10x10x10cm (just for the tactile density)',
ru: 'Чугунный куб 10x10x10 см (по приколу)',
},
});
+233
View File
@@ -0,0 +1,233 @@
import { localePath } from '@ermnvldmr/i18n';
import { BentoGrid, Header, Paragraph, VStack, Breadcrumbs } from '@ermnvldmr/ui';
import { Ghost, Coffee, Plane, Check, Gift, Cuboid, BoxSelect, Cpu } from 'lucide-react';
import { t } from './index.i18n';
import { DefaultLayout } from '../../components/Layout/DefaultLayout';
import { createPage } from '../../lib/core/createPage';
/**
* Wanted page component.
* Serves as a personal log of things to acquire.
*
* @example
* ```tsx
* createPage(WantedPage, { title: t('Wanted'), description: t('A quiet log of things I am planning to pick up eventually. It serves mostly as a personal reference, but also as a zero-pressure guide for friends.') });
* ```
*/
function WantedPage(): React.JSX.Element {
const breadcrumbs = (
<Breadcrumbs>
<Breadcrumbs.Item href={localePath('/')}>{t('Home')}</Breadcrumbs.Item>
<Breadcrumbs.Separator />
<Breadcrumbs.Item isCurrent>{t('Wanted')}</Breadcrumbs.Item>
</Breadcrumbs>
);
return (
<DefaultLayout
breadcrumbs={breadcrumbs}
currentPath={localePath('/wanted')}
description={t(
'A quiet log of things I am planning to pick up eventually. It serves mostly as a personal reference, but also as a zero-pressure guide for friends.'
)}
title={t('Wanted')}
>
<VStack gap={8}>
<VStack gap={4}>
<Header level={3}>{t('How this works')}</Header>
<VStack gap={4}>
<Paragraph size="m">
{t(
'Think of this as a living list of things I plan to acquire over time. If you ever feel inspired to contribute, I would be genuinely thrilled, but please know it is never expected.'
)}
</Paragraph>
<Paragraph size="m">
{t(
'When it comes to the items themselves, authenticity and quality matter a lot to me. I would always prefer to have nothing at all rather than a replica or a knock-off.'
)}
</Paragraph>
<Paragraph size="m">
{t(
'And of course, if you are ever unsure about a specific edition or detail, we can always just talk about it.'
)}
</Paragraph>
</VStack>
</VStack>
<BentoGrid>
{/* Collectibles - Figurines */}
<BentoGrid.ListCard
colSpan={2}
defaultValue={['wanted']}
description={t(
'The specifics of the edition and its authenticity are quite important here. It is usually best to know the exact details to get it right.'
)}
icon={<Ghost size={24} />}
sections={[
{
value: 'wanted',
label: t('Looking for'),
labelIcon: <Gift size={18} />,
items: [
t('NENDOROID 1970 Jill Stingray (VA-11 Hall-A)'),
t('Mirror’s Edge Catalyst (Collector’s Edition)'),
t("Deus Ex: Mankind Divided (Collector's Edition)"),
],
},
{
value: 'owned',
label: t('Already Owned'),
labelIcon: <Check size={18} />,
items: [t('Genshin Impact Pop! Aether (#160)')],
},
]}
title={t('Figurines')}
/>
{/* Collectibles - LEGO */}
<BentoGrid.ListCard
colSpan={2}
defaultValue={['wanted']}
description={t(
'I appreciate sets that focus on engineering and make for good display pieces, like Architecture, Technic, or the Botanical collection. I generally lean away from traditional play-sets.'
)}
icon={<Cuboid size={24} />}
sections={[
{
value: 'wanted',
label: t('Looking for'),
labelIcon: <Gift size={18} />,
items: [
t('Architectural landmarks or skylines'),
t('NASA and space exploration sets (like the #92176 Ideas NASA Apollo Saturn V)'),
t('High-fidelity Technic vehicles'),
],
},
{
value: 'owned',
label: t('Already Owned'),
labelIcon: <Check size={18} />,
items: [t('Japanese Red Maple Bonsai (10348)'), t('The Pig House (21170)')],
},
]}
title={t('LEGO Sets')}
/>
{/* Collectibles - Die-cast */}
<BentoGrid.ListCard
colSpan={2}
defaultValue={['wanted']}
description={t(
'I enjoy high-quality pre-assembled die-cast models. I am not much into plastic kits that require glue or paint to assemble.'
)}
icon={<Plane size={24} />}
sections={[
{
value: 'wanted',
label: t('Looking for'),
labelIcon: <Gift size={18} />,
items: [
t('Spacecraft scale replicas (SpaceX, NASA)'),
t('Motorsport cars (Modern F1, GT3, Endurance Legends)'),
t('Aviation models (SR-71 Blackbird, Concorde)'),
],
},
{
value: 'owned',
label: t('Already Owned'),
labelIcon: <Check size={18} />,
items: [t('Bburago – McLaren F1 MCL39 2025 #4 Norris')],
},
]}
title={t('Die-cast Models')}
/>
{/* Coffee stuff */}
<BentoGrid.ListCard
colSpan={2}
defaultValue={['wanted']}
description={t(
'My current espresso setup uses a 51mm portafilter, so any accessories for it need to match that size perfectly.'
)}
icon={<Coffee size={24} />}
sections={[
{
value: 'wanted',
label: t('Looking for'),
labelIcon: <Gift size={18} />,
items: [
t('AeroPress'),
t('Dedicated cold brewer (Hario or Toddy)'),
t('51mm WDT Tool'),
t('Freshly roasted specialty coffee beans'),
],
},
{
value: 'owned',
label: t('Already Owned'),
labelIcon: <Check size={18} />,
items: [
t('Espresso Machine'),
t('Hario V60'),
t('Manual Hand Grinder'),
t('French Press'),
],
},
]}
title={t('Coffee gear')}
/>
{/* Hobby */}
<BentoGrid.ListCard
colSpan={2}
defaultValue={['wanted']}
description={t('Various tools and equipment for electronics and other side projects.')}
icon={<Cpu size={24} />}
sections={[
{
value: 'wanted',
label: t('Looking for'),
labelIcon: <Gift size={18} />,
items: [
t('Alientek T90 Soldering Iron (or a similar compact, smart iron)'),
],
},
]}
title={t('Hobby')}
/>
{/* Other stuff */}
<BentoGrid.ListCard
colSpan={2}
defaultValue={['wanted']}
description={t('A few standalone pieces that caught my eye.')}
icon={<BoxSelect size={24} />}
sections={[
{
value: 'wanted',
label: t('Looking for'),
labelIcon: <Gift size={18} />,
items: [
t('TimePiece® 3D tear-off calendar'),
t('Seiko SSC813 Prospex watch'),
t('Tag Heuer Carrera watch'),
t('Cast Iron Cube 10x10x10cm (just for the tactile density)'),
],
},
]}
title={t('Other items')}
/>
</BentoGrid>
</VStack>
</DefaultLayout>
);
}
createPage(WantedPage, {
title: t('Wanted'),
description: t(
'A quiet log of things I am planning to pick up eventually. It serves mostly as a personal reference, but also as a zero-pressure guide for friends.'
),
});
export default WantedPage;
@@ -2,5 +2,6 @@ import { createKeyset } from '@ermnvldmr/i18n';
export const { t } = createKeyset({
Articles: { en: 'Articles', ru: 'Статьи' },
Wanted: { en: 'Wanted', ru: 'Разыскивается' },
GitHub: { en: 'GitHub', ru: 'ГитХаб' },
});
@@ -37,6 +37,7 @@ export const PageHead = ({ heading, caption, breadcrumbs, metadata, strategy }:
const nav = (
<HStack gap={4}>
<Link href="/articles">{t('Articles')}</Link>
<Link href="/wanted">{t('Wanted')}</Link>
<Link href="https://github.com/deytenit">{t('GitHub')}</Link>
</HStack>
);