Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92a3f014a6 | ||
|
|
4c8da3765d | ||
|
|
ae6018a1f0 | ||
|
|
fcded6f139 |
Generated
-246
File diff suppressed because one or more lines are too long
-4
@@ -1,4 +0,0 @@
|
|||||||
<changelist name="Uncommitted_changes_before_Checkout_at_9_20_26,_11_55 AM_[Changes]" date="1789898166789" recycled="true" deleted="true">
|
|
||||||
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/Uncommitted_changes_before_Checkout_at_9_20_26,_11_55 AM_[Changes]/shelved.patch" />
|
|
||||||
<option name="DESCRIPTION" value="Uncommitted changes before Checkout at 9/20/26, 11:55 AM [Changes]" />
|
|
||||||
</changelist>
|
|
||||||
Generated
-143
File diff suppressed because one or more lines are too long
-4
@@ -1,4 +0,0 @@
|
|||||||
<changelist name="Uncommitted_changes_before_Checkout_at_9_21_26,_1_17 PM_[Changes]" date="1789989456881" recycled="true" deleted="true">
|
|
||||||
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/Uncommitted_changes_before_Checkout_at_9_21_26,_1_17 PM_[Changes]/shelved.patch" />
|
|
||||||
<option name="DESCRIPTION" value="Uncommitted changes before Checkout at 9/21/26, 1:17 PM [Changes]" />
|
|
||||||
</changelist>
|
|
||||||
Generated
+130
-85
@@ -4,8 +4,9 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="bb7b50a5-be9c-4cd7-a05b-979f0e91b173" name="Changes" comment="">
|
<list default="true" id="bb7b50a5-be9c-4cd7-a05b-979f0e91b173" name="Changes" comment="refactor(products): organize product showcase into feature module">
|
||||||
<change beforePath="$PROJECT_DIR$/components/HorizontalShowcase.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/components/HorizontalShowcase.tsx" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/tailwind.config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/tailwind.config.ts" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -27,61 +28,61 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="NextEditCompletionFeaturesState">
|
<component name="NextEditCompletionFeaturesState">
|
||||||
<decayedCancelled>
|
<decayedCancelled>
|
||||||
<entry key="MS100" value="1.028605430515295" />
|
<entry key="MS100" value="1.0" />
|
||||||
<entry key="MS500" value="2.124649469580447" />
|
<entry key="MS500" value="1.000008943214075" />
|
||||||
<entry key="S2" value="5.757603075779661" />
|
<entry key="S2" value="1.2607914241876252" />
|
||||||
<entry key="S5" value="9.075791406095624" />
|
<entry key="S5" value="3.6321166926353086" />
|
||||||
<entry key="S10" value="11.490304279732543" />
|
<entry key="S10" value="7.187879480049254" />
|
||||||
<entry key="S30" value="14.544855509715473" />
|
<entry key="S30" value="12.833490057716963" />
|
||||||
<entry key="S60" value="15.928253142043944" />
|
<entry key="S60" value="15.367124944343653" />
|
||||||
<entry key="M2" value="17.05794166660894" />
|
<entry key="M2" value="17.200465165116825" />
|
||||||
<entry key="M5" value="18.240030198039076" />
|
<entry key="M5" value="18.867586649419653" />
|
||||||
<entry key="M10" value="19.085397144523835" />
|
<entry key="M10" value="19.889539626550388" />
|
||||||
<entry key="M15" value="19.539401536900623" />
|
<entry key="M15" value="20.405494126294794" />
|
||||||
<entry key="M30" value="20.15328332293758" />
|
<entry key="M30" value="21.08410736765042" />
|
||||||
<entry key="H1" value="20.794543104303607" />
|
<entry key="H1" value="21.75882388976373" />
|
||||||
<entry key="H2" value="24.217320209573487" />
|
<entry key="H2" value="25.19651197545119" />
|
||||||
<entry key="H4" value="33.81335646745446" />
|
<entry key="H4" value="34.79882663024789" />
|
||||||
<entry key="D1" value="60.18887647810417" />
|
<entry key="D1" value="61.184565108820564" />
|
||||||
<entry key="W1" value="68.4601968975454" />
|
<entry key="W1" value="69.45949632611399" />
|
||||||
</decayedCancelled>
|
</decayedCancelled>
|
||||||
<decayedSelected>
|
<decayedSelected>
|
||||||
<entry key="MS100" value="0.0" />
|
<entry key="MS100" value="7.962034587841035E-12" />
|
||||||
<entry key="MS500" value="8.699625509373026E-98" />
|
<entry key="MS500" value="0.006028438183823964" />
|
||||||
<entry key="S2" value="5.430941684423347E-25" />
|
<entry key="S2" value="0.2786449669589018" />
|
||||||
<entry key="S5" value="1.9676599943042008E-10" />
|
<entry key="S5" value="0.5998193629466475" />
|
||||||
<entry key="S10" value="1.4027330445612952E-5" />
|
<entry key="S10" value="0.7744876138562475" />
|
||||||
<entry key="S30" value="0.02411709586160527" />
|
<entry key="S30" value="0.9379611448586518" />
|
||||||
<entry key="S60" value="0.1553011170701436" />
|
<entry key="S60" value="1.098380535936316" />
|
||||||
<entry key="M2" value="0.3961550964122234" />
|
<entry key="M2" value="1.3551692202762455" />
|
||||||
<entry key="M5" value="0.7735594310297959" />
|
<entry key="M5" value="1.7492815083633066" />
|
||||||
<entry key="M10" value="1.120827746179152" />
|
<entry key="M10" value="2.1050752944469457" />
|
||||||
<entry key="M15" value="1.3221230513291828" />
|
<entry key="M15" value="2.3102267135979067" />
|
||||||
<entry key="M30" value="1.6023719910246246" />
|
<entry key="M30" value="2.595453075209157" />
|
||||||
<entry key="H1" value="1.7960429930071773" />
|
<entry key="H1" value="2.792248246685056" />
|
||||||
<entry key="H2" value="2.045967012949897" />
|
<entry key="H2" value="3.0438541717577623" />
|
||||||
<entry key="H4" value="2.5063189725869783" />
|
<entry key="H4" value="3.5050645308767083" />
|
||||||
<entry key="D1" value="3.6098476224764395" />
|
<entry key="D1" value="4.609559468032772" />
|
||||||
<entry key="W1" value="3.9392268953128196" />
|
<entry key="W1" value="4.939182358578843" />
|
||||||
</decayedSelected>
|
</decayedSelected>
|
||||||
<decayedShown>
|
<decayedShown>
|
||||||
<entry key="MS100" value="0.04871208675588815" />
|
<entry key="MS100" value="3.2612493671796914E-8" />
|
||||||
<entry key="MS500" value="1.5761328815881446" />
|
<entry key="MS500" value="0.03182913112034664" />
|
||||||
<entry key="S2" value="5.568297668845106" />
|
<entry key="S2" value="0.7198587400143126" />
|
||||||
<entry key="S5" value="8.989731845795651" />
|
<entry key="S5" value="3.605555500545043" />
|
||||||
<entry key="S10" value="11.439232203057065" />
|
<entry key="S10" value="7.540560604413133" />
|
||||||
<entry key="S30" value="14.54354096178068" />
|
<entry key="S30" value="13.59016436886081" />
|
||||||
<entry key="S60" value="16.064294199401182" />
|
<entry key="S60" value="16.363500468632758" />
|
||||||
<entry key="M2" value="17.43942775764285" />
|
<entry key="M2" value="18.498243290148842" />
|
||||||
<entry key="M5" value="19.00501566584518" />
|
<entry key="M5" value="20.590803130608784" />
|
||||||
<entry key="M10" value="20.200966633195225" />
|
<entry key="M10" value="21.980529817792103" />
|
||||||
<entry key="M15" value="20.857682272562908" />
|
<entry key="M15" value="22.705973658811303" />
|
||||||
<entry key="M30" value="21.753511294575368" />
|
<entry key="M30" value="23.6744528413458" />
|
||||||
<entry key="H1" value="22.589437021258547" />
|
<entry key="H1" value="24.548438225385052" />
|
||||||
<entry key="H2" value="26.262649646152585" />
|
<entry key="H2" value="28.238985379440273" />
|
||||||
<entry key="H4" value="36.319290758304845" />
|
<entry key="H4" value="38.30313469133441" />
|
||||||
<entry key="D1" value="63.798632595714466" />
|
<entry key="D1" value="65.7939710746819" />
|
||||||
<entry key="W1" value="72.39940953778996" />
|
<entry key="W1" value="74.39865557179122" />
|
||||||
</decayedShown>
|
</decayedShown>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectColorInfo">{
|
<component name="ProjectColorInfo">{
|
||||||
@@ -89,43 +90,49 @@
|
|||||||
"associatedIndex": 2
|
"associatedIndex": 2
|
||||||
}</component>
|
}</component>
|
||||||
<component name="ProjectId" id="3HDEfy1HyzjDcELlwvnRRXxPltq" />
|
<component name="ProjectId" id="3HDEfy1HyzjDcELlwvnRRXxPltq" />
|
||||||
|
<component name="ProjectLevelVcsManager">
|
||||||
|
<ConfirmationsSetting value="2" id="Add" />
|
||||||
|
</component>
|
||||||
<component name="ProjectViewState">
|
<component name="ProjectViewState">
|
||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">{
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"ASKED_MARK_IGNORED_FILES_AS_EXCLUDED": "true",
|
"ASKED_MARK_IGNORED_FILES_AS_EXCLUDED": "true",
|
||||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||||
"RunOnceActivity.git.unshallow": "true",
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||||
"codeWithMe.voiceChat.enabledByDefault": "false",
|
"codeWithMe.voiceChat.enabledByDefault": "false",
|
||||||
"com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
|
"com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
|
||||||
"git-widget-placeholder": "develop",
|
"git-widget-placeholder": "develop",
|
||||||
"javascript.nodejs.core.library.configured.version": "24.20.0",
|
"javascript.nodejs.core.library.configured.version": "24.20.0",
|
||||||
"javascript.nodejs.core.library.typings.version": "24.13.3",
|
"javascript.nodejs.core.library.typings.version": "24.13.3",
|
||||||
"javascript.preferred.runtime.type.id": "node",
|
"javascript.preferred.runtime.type.id": "node",
|
||||||
"js.debugger.nextJs.config.created.client": "true",
|
"js.debugger.nextJs.config.created.client": "true",
|
||||||
"js.debugger.nextJs.config.created.server": "true",
|
"js.debugger.nextJs.config.created.server": "true",
|
||||||
"junie.onboarding.icon.badge.shown": "true",
|
"junie.onboarding.icon.badge.shown": "true",
|
||||||
"kronk.content.tree.expanded.paths": "",
|
"kronk.content.tree.expanded.paths": "",
|
||||||
"last_opened_file_path": "/home/hamed/Documents/Projects/GItLabRepo/device_web",
|
"last_opened_file_path": "/home/hamed/Documents/Projects/GItLabRepo/device_web",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.jshint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"node.js.selected.package.jshint": "",
|
||||||
"prettierjs.PrettierConfiguration.Package": "/home/hamed/Documents/Projects/GIthubRepo/robot-market-landing/node_modules/prettier",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"settings.editor.selected.configurable": "settings.javascript.prettier",
|
"nodejs_package_manager_path": "npm",
|
||||||
"to.speed.mode.migration.done": "true",
|
"prettierjs.PrettierConfiguration.Package": "/home/hamed/Documents/Projects/GIthubRepo/robot-market-landing/node_modules/prettier",
|
||||||
"ts.external.directory.path": "/home/hamed/Documents/Projects/GIthubRepo/robot-market-landing/node_modules/typescript/lib",
|
"settings.editor.selected.configurable": "settings.javascript.prettier",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"to.speed.mode.migration.done": "true",
|
||||||
|
"ts.external.directory.path": "/home/hamed/Documents/Projects/GIthubRepo/robot-market-landing/node_modules/typescript/lib",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}</component>
|
}]]></component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$" />
|
||||||
<recent name="D:\Project\GitHubRepo\robot-market-landing\public\images\icons" />
|
<recent name="D:\Project\GitHubRepo\robot-market-landing\public\images\icons" />
|
||||||
<recent name="D:\Project\GitHubRepo\robot-market-landing\public\images" />
|
<recent name="D:\Project\GitHubRepo\robot-market-landing\public\images" />
|
||||||
<recent name="D:\Project\GitHubRepo\robot-market-landing\app" />
|
<recent name="D:\Project\GitHubRepo\robot-market-landing\app" />
|
||||||
@@ -215,6 +222,10 @@
|
|||||||
<workItem from="1789973458932" duration="1450000" />
|
<workItem from="1789973458932" duration="1450000" />
|
||||||
<workItem from="1789981347522" duration="4504000" />
|
<workItem from="1789981347522" duration="4504000" />
|
||||||
<workItem from="1790050380142" duration="326000" />
|
<workItem from="1790050380142" duration="326000" />
|
||||||
|
<workItem from="1790568898974" duration="91000" />
|
||||||
|
<workItem from="1790569032481" duration="788000" />
|
||||||
|
<workItem from="1790573950198" duration="16000" />
|
||||||
|
<workItem from="1790660862579" duration="2098000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="update">
|
<task id="LOCAL-00001" summary="update">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -552,7 +563,39 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1789974962919</updated>
|
<updated>1789974962919</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="43" />
|
<task id="LOCAL-00043" summary="Replace desktop showcase video with scroll-driven color backgrounds">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1790492715355</created>
|
||||||
|
<option name="number" value="00043" />
|
||||||
|
<option name="presentableId" value="LOCAL-00043" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1790492715355</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00044" summary="Replace desktop showcase video with scroll-driven color backgrounds">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1790661145102</created>
|
||||||
|
<option name="number" value="00044" />
|
||||||
|
<option name="presentableId" value="LOCAL-00044" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1790661145102</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00045" summary="refactor(products): organize product showcase into feature module">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1790662441910</created>
|
||||||
|
<option name="number" value="00045" />
|
||||||
|
<option name="presentableId" value="LOCAL-00045" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1790662441910</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00046" summary="refactor(products): organize product showcase into feature module">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1790662596270</created>
|
||||||
|
<option name="number" value="00046" />
|
||||||
|
<option name="presentableId" value="LOCAL-00046" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1790662596270</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="47" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -581,6 +624,8 @@
|
|||||||
<MESSAGE value="chore: configure prettier for consistent WebStorm formatting" />
|
<MESSAGE value="chore: configure prettier for consistent WebStorm formatting" />
|
||||||
<MESSAGE value="FAZ1" />
|
<MESSAGE value="FAZ1" />
|
||||||
<MESSAGE value="Improve featured products layout and add support CTA" />
|
<MESSAGE value="Improve featured products layout and add support CTA" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="Improve featured products layout and add support CTA" />
|
<MESSAGE value="Replace desktop showcase video with scroll-driven color backgrounds" />
|
||||||
|
<MESSAGE value="refactor(products): organize product showcase into feature module" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="refactor(products): organize product showcase into feature module" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,599 @@
|
|||||||
|
# Next.js Frontend Architecture Guide
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
This document defines the architecture rules for this Next.js project.
|
||||||
|
|
||||||
|
Before implementing new features, refactoring existing code, or creating new modules, read and follow this architecture.
|
||||||
|
|
||||||
|
The goal is to create a scalable, production-ready frontend suitable for a professional development team.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Technology Stack
|
||||||
|
|
||||||
|
The project must use:
|
||||||
|
|
||||||
|
- Next.js (App Router)
|
||||||
|
- React
|
||||||
|
- TypeScript
|
||||||
|
- Redux Toolkit
|
||||||
|
- Axios
|
||||||
|
- Tailwind CSS
|
||||||
|
- Ant Design
|
||||||
|
|
||||||
|
Do not introduce alternative frameworks or libraries unless explicitly requested.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Architecture Pattern
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
## Feature-Based Architecture
|
||||||
|
|
||||||
|
Organize code around business features, not technical file types.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
|
||||||
|
components/
|
||||||
|
pages/
|
||||||
|
services/
|
||||||
|
utils/
|
||||||
|
```
|
||||||
|
|
||||||
|
as the main structure.
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
|
||||||
|
├── app/
|
||||||
|
│ ├── (routes)/
|
||||||
|
│ ├── api/
|
||||||
|
│ ├── providers/
|
||||||
|
│ ├── layout.tsx
|
||||||
|
│ ├── loading.tsx
|
||||||
|
│ ├── error.tsx
|
||||||
|
│ └── globals.css
|
||||||
|
│
|
||||||
|
├── features/
|
||||||
|
│ ├── auth/
|
||||||
|
│ ├── users/
|
||||||
|
│ ├── products/
|
||||||
|
│ ├── companies/
|
||||||
|
│ └── ...
|
||||||
|
│
|
||||||
|
├── components/
|
||||||
|
│ ├── ui/
|
||||||
|
│ ├── common/
|
||||||
|
│ └── layouts/
|
||||||
|
│
|
||||||
|
├── services/
|
||||||
|
│ ├── api/
|
||||||
|
│ ├── storage/
|
||||||
|
│ └── websocket/
|
||||||
|
│
|
||||||
|
├── store/
|
||||||
|
│
|
||||||
|
├── hooks/
|
||||||
|
│
|
||||||
|
├── lib/
|
||||||
|
│
|
||||||
|
├── types/
|
||||||
|
│
|
||||||
|
├── utils/
|
||||||
|
│
|
||||||
|
└── config/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Next.js App Router Rules
|
||||||
|
|
||||||
|
Use Next.js App Router.
|
||||||
|
|
||||||
|
Routes must be created using:
|
||||||
|
|
||||||
|
```
|
||||||
|
app/
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
app/dashboard/page.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
creates:
|
||||||
|
|
||||||
|
```
|
||||||
|
/dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not use React Router.
|
||||||
|
|
||||||
|
Do not manually create routing logic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Server Components vs Client Components
|
||||||
|
|
||||||
|
## Default Rule
|
||||||
|
|
||||||
|
All components should be Server Components by default.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
export default function UsersPage() {
|
||||||
|
return <div>Users</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client Components
|
||||||
|
|
||||||
|
Use Client Components only when required.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- useState
|
||||||
|
- useEffect
|
||||||
|
- Redux hooks
|
||||||
|
- Browser APIs
|
||||||
|
- Event handlers
|
||||||
|
|
||||||
|
Then add:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client';
|
||||||
|
```
|
||||||
|
|
||||||
|
at the top.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
export default function LoginForm() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not add `"use client"` unnecessarily.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Feature Structure
|
||||||
|
|
||||||
|
Each business feature must be isolated.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
features/auth/
|
||||||
|
|
||||||
|
├── api/
|
||||||
|
│ └── auth.api.ts
|
||||||
|
│
|
||||||
|
├── components/
|
||||||
|
│ └── LoginForm.tsx
|
||||||
|
│
|
||||||
|
├── hooks/
|
||||||
|
│ └── useLogin.ts
|
||||||
|
│
|
||||||
|
├── store/
|
||||||
|
│ └── auth.slice.ts
|
||||||
|
│
|
||||||
|
├── schemas/
|
||||||
|
│ └── auth.schema.ts
|
||||||
|
│
|
||||||
|
├── types.ts
|
||||||
|
│
|
||||||
|
└── index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Example business features:
|
||||||
|
|
||||||
|
```
|
||||||
|
features/
|
||||||
|
|
||||||
|
auth
|
||||||
|
users
|
||||||
|
companies
|
||||||
|
machines
|
||||||
|
inventory
|
||||||
|
sales
|
||||||
|
payments
|
||||||
|
reports
|
||||||
|
settings
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Component Architecture
|
||||||
|
|
||||||
|
## Shared Components
|
||||||
|
|
||||||
|
Reusable components belong here:
|
||||||
|
|
||||||
|
```
|
||||||
|
components/ui/
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```
|
||||||
|
Button
|
||||||
|
Modal
|
||||||
|
Input
|
||||||
|
Table
|
||||||
|
Dropdown
|
||||||
|
Form
|
||||||
|
```
|
||||||
|
|
||||||
|
These components must not contain business logic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Business components belong inside features:
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
features/products/components/ProductCard.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
Not:
|
||||||
|
|
||||||
|
```
|
||||||
|
components/ProductCard.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# API Architecture
|
||||||
|
|
||||||
|
All API communication must go through Axios.
|
||||||
|
|
||||||
|
Never call Axios directly inside components.
|
||||||
|
|
||||||
|
Wrong:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
function Users() {
|
||||||
|
axios.get('/users');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Correct:
|
||||||
|
|
||||||
|
```
|
||||||
|
Component
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Hook
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Feature API
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Axios Service
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Backend API
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Axios configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
services/api/
|
||||||
|
|
||||||
|
axios.ts
|
||||||
|
interceptors.ts
|
||||||
|
endpoints.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export const api = axios.create({
|
||||||
|
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Redux Toolkit Rules
|
||||||
|
|
||||||
|
Redux Toolkit is used only for global client state.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Authentication state
|
||||||
|
- User preferences
|
||||||
|
- Application settings
|
||||||
|
- Global UI state
|
||||||
|
|
||||||
|
Structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
store/
|
||||||
|
|
||||||
|
├── index.ts
|
||||||
|
├── provider.tsx
|
||||||
|
└── slices/
|
||||||
|
```
|
||||||
|
|
||||||
|
Feature state:
|
||||||
|
|
||||||
|
```
|
||||||
|
features/auth/store/
|
||||||
|
|
||||||
|
auth.slice.ts
|
||||||
|
auth.selector.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Do not store everything in Redux.
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```
|
||||||
|
useState
|
||||||
|
```
|
||||||
|
|
||||||
|
for local component state.
|
||||||
|
|
||||||
|
Use Redux only for shared application state.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Redux Provider in Next.js
|
||||||
|
|
||||||
|
Redux Provider must be a Client Component.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
store/provider.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import {Provider} from 'react-redux';
|
||||||
|
|
||||||
|
export function ReduxProvider({children}) {
|
||||||
|
return <Provider store={store}>{children}</Provider>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Register it in:
|
||||||
|
|
||||||
|
```
|
||||||
|
app/layout.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# TypeScript Rules
|
||||||
|
|
||||||
|
The project must be strongly typed.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
any;
|
||||||
|
```
|
||||||
|
|
||||||
|
Prefer:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface;
|
||||||
|
type;
|
||||||
|
generics;
|
||||||
|
unknown;
|
||||||
|
```
|
||||||
|
|
||||||
|
Each feature owns its types:
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
features/users/types.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Tailwind CSS Rules
|
||||||
|
|
||||||
|
Use Tailwind for:
|
||||||
|
|
||||||
|
- Layout
|
||||||
|
- Spacing
|
||||||
|
- Responsive design
|
||||||
|
- Custom styling
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
```
|
||||||
|
|
||||||
|
Avoid unnecessary CSS files.
|
||||||
|
|
||||||
|
Global CSS should only contain:
|
||||||
|
|
||||||
|
- Variables
|
||||||
|
- Theme
|
||||||
|
- Global styles
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ant Design Rules
|
||||||
|
|
||||||
|
Use Ant Design for complex UI components:
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Tables
|
||||||
|
- Forms
|
||||||
|
- Modal
|
||||||
|
- DatePicker
|
||||||
|
- Dropdown
|
||||||
|
- Pagination
|
||||||
|
- Notification
|
||||||
|
|
||||||
|
Use Tailwind for:
|
||||||
|
|
||||||
|
- Layout
|
||||||
|
- Positioning
|
||||||
|
- Spacing
|
||||||
|
- Responsive behavior
|
||||||
|
|
||||||
|
Do not rewrite Ant Design components unless required.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Data Fetching Rules
|
||||||
|
|
||||||
|
Follow this structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
Page
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Feature Component
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Custom Hook
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
API Layer
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Axios
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Backend
|
||||||
|
```
|
||||||
|
|
||||||
|
Never put business API logic inside UI components.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Dependency Rules
|
||||||
|
|
||||||
|
Features should remain independent.
|
||||||
|
|
||||||
|
Wrong:
|
||||||
|
|
||||||
|
```
|
||||||
|
features/products
|
||||||
|
|
||||||
|
imports
|
||||||
|
|
||||||
|
features/auth
|
||||||
|
```
|
||||||
|
|
||||||
|
Correct:
|
||||||
|
|
||||||
|
```
|
||||||
|
features/products
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
services
|
||||||
|
components
|
||||||
|
utils
|
||||||
|
```
|
||||||
|
|
||||||
|
Shared logic belongs in:
|
||||||
|
|
||||||
|
```
|
||||||
|
components/
|
||||||
|
services/
|
||||||
|
utils/
|
||||||
|
lib/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Refactoring Rules
|
||||||
|
|
||||||
|
When refactoring an existing project:
|
||||||
|
|
||||||
|
1. Analyze the current structure first.
|
||||||
|
2. Do not rewrite everything immediately.
|
||||||
|
3. Move code gradually into feature folders.
|
||||||
|
4. Preserve existing functionality.
|
||||||
|
5. Improve:
|
||||||
|
- Type safety
|
||||||
|
- Separation of concerns
|
||||||
|
- API abstraction
|
||||||
|
- Component reuse
|
||||||
|
- State management
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Code Quality Rules
|
||||||
|
|
||||||
|
Every file should have one responsibility.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```
|
||||||
|
User.tsx
|
||||||
|
|
||||||
|
- UI
|
||||||
|
- API
|
||||||
|
- Validation
|
||||||
|
- State
|
||||||
|
```
|
||||||
|
|
||||||
|
Prefer:
|
||||||
|
|
||||||
|
```
|
||||||
|
UserCard.tsx
|
||||||
|
|
||||||
|
user.api.ts
|
||||||
|
|
||||||
|
useUser.ts
|
||||||
|
|
||||||
|
user.schema.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Final Architecture Goal
|
||||||
|
|
||||||
|
The final project must be:
|
||||||
|
|
||||||
|
- Scalable
|
||||||
|
- Maintainable
|
||||||
|
- Team-friendly
|
||||||
|
- Type-safe
|
||||||
|
- Easy to test
|
||||||
|
- Ready for future features
|
||||||
|
|
||||||
|
Always prefer clean architecture over fast implementation.
|
||||||
|
|
||||||
|
Before creating code, understand where the code belongs in this architecture.
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import LocationsSection from '@/components/LocationsSection';
|
import LocationsSection from '@/components/LocationsSection';
|
||||||
import ShowcaseSection from '@/components/ShowcaseSection';
|
import {ShowcaseSection} from '@/features/products';
|
||||||
import FeaturesSection from '@/components/FeaturesSection';
|
import FeaturesSection from '@/components/FeaturesSection';
|
||||||
import AboutSection from '@/components/AboutSection';
|
import AboutSection from '@/components/AboutSection';
|
||||||
import HeroSection from '@/components/HeroSection';
|
import HeroSection from '@/components/HeroSection';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type {Metadata} from 'next';
|
import type {Metadata} from 'next';
|
||||||
import {notFound} from 'next/navigation';
|
import {notFound} from 'next/navigation';
|
||||||
import {content} from '@/data/content';
|
import {content} from '@/data/content';
|
||||||
import ProductDetails from '@/components/ProductDetails';
|
import {ProductDetails} from '@/features/products';
|
||||||
import ProtectedPage from '@/components/auth/ProtectedPage';
|
import ProtectedPage from '@/components/auth/ProtectedPage';
|
||||||
|
|
||||||
type Props = {params: {id: string}};
|
type Props = {params: {id: string}};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {Suspense} from 'react';
|
import {Suspense} from 'react';
|
||||||
import type {Metadata} from 'next';
|
import type {Metadata} from 'next';
|
||||||
import ProductsPage from '@/components/ProductsPage';
|
import {ProductsPage} from '@/features/products';
|
||||||
|
|
||||||
export const metadata: Metadata = {title: 'همه محصولات | روبات مارکت'};
|
export const metadata: Metadata = {title: 'همه محصولات | روبات مارکت'};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import {useEffect, useRef} from 'react';
|
|||||||
import {gsap} from 'gsap';
|
import {gsap} from 'gsap';
|
||||||
import {ScrollTrigger} from 'gsap/ScrollTrigger';
|
import {ScrollTrigger} from 'gsap/ScrollTrigger';
|
||||||
import VendingCard from './VendingCard';
|
import VendingCard from './VendingCard';
|
||||||
import {featuredMachines} from '@/data/products';
|
import {featuredMachines} from '@/features/products/data/catalog';
|
||||||
import {useLanguage} from '@/app/context/LanguageContext';
|
import {useLanguage} from '@/app/context/LanguageContext';
|
||||||
|
|
||||||
gsap.registerPlugin(ScrollTrigger);
|
gsap.registerPlugin(ScrollTrigger);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import {PhoneOutlined} from '@ant-design/icons';
|
import {PhoneOutlined} from '@ant-design/icons';
|
||||||
import {featuredMachines} from '@/data/products';
|
import {featuredMachines} from '@/features/products/data/catalog';
|
||||||
import {useLanguage} from '@/app/context/LanguageContext';
|
import {useLanguage} from '@/app/context/LanguageContext';
|
||||||
import {commerceCopy} from '@/data/commerce';
|
import {commerceCopy} from '@/data/commerce';
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ import Link from 'next/link';
|
|||||||
import {CheckCircleOutlined} from '@ant-design/icons';
|
import {CheckCircleOutlined} from '@ant-design/icons';
|
||||||
import {useLanguage} from '@/app/context/LanguageContext';
|
import {useLanguage} from '@/app/context/LanguageContext';
|
||||||
import {commerceCopy} from '@/data/commerce';
|
import {commerceCopy} from '@/data/commerce';
|
||||||
import QuantityControl from './QuantityControl';
|
import QuantityControl from '@/components/QuantityControl';
|
||||||
|
|
||||||
export default function ProductDetails({id}: {id: string}) {
|
export default function ProductDetails({id}: {id: string}) {
|
||||||
const {t, locale} = useLanguage();
|
const {t, locale} = useLanguage();
|
||||||
@@ -4,8 +4,8 @@ import Link from 'next/link';
|
|||||||
import {usePathname, useRouter, useSearchParams} from 'next/navigation';
|
import {usePathname, useRouter, useSearchParams} from 'next/navigation';
|
||||||
import {useLanguage} from '@/app/context/LanguageContext';
|
import {useLanguage} from '@/app/context/LanguageContext';
|
||||||
import {commerceCopy} from '@/data/commerce';
|
import {commerceCopy} from '@/data/commerce';
|
||||||
import {filterMachines, productCategories} from '@/data/products';
|
import {filterMachines, productCategories} from '@/features/products/data/catalog';
|
||||||
import QuantityControl from './QuantityControl';
|
import QuantityControl from '@/components/QuantityControl';
|
||||||
|
|
||||||
export default function ProductsPage() {
|
export default function ProductsPage() {
|
||||||
const {t, locale} = useLanguage();
|
const {t, locale} = useLanguage();
|
||||||
@@ -3,9 +3,6 @@
|
|||||||
import type {Machine} from '@/types/domain';
|
import type {Machine} from '@/types/domain';
|
||||||
import type {MouseEvent} from 'react';
|
import type {MouseEvent} from 'react';
|
||||||
import {useRef} from 'react';
|
import {useRef} from 'react';
|
||||||
import QuantityControl from './QuantityControl';
|
|
||||||
import ProtectedLink from './auth/ProtectedLink';
|
|
||||||
import {commerceCopy} from '@/data/commerce';
|
|
||||||
import {useLanguage} from '@/app/context/LanguageContext';
|
import {useLanguage} from '@/app/context/LanguageContext';
|
||||||
import FloatingItems from './FloatingItems';
|
import FloatingItems from './FloatingItems';
|
||||||
import {floatingSnacks} from '@/data/content';
|
import {floatingSnacks} from '@/data/content';
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export {default as ProductDetails} from './components/ProductDetails';
|
||||||
|
export {default as ProductsPage} from './components/ProductsPage';
|
||||||
|
export {default as ShowcaseSection} from './components/ShowcaseSection';
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import type {Config} from 'tailwindcss';
|
import type {Config} from 'tailwindcss';
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
darkMode: 'class',
|
darkMode: 'class',
|
||||||
content: ['./app/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}'],
|
content: ['./app/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}', './features/**/*.{js,jsx,ts,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
|
|||||||
Reference in New Issue
Block a user