Conversation
Replaces the free-text `position` field with a Select backed by a new SliderPositionEnum (home-main, home-secondary, category-top, product-side). The factory now derives its position from the enum, and the table column shows the readable label. Prevents typos that would silently break the storefront's slider lookup. Lang + db doc updated.
…stem Slider: mirror the admin SliderPositionEnum in shop; rename GetHeroSlides -> GetSliderByPosition(SliderPositionEnum) and have HomeController pass HOME_MAIN, so the admin's assigned position and the storefront lookup share one enum value instead of a hardcoded string. Localization: move ALL server-side user-facing Persian out of PHP into Laravel's lang system, default locale fa (APP_LOCALE=fa in .env, .env.example and phpunit.xml; fallback_locale=en so framework strings still resolve). Three lang/fa files: - enums.php: every enum label() (keyed enums.<enum>.<case>) - messages.php: flash/withErrors/abort strings, breadcrumbs, footer titles, home row titles, payment/result messages (payment.order_number takes an :id), deleted_product/guest_user fallbacks - validation.php: standard Laravel rules + attributes, so AddressController drops its inline messages/attributes and every form gets Persian errors Digit-normalization maps and code comments are intentionally left as-is. Docs/AGENTS/tests updated; a HomePageTest case asserts a non-home-main slider doesn't leak onto the hero.
Tags: new `tags` table + `attribute_tag` pivot, `Tag` model/factory/seeder
and `TagResource`. A tag is an SEO landing page for a category and/or
attribute filter, not a free-form product label (no `product_tag` pivot).
Deviations from the source schema: `category_id` is nullable and
attributes are many-to-many (so a tag can be category-only,
attribute-only, or both — at least one required, enforced in the form via
`requiredWithout`); SEO columns `title`/`description`/`no_index`/
`canonical` added to match categories/products; the single `attribute_id`
column and the user/seller `type` column are dropped (single-vendor).
Home sections: new `home_sections` table (not in the source schema) so
staff compose the storefront home page instead of it being hardcoded.
`HomeSectionTypeEnum` (slider/tags/categories/banners/products/brands),
a `config` JSON bag per type (`{"position": …}` for slider/banners,
`{"sort": …}` for product rows), `order` + `status`, and a
`HomeSectionResource` with a drag-to-reorder table whose form only shows
the fields the chosen type needs. `HomeSectionSeeder` seeds the current
hardcoded order. The storefront does not read this table yet.
Banner positions: `position` moves from a free-text input to a
`BannerPositionEnum` dropdown (home-top / home-middle / category-side),
mirrored in the shop so the assigned position and the storefront lookup
can't disagree; the table column and factory derive from the enum too.
Banner/slide `url` no longer requires an absolute URL — a leading `/`
internal path is accepted so they can link to tag pages.
SliderSeeder: create exactly one published slider per position (the
storefront takes the first published slider per position, so random
duplicates made the visible one nondeterministic) and delete via
`Slider::query()->delete()`, since Postgres refuses to TRUNCATE a table
that `slides` FK-references.
Tag pages: `GET /tags/{slug}` -> `TagController@show` + `Tags/Show.vue`.
A tag is an SEO landing page for a category and/or attribute filter, so
the page reuses the category machinery — `CollectCategoryIds` +
`GetCategoryProducts` + `GetCategoryFilters` — merging the tag's
attribute ids into the applied filters (OR within an attribute group,
AND across groups, same as the category page). For attribute-only tags
there is no category, so the controller passes an empty category-id list
and both shared actions now guard their category `whereIn` behind
`when($ids !== [])` ("no category constraint"); category pages always
pass ids, so they are unaffected. `app/Actions/Tag/BuildTagDetail`
(-> `TagDTO`, nullable category name/url) + `BuildTagBreadcrumbs`
(Home -> [Category …] -> Tag). SEO title/description/canonical/no_index
come from the tag; JSON-LD `BreadcrumbList`. Tests cover attribute
filtering, category-only, attribute-only (cross-category) and
multi-attribute AND.
Home: tags flagged `show_on_home` render as an image strip after the
category strip (`GetHomeTags` -> `tags` prop -> `Home/TagStrip.vue`),
each linking to its tag page.
Banners: `GetPromoBanners` becomes `GetBannersByPosition`, taking a
`BannerPositionEnum` mirrored from the admin enum, so the home grid asks
for `home-middle` instead of relying on an implicit convention — the
same pattern already used for slider positions.
Docs: TAGS.md rewritten as built; `home_sections` documented in the db
doc and flagged in both roadmaps as admin-only (the storefront still
renders a hardcoded home layout and does not read the table yet).
…hed checkout total
…Phase 4 still owes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
mainup to date with theshopbranch — 40 commits since PR #55.Breakdown: 29
feat, 6docs, 2test, 2refactor, 1fix.🤖 Generated with Claude Code