master a83dde725a92 cached
57 files
113.7 KB
32.0k tokens
31 symbols
1 requests
Download .txt
Repository: TheCoderDream/React-Ecommerce-App-with-Redux
Branch: master
Commit: a83dde725a92
Files: 57
Total size: 113.7 KB

Directory structure:
gitextract_ub8tvy_4/

├── .gitignore
├── .idea/
│   ├── ecommerce.iml
│   ├── inspectionProfiles/
│   │   └── Project_Default.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── vcs.xml
│   └── workspace.xml
├── README.md
├── package.json
├── public/
│   ├── index.html
│   └── manifest.json
└── src/
    ├── App.js
    ├── App.scss
    ├── App.test.js
    ├── actions/
    │   └── index.js
    ├── components/
    │   ├── BrandFilter/
    │   │   ├── BrandFilter.js
    │   │   └── BrandFilter.scss
    │   ├── CartItem/
    │   │   ├── CartItem.js
    │   │   └── CartItem.scss
    │   ├── Footer/
    │   │   └── Footer.js
    │   ├── Header/
    │   │   └── Header.js
    │   ├── LayoutMode/
    │   │   ├── LayoutMode.js
    │   │   └── LayoutMode.scss
    │   ├── OrderFilter/
    │   │   ├── OrderFilter.js
    │   │   └── OrderFilter.scss
    │   ├── Pagination/
    │   │   ├── Pagination.js
    │   │   └── Pagination.scss
    │   ├── Product/
    │   │   ├── Product.js
    │   │   └── Product.scss
    │   ├── ProductDetail/
    │   │   └── ProductDetail.js
    │   ├── ProductSlider/
    │   │   ├── ProductSlider.js
    │   │   └── ProductSlider.scss
    │   └── SlideDots/
    │       ├── SlideDots.js
    │       └── SlideDots.scss
    ├── containers/
    │   ├── FilterBar/
    │   │   └── FilterBar.js
    │   └── ProductList/
    │       ├── ProductList.js
    │       └── ProductList.scss
    ├── data/
    │   ├── brands.js
    │   ├── getData.js
    │   └── phones.js
    ├── index.js
    ├── index.scss
    ├── pages/
    │   ├── Home/
    │   │   └── Home.js
    │   ├── ProductDetail/
    │   │   └── ProductDetail.js
    │   └── ShopingCart/
    │       └── ShoppingCart.js
    ├── pipes/
    │   ├── brandFilter.js
    │   ├── orderByFilter.js
    │   ├── paginationFilter.js
    │   ├── priceFormatter.js
    │   └── shortenTitle.js
    ├── reducers/
    │   ├── brand.filter.reducer.js
    │   ├── index.js
    │   ├── orderByPrice.filter.reducer.js
    │   ├── pagination.reducer.js
    │   └── shop.reducer.js
    ├── serviceWorker.js
    └── utilities/
        └── cumulativeOffset.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: .idea/ecommerce.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
  <component name="NewModuleRootManager">
    <content url="file://$MODULE_DIR$">
      <excludeFolder url="file://$MODULE_DIR$/.tmp" />
      <excludeFolder url="file://$MODULE_DIR$/temp" />
      <excludeFolder url="file://$MODULE_DIR$/tmp" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

================================================
FILE: .idea/inspectionProfiles/Project_Default.xml
================================================
<component name="InspectionProjectProfileManager">
  <profile version="1.0">
    <option name="myName" value="Project Default" />
    <inspection_tool class="Eslint" enabled="true" level="ERROR" enabled_by_default="true" />
  </profile>
</component>

================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="JavaScriptSettings">
    <option name="languageLevel" value="JSX" />
  </component>
</project>

================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/.idea/ecommerce.iml" filepath="$PROJECT_DIR$/.idea/ecommerce.iml" />
    </modules>
  </component>
</project>

================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="VcsDirectoryMappings">
    <mapping directory="$PROJECT_DIR$" vcs="Git" />
  </component>
</project>

================================================
FILE: .idea/workspace.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="BookmarkManager">
    <bookmark url="file://$PROJECT_DIR$/src/components/Pagination/Pagination.js" line="128" />
  </component>
  <component name="ChangeListManager">
    <list default="true" id="020428e6-7073-44e2-8b90-76d90e895943" name="Default Changelist" comment="">
      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
      <change beforePath="$PROJECT_DIR$/src/components/CartItem/CartItem.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/CartItem/CartItem.js" afterDir="false" />
      <change beforePath="$PROJECT_DIR$/src/components/Product/Product.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/Product/Product.js" afterDir="false" />
    </list>
    <ignored path="$PROJECT_DIR$/.tmp/" />
    <ignored path="$PROJECT_DIR$/temp/" />
    <ignored path="$PROJECT_DIR$/tmp/" />
    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
    <option name="SHOW_DIALOG" value="false" />
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
    <option name="LAST_RESOLUTION" value="IGNORE" />
  </component>
  <component name="FUSProjectUsageTrigger">
    <session id="-1590563976">
      <usages-collector id="statistics.lifecycle.project">
        <counts>
          <entry key="project.closed" value="6" />
          <entry key="project.open.time.0" value="3" />
          <entry key="project.open.time.1" value="2" />
          <entry key="project.open.time.2" value="2" />
          <entry key="project.open.time.3" value="1" />
          <entry key="project.open.time.5" value="2" />
          <entry key="project.open.time.6" value="1" />
          <entry key="project.open.time.7" value="1" />
          <entry key="project.opened" value="12" />
        </counts>
      </usages-collector>
      <usages-collector id="statistics.file.extensions.open">
        <counts>
          <entry key="html" value="1" />
          <entry key="js" value="85" />
          <entry key="json" value="2" />
          <entry key="phones" value="1" />
          <entry key="rnc" value="1" />
          <entry key="scss" value="28" />
        </counts>
      </usages-collector>
      <usages-collector id="statistics.file.types.open">
        <counts>
          <entry key="HTML" value="1" />
          <entry key="JSON" value="3" />
          <entry key="JavaScript" value="85" />
          <entry key="RNG Compact" value="1" />
          <entry key="SCSS" value="28" />
        </counts>
      </usages-collector>
      <usages-collector id="statistics.js.language.service.starts">
        <counts>
          <entry key="ESLintLanguageService" value="12" />
        </counts>
      </usages-collector>
      <usages-collector id="statistics.file.extensions.edit">
        <counts>
          <entry key="js" value="10067" />
          <entry key="scss" value="1168" />
          <entry key="txt" value="43" />
        </counts>
      </usages-collector>
      <usages-collector id="statistics.file.types.edit">
        <counts>
          <entry key="JavaScript" value="10067" />
          <entry key="PLAIN_TEXT" value="43" />
          <entry key="SCSS" value="1168" />
        </counts>
      </usages-collector>
    </session>
  </component>
  <component name="FileEditorManager">
    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/components/BrandFilter/BrandFilter.js">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="575">
              <caret line="29" column="62" selection-start-line="29" selection-start-column="62" selection-end-line="29" selection-end-column="62" />
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/components/BrandFilter/BrandFilter.scss">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="1311">
              <caret line="57" column="1" selection-start-line="57" selection-start-column="1" selection-end-line="57" selection-end-column="1" />
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/components/OrderFilter/OrderFilter.js">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="1173">
              <caret line="54" column="60" selection-start-line="54" selection-start-column="60" selection-end-line="54" selection-end-column="60" />
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/components/CartItem/CartItem.js">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="204">
              <caret line="66" column="46" selection-start-line="66" selection-start-column="46" selection-end-line="66" selection-end-column="46" />
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/data/phones.js">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="69">
              <caret line="3" column="15" selection-start-line="3" selection-start-column="15" selection-end-line="3" selection-end-column="15" />
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/components/Product/Product.js">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="-776">
              <caret line="31" column="43" selection-start-line="31" selection-start-column="43" selection-end-line="31" selection-end-column="43" />
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/components/Product/Product.scss">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="1610">
              <caret line="70" column="1" selection-start-line="70" selection-start-column="1" selection-end-line="70" selection-end-column="1" />
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/containers/ProductList/ProductList.js">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="1449">
              <caret line="71" column="88" selection-start-line="71" selection-start-column="88" selection-end-line="71" selection-end-column="88" />
              <folding>
                <element signature="e#0#39#0" expanded="true" />
              </folding>
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="false">
        <entry file="file://$PROJECT_DIR$/src/components/LayoutMode/LayoutMode.js">
          <provider selected="true" editor-type-id="text-editor">
            <state relative-caret-position="322">
              <caret line="15" column="7" selection-start-line="15" selection-start-column="7" selection-end-line="15" selection-end-column="7" />
              <folding>
                <element signature="e#0#26#0" expanded="true" />
              </folding>
            </state>
          </provider>
        </entry>
      </file>
      <file pinned="false" current-in-tab="true">
        <entry file="file://$PROJECT_DIR$/package.json">
          <provider selected="true" editor-type-id="text-editor" />
        </entry>
      </file>
    </leaf>
  </component>
  <component name="FileTemplateManagerImpl">
    <option name="RECENT_TEMPLATES">
      <list>
        <option value="Scss File" />
        <option value="JavaScript File" />
      </list>
    </option>
  </component>
  <component name="Git.Settings">
    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
  </component>
  <component name="IdeDocumentHistory">
    <option name="CHANGED_PATHS">
      <list>
        <option value="$PROJECT_DIR$/phones.json" />
        <option value="$PROJECT_DIR$/brands.js" />
        <option value="$PROJECT_DIR$/phones.js" />
        <option value="$PROJECT_DIR$/src/index.js" />
        <option value="$PROJECT_DIR$/src/containers/ProductList/ProductList.scss" />
        <option value="$PROJECT_DIR$/src/pipes/priceFormatter.js" />
        <option value="$PROJECT_DIR$/src/utilities/cumulativeOffset.js" />
        <option value="$PROJECT_DIR$/src/components/Footer/Footer.js" />
        <option value="$PROJECT_DIR$/src/components/SlideDots/SlideDots.scss" />
        <option value="$PROJECT_DIR$/src/components/SlideDots/SlideDots.js" />
        <option value="$PROJECT_DIR$/public/index.html" />
        <option value="$PROJECT_DIR$/src/pipes/shortenTitle.js" />
        <option value="$PROJECT_DIR$/src/components/ProductSlider.js" />
        <option value="$PROJECT_DIR$/src/components/ProductSlider/ProductSlider.js" />
        <option value="$PROJECT_DIR$/src/components/ProductSlider/ProductSlider.scss" />
        <option value="$PROJECT_DIR$/src/reducers/brand.filter.reducer.js" />
        <option value="$PROJECT_DIR$/src/pipes/brandFilter.js" />
        <option value="$PROJECT_DIR$/src/containers/FilterBar/FilterBar.js" />
        <option value="$PROJECT_DIR$/src/App.scss" />
        <option value="$PROJECT_DIR$/src/reducers/orderByPrice.filter.reducer.js" />
        <option value="$PROJECT_DIR$/src/reducers/index.js" />
        <option value="$PROJECT_DIR$/src/pipes/orderByFilter.js" />
        <option value="$PROJECT_DIR$/src/components/OrderFilter/OrderFilter.scss" />
        <option value="$PROJECT_DIR$/src/pages/ProductDetail/ProductDetail.js" />
        <option value="$PROJECT_DIR$/src/components/ProductDetail/ProductDetail.js" />
        <option value="$PROJECT_DIR$/src/index.scss" />
        <option value="$PROJECT_DIR$/src/pages/ShopingCart/ShoppingCart.js" />
        <option value="$PROJECT_DIR$/src/data/getData.js" />
        <option value="$PROJECT_DIR$/src/App.js" />
        <option value="$PROJECT_DIR$/src/actions/index.js" />
        <option value="$PROJECT_DIR$/src/reducers/pagination.reducer.js" />
        <option value="$PROJECT_DIR$/src/pipes/paginationFilter.js" />
        <option value="$PROJECT_DIR$/src/pages/Home/Home.js" />
        <option value="$PROJECT_DIR$/src/components/Pagination/Pagination.js" />
        <option value="$PROJECT_DIR$/src/reducers/shop.reducer.js" />
        <option value="$PROJECT_DIR$/src/components/CartItem/CartItem.scss" />
        <option value="$PROJECT_DIR$/src/components/Header/Header.js" />
        <option value="$PROJECT_DIR$/src/data/phones.js" />
        <option value="$PROJECT_DIR$/src/components/Product/Product.scss" />
        <option value="$PROJECT_DIR$/src/components/BrandFilter/BrandFilter.js" />
        <option value="$PROJECT_DIR$/src/components/BrandFilter/BrandFilter.scss" />
        <option value="$PROJECT_DIR$/src/components/OrderFilter/OrderFilter.js" />
        <option value="$PROJECT_DIR$/src/containers/ProductList/ProductList.js" />
        <option value="$PROJECT_DIR$/src/components/LayoutMode/LayoutMode.js" />
        <option value="$PROJECT_DIR$/src/components/CartItem/CartItem.js" />
        <option value="$PROJECT_DIR$/src/components/Product/Product.js" />
      </list>
    </option>
  </component>
  <component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
  <component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER">
    <package-json value="$PROJECT_DIR$/package.json" />
  </component>
  <component name="JsGulpfileManager">
    <detection-done>true</detection-done>
    <sorting>DEFINITION_ORDER</sorting>
  </component>
  <component name="NodeModulesDirectoryManager">
    <handled-path value="$PROJECT_DIR$/node_modules" />
  </component>
  <component name="NodePackageJsonFileManager">
    <packageJsonPaths>
      <path value="$PROJECT_DIR$/package.json" />
    </packageJsonPaths>
  </component>
  <component name="ProjectFrameBounds" extendedState="6">
    <option name="x" value="1750" />
    <option name="y" value="16" />
    <option name="width" value="2092" />
    <option name="height" value="2094" />
  </component>
  <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
  <component name="ProjectView">
    <navigator proportions="" version="1">
      <foldersAlwaysOnTop value="true" />
    </navigator>
    <panes>
      <pane id="Scope" />
      <pane id="ProjectPane">
        <subPane>
          <expand>
            <path>
              <item name="ecommerce" type="b2602c69:ProjectViewProjectNode" />
              <item name="ecommerce" type="462c0819:PsiDirectoryNode" />
            </path>
            <path>
              <item name="ecommerce" type="b2602c69:ProjectViewProjectNode" />
              <item name="ecommerce" type="462c0819:PsiDirectoryNode" />
              <item name="build" type="462c0819:PsiDirectoryNode" />
            </path>
            <path>
              <item name="ecommerce" type="b2602c69:ProjectViewProjectNode" />
              <item name="ecommerce" type="462c0819:PsiDirectoryNode" />
              <item name="src" type="462c0819:PsiDirectoryNode" />
            </path>
          </expand>
          <select />
        </subPane>
      </pane>
    </panes>
  </component>
  <component name="PropertiesComponent">
    <property name="WebServerToolWindowFactoryState" value="false" />
    <property name="last_opened_file_path" value="C:/AngularWorkBench/studyCase" />
    <property name="node.js.detected.package.eslint" value="true" />
    <property name="node.js.path.for.package.eslint" value="project" />
    <property name="node.js.selected.package.eslint" value="C:\ReactWorkBench\ecommerce\node_modules\eslint" />
    <property name="nodejs_interpreter_path" value="node" />
    <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
    <property name="nodejs_npm_path_reset_for_default_project" value="true" />
    <property name="nodejs_package_manager_path" value="yarn" />
    <property name="settings.editor.selected.configurable" value="configurable.group.appearance" />
  </component>
  <component name="RecentsManager">
    <key name="MoveFile.RECENT_KEYS">
      <recent name="C:\ReactWorkBench\ecommerce\src\components\ProductSlider" />
      <recent name="C:\ReactWorkBench\ecommerce\src\data" />
    </key>
  </component>
  <component name="RunDashboard">
    <option name="ruleStates">
      <list>
        <RuleState>
          <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
        </RuleState>
        <RuleState>
          <option name="name" value="StatusDashboardGroupingRule" />
        </RuleState>
      </list>
    </option>
  </component>
  <component name="RunManager">
    <configuration name="build" type="js.build_tools.npm" factoryName="npm" temporary="true" nameIsGenerated="true">
      <package-json value="$PROJECT_DIR$/package.json" />
      <command value="run" />
      <scripts>
        <script value="build" />
      </scripts>
      <node-interpreter value="project" />
      <envs />
      <method v="2" />
    </configuration>
    <recent_temporary>
      <list>
        <item itemvalue="npm.build" />
      </list>
    </recent_temporary>
  </component>
  <component name="SvnConfiguration">
    <configuration />
  </component>
  <component name="TaskManager">
    <task active="true" id="Default" summary="Default task">
      <changelist id="020428e6-7073-44e2-8b90-76d90e895943" name="Default Changelist" comment="" />
      <created>1551523495441</created>
      <option name="number" value="Default" />
      <option name="presentableId" value="Default" />
      <updated>1551523495441</updated>
      <workItem from="1551523496846" duration="7020000" />
      <workItem from="1551544849221" duration="39240000" />
      <workItem from="1551677285453" duration="127000" />
      <workItem from="1551677452146" duration="116000" />
      <workItem from="1551725494804" duration="7346000" />
      <workItem from="1552070634490" duration="785000" />
      <workItem from="1552071464919" duration="1882000" />
      <workItem from="1552110528332" duration="4934000" />
      <workItem from="1552159819586" duration="1845000" />
      <workItem from="1552209387669" duration="602000" />
      <workItem from="1552228612625" duration="2472000" />
      <workItem from="1552236746721" duration="574000" />
    </task>
    <task id="LOCAL-00001" summary="I've fixed some issues related to css.">
      <created>1552232148707</created>
      <option name="number" value="00001" />
      <option name="presentableId" value="LOCAL-00001" />
      <option name="project" value="LOCAL" />
      <updated>1552232148707</updated>
    </task>
    <option name="localTasksCounter" value="2" />
    <servers />
  </component>
  <component name="TimeTrackingManager">
    <option name="totallyTimeSpent" value="66943000" />
  </component>
  <component name="ToolWindowManager">
    <frame x="-6" y="-6" width="1933" height="1053" extended-state="6" />
    <editor active="true" />
    <layout>
      <window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.14391144" />
      <window_info id="Structure" order="1" side_tool="true" weight="0.25" />
      <window_info id="npm" order="2" side_tool="true" />
      <window_info id="Favorites" order="3" side_tool="true" />
      <window_info anchor="bottom" id="Message" order="0" />
      <window_info anchor="bottom" id="Find" order="1" />
      <window_info anchor="bottom" id="Run" order="2" weight="0.469163" />
      <window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
      <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
      <window_info anchor="bottom" id="TODO" order="6" />
      <window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
      <window_info anchor="bottom" id="Version Control" order="8" show_stripe_button="false" />
      <window_info anchor="bottom" id="Event Log" order="9" side_tool="true" />
      <window_info active="true" anchor="bottom" id="Terminal" order="10" visible="true" weight="0.20814978" />
      <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
      <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
      <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
    </layout>
    <layout-to-restore>
      <window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.06865671" />
      <window_info id="Structure" order="1" side_tool="true" weight="0.25" />
      <window_info id="npm" order="2" side_tool="true" />
      <window_info id="Favorites" order="3" side_tool="true" />
      <window_info anchor="bottom" id="Message" order="0" />
      <window_info anchor="bottom" id="Find" order="1" />
      <window_info anchor="bottom" id="Run" order="2" weight="0.32929516" />
      <window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
      <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
      <window_info anchor="bottom" id="TODO" order="6" />
      <window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
      <window_info anchor="bottom" id="Version Control" order="8" show_stripe_button="false" />
      <window_info anchor="bottom" id="Event Log" order="9" side_tool="true" />
      <window_info active="true" anchor="bottom" id="Terminal" order="10" visible="true" weight="0.0" />
      <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
      <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
      <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
    </layout-to-restore>
  </component>
  <component name="TypeScriptGeneratedFilesManager">
    <option name="version" value="1" />
  </component>
  <component name="VcsContentAnnotationSettings">
    <option name="myLimit" value="2678400000" />
  </component>
  <component name="VcsManagerConfiguration">
    <MESSAGE value="I've fixed some issues related to css." />
    <option name="LAST_COMMIT_MESSAGE" value="I've fixed some issues related to css." />
  </component>
  <component name="XDebuggerManager">
    <breakpoint-manager>
      <breakpoints>
        <line-breakpoint enabled="true" type="javascript">
          <url>file://$PROJECT_DIR$/src/pages/ShopingCart/ShoppingCart.js</url>
          <line>30</line>
          <option name="timeStamp" value="1" />
        </line-breakpoint>
        <line-breakpoint enabled="true" type="javascript">
          <url>file://$PROJECT_DIR$/src/containers/ProductList/ProductList.js</url>
          <option name="timeStamp" value="2" />
        </line-breakpoint>
      </breakpoints>
    </breakpoint-manager>
  </component>
  <component name="editorHistoryManager">
    <entry file="file://$PROJECT_DIR$/src/data/brands.js">
      <provider selected="true" editor-type-id="text-editor">
        <state>
          <caret column="82" selection-start-column="82" selection-end-column="82" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pipes/priceFormatter.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="46">
          <caret line="2" column="2" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="2" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/utilities/cumulativeOffset.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="276">
          <caret line="12" column="2" selection-start-line="12" selection-start-column="2" selection-end-line="12" selection-end-column="2" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/containers/ProductList/ProductList.scss">
      <provider selected="true" editor-type-id="text-editor" />
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/SlideDots/SlideDots.scss">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="69">
          <caret line="3" column="15" selection-start-line="3" selection-start-column="15" selection-end-line="3" selection-end-column="15" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pipes/shortenTitle.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="46">
          <caret line="2" column="2" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="2" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pipes/brandFilter.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="46">
          <caret line="2" lean-forward="true" selection-start-line="2" selection-end-line="2" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/containers/FilterBar/FilterBar.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="294">
          <caret line="13" column="38" selection-start-line="13" selection-start-column="38" selection-end-line="13" selection-end-column="38" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/reducers/index.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="161">
          <caret line="7" column="36" lean-forward="true" selection-start-line="7" selection-start-column="36" selection-end-line="7" selection-end-column="36" />
        </state>
      </provider>
    </entry>
    <entry file="jar://$APPLICATION_HOME_DIR$/lib/webstorm.jar!/resources/html5-schema/html5/phrase.rnc">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="213">
          <caret line="345" column="16" selection-start-line="345" selection-start-column="16" selection-end-line="345" selection-end-column="16" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/SlideDots/SlideDots.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="299">
          <caret line="14" selection-start-line="14" selection-end-line="14" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/public/index.html">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="299">
          <caret line="13" column="8" selection-start-line="13" selection-start-column="8" selection-end-line="13" selection-end-column="8" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/data/getData.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="1334">
          <caret line="58" column="7" selection-start-line="58" selection-start-column="7" selection-end-line="58" selection-end-column="7" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/index.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="69">
          <caret line="7" selection-start-line="7" selection-end-line="7" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/reducers/orderByPrice.filter.reducer.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="207">
          <caret line="9" column="22" selection-start-line="9" selection-start-column="22" selection-end-line="9" selection-end-column="22" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/App.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="253">
          <caret line="11" column="64" lean-forward="true" selection-start-line="11" selection-start-column="64" selection-end-line="11" selection-end-column="64" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pipes/orderByFilter.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="115">
          <caret line="5" column="21" selection-start-line="5" selection-start-column="21" selection-end-line="5" selection-end-column="21" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/Footer/Footer.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="138">
          <caret line="6" column="81" selection-start-line="6" selection-start-column="81" selection-end-line="6" selection-end-column="81" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/reducers/brand.filter.reducer.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="46">
          <caret line="2" column="60" selection-start-line="2" selection-start-column="60" selection-end-line="2" selection-end-column="60" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/ProductDetail/ProductDetail.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="506">
          <caret line="26" column="6" selection-start-line="26" selection-start-column="6" selection-end-line="26" selection-end-column="6" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/actions/index.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="23">
          <caret line="1" column="67" selection-start-line="1" selection-start-column="67" selection-end-line="1" selection-end-column="67" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/Pagination/Pagination.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="451">
          <caret line="34" selection-start-line="34" selection-end-line="34" />
          <folding>
            <element signature="e#0#39#0" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pages/Home/Home.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="207">
          <caret line="12" column="22" selection-start-line="12" selection-start-column="22" selection-end-line="12" selection-end-column="22" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/Pagination/Pagination.scss">
      <provider selected="true" editor-type-id="text-editor" />
    </entry>
    <entry file="file://$PROJECT_DIR$/src/reducers/pagination.reducer.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="575">
          <caret line="25" column="19" selection-start-line="25" selection-start-column="19" selection-end-line="28" selection-end-column="14" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pipes/paginationFilter.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="138">
          <caret line="6" column="5" selection-start-line="6" selection-start-column="5" selection-end-line="6" selection-end-column="5" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/App.scss">
      <provider selected="true" editor-type-id="text-editor" />
    </entry>
    <entry file="file://$PROJECT_DIR$/src/index.scss">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="161">
          <caret line="7" selection-start-line="7" selection-end-line="18" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pages/ProductDetail/ProductDetail.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="253">
          <caret line="14" column="62" selection-start-line="14" selection-start-column="62" selection-end-line="14" selection-end-column="62" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/ProductSlider/ProductSlider.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="1058">
          <caret line="48" column="46" selection-start-line="48" selection-start-column="46" selection-end-line="48" selection-end-column="46" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/ProductSlider/ProductSlider.scss">
      <provider selected="true" editor-type-id="text-editor">
        <state>
          <caret selection-end-line="26" selection-end-column="1" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/reducers/shop.reducer.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="1334">
          <caret line="64" column="60" selection-start-line="64" selection-start-column="60" selection-end-line="64" selection-end-column="60" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/pages/ShopingCart/ShoppingCart.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="414">
          <caret line="21" column="81" selection-start-line="21" selection-start-column="81" selection-end-line="21" selection-end-column="81" />
          <folding>
            <element signature="e#0#26#0" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/OrderFilter/OrderFilter.scss">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="-498">
          <caret selection-end-line="53" selection-end-column="1" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/Header/Header.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="69">
          <caret line="5" selection-start-line="5" selection-end-line="5" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/CartItem/CartItem.scss">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="742">
          <caret line="82" selection-start-line="82" selection-end-line="82" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/BrandFilter/BrandFilter.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="575">
          <caret line="29" column="62" selection-start-line="29" selection-start-column="62" selection-end-line="29" selection-end-column="62" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/BrandFilter/BrandFilter.scss">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="1311">
          <caret line="57" column="1" selection-start-line="57" selection-start-column="1" selection-end-line="57" selection-end-column="1" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/OrderFilter/OrderFilter.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="1173">
          <caret line="54" column="60" selection-start-line="54" selection-start-column="60" selection-end-line="54" selection-end-column="60" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/data/phones.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="69">
          <caret line="3" column="15" selection-start-line="3" selection-start-column="15" selection-end-line="3" selection-end-column="15" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/Product/Product.scss">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="1610">
          <caret line="70" column="1" selection-start-line="70" selection-start-column="1" selection-end-line="70" selection-end-column="1" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/containers/ProductList/ProductList.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="1449">
          <caret line="71" column="88" selection-start-line="71" selection-start-column="88" selection-end-line="71" selection-end-column="88" />
          <folding>
            <element signature="e#0#39#0" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/LayoutMode/LayoutMode.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="322">
          <caret line="15" column="7" selection-start-line="15" selection-start-column="7" selection-end-line="15" selection-end-column="7" />
          <folding>
            <element signature="e#0#26#0" expanded="true" />
          </folding>
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/CartItem/CartItem.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="204">
          <caret line="66" column="46" selection-start-line="66" selection-start-column="46" selection-end-line="66" selection-end-column="46" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/src/components/Product/Product.js">
      <provider selected="true" editor-type-id="text-editor">
        <state relative-caret-position="-776">
          <caret line="31" column="43" selection-start-line="31" selection-start-column="43" selection-end-line="31" selection-end-column="43" />
        </state>
      </provider>
    </entry>
    <entry file="file://$PROJECT_DIR$/package.json">
      <provider selected="true" editor-type-id="text-editor" />
    </entry>
  </component>
</project>

================================================
FILE: README.md
================================================
# Here is the live demo <a href="http://numberless-leg.surge.sh" style="font-size: 40px">CLICK TO SEE DEMO</a>

![alt-text](https://github.com/TheCodersDream/React-Ecommerce-App-with-Redux/blob/master/ecm1-1.png)
![alt-text](https://github.com/TheCodersDream/React-Ecommerce-App-with-Redux/blob/master/ecm2-2.png)
![alt-text](https://github.com/TheCodersDream/React-Ecommerce-App-with-Redux/blob/master/ecm3.png)
![alt-text](https://github.com/TheCodersDream/React-Ecommerce-App-with-Redux/blob/master/ecm4.png)
![alt-text](https://github.com/TheCodersDream/React-Ecommerce-App-with-Redux/blob/master/ecm5.png)


This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

## Available Scripts

In the project directory, you can run:

### `npm start`

Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.<br>
You will also see any lint errors in the console.

### `npm test`

Launches the test runner in the interactive watch mode.<br>
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.

### `npm run build`

Builds the app for production to the `build` folder.<br>
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.

### `npm run eject`

**Note: this is a one-way operation. Once you `eject`, you can’t go back!**

If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.

You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.

## Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).

### Code Splitting

This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting

### Analyzing the Bundle Size

This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size

### Making a Progressive Web App

This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app

### Advanced Configuration

This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration

### Deployment

This section has moved here: https://facebook.github.io/create-react-app/docs/deployment

### `npm run build` fails to minify

This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify


================================================
FILE: package.json
================================================
{
  "name": "ecommerce",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "bootstrap": "^4.3.1",
    "node-sass": "^4.11.0",
    "react": "^16.8.3",
    "react-dom": "^16.8.3",
    "react-medium-image-zoom": "^3.0.15",
    "react-redux": "^6.0.1",
    "react-router-dom": "^4.3.1",
    "react-scripts": "2.1.5",
    "redux": "^4.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}


================================================
FILE: public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script src="https://use.fontawesome.com/c560c025cf.js"></script>
  </body>
</html>


================================================
FILE: public/manifest.json
================================================
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}


================================================
FILE: src/App.js
================================================
import React, { Component } from 'react';
import {Provider} from 'react-redux';
import {createStore } from 'redux';
import rootReducer from './reducers';

import {BrowserRouter, Switch, Route, Redirect} from 'react-router-dom';

import './App.scss';
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import Footer from "./components/Footer/Footer";
import ProductDetail from "./pages/ProductDetail/ProductDetail";
import ShoppingCart from "./pages/ShopingCart/ShoppingCart";



export const  store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

class App extends Component {
  render() {
    return (
        <Provider store={store}>
            <BrowserRouter>
            <React.Fragment>
                <Header/>
                <Switch>
                    <Route exact path={'/'} render={() => {
                        return <Redirect to={'/products'}/>
                    }}/>
                    <Route exact path={'/products'} component={Home}/>
                    <Route exact path={'/products/:id'} component={ProductDetail}/>
                    <Route exact patr={'/cart'} component={ShoppingCart}/>
                </Switch>
                <Footer/>
            </React.Fragment>
            </BrowserRouter>
        </Provider>
    );
  }
}

export default App;


================================================
FILE: src/App.scss
================================================


================================================
FILE: src/App.test.js
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
  ReactDOM.unmountComponentAtNode(div);
});


================================================
FILE: src/actions/index.js
================================================
export const ADD_PRODUCT_TO_CART = 'ADD_PRODUCT_TO_CART';
export const REMOVE_PRODUCT_FROM_CART = 'REMOVE_PRODUCT_FROM_CART';
export const INCREMENT_CART_ITEM_QUANTITY = 'INCREMENT_CART_ITEM_QUANTITY';
export const DECREMENT_CART_ITEM_QUANTITY = 'DECREMENT_CART_ITEM_QUANTITY';

export const addProductToCart = product => {
    return {
        type: ADD_PRODUCT_TO_CART,
        payload: product
    }
};

export const removeProductToCart = productId => {
    return {
        type: REMOVE_PRODUCT_FROM_CART,
        payload: productId
    }
};

export const incrementCartQuantity = productId => {
    return{
        type: INCREMENT_CART_ITEM_QUANTITY,
        payload: productId
    }
};

export const decrementCartQuantity = productId => {
  return {
      type: DECREMENT_CART_ITEM_QUANTITY,
      payload: productId
  }
};


export const ADD_BRAND_TO_FILTER = 'ADD_BRAND_TO_FILTER';
export const REMOVE_BRAND_FROM_FILTER = 'REMOVE_BRAND_FROM_FILTER';

export const addBrandToFilter = brand => {
    return {
        type: ADD_BRAND_TO_FILTER,
        brand
    }
};


export const removeBrandFromFilter = brand => {
    return  {
        type: REMOVE_BRAND_FROM_FILTER,
        brand
    }
};

export const ORDER_BY_ASC = 'ORDER_BY_ASC';
export const ORDER_BY_DESC = 'ORDER_BY_DESC';
export const CLEAR_ORDER_BY_PRICE = 'CLEAR_ORDER_BY_PRICE';

export const orderByAsc = () => {
    return {
        type: ORDER_BY_ASC
    }
};

export const orderByDesc =  () => {
    return {
        type: ORDER_BY_DESC
    }
};

export const clearOrderBy = () => {
    return {
        type: CLEAR_ORDER_BY_PRICE
    }
};


export const PREV_PAGE = 'PREV_PAGE';
export const NEXT_PAGE = 'NEXT_PAGE';
export const GO_PAGE = 'GO_PAGE';
export const COUNT_ITEM = 'COUNT_ITEM';


export const nextPage = () => {
    return {
        type: NEXT_PAGE
    }
};

export const prevPage = () => {
    return {
        type: PREV_PAGE
    }
};

export const goPage = (n) => {
    return {
        type: GO_PAGE,
        currentPage: n
    }
};

export const countItem = (n) => {
    return {
        type: COUNT_ITEM,
        totalItemsCount: n
    }
}


================================================
FILE: src/components/BrandFilter/BrandFilter.js
================================================
import React, {Component} from 'react';
import {connect} from 'react-redux';
import './BrandFilter.scss';
import {brands} from "../../data/brands";
import {addBrandToFilter, removeBrandFromFilter} from "../../actions";


const BrandFilter = (props) => {

    const {dispatch, brandItemsCount} = props;
    const handleSelectBox = (e) => {
        const name = e.target.name;
        const value = e.target.checked;

        if(e.target.checked) {
            dispatch(addBrandToFilter(name));
        } else {
            dispatch(removeBrandFromFilter(name));
        }
    };


        return (
            <div className="card mb-3">
                <div className="card-header">
                    <h3>Brands</h3>
                </div>
                <ul className="list-group flex-row flex-wrap">
                    {brands.map(brand => (
                        <li className="list-group-item flex-50">
                            <label className="custom-checkbox text-capitalize"> {brand} ({brandItemsCount[brand]})
                                <input type="checkbox"
                                       name={brand}
                                       className="custom-checkbox__input" onInput={handleSelectBox}/>
                                <span className="custom-checkbox__span"></span>
                            </label>
                        </li>
                    ))}
                </ul>
            </div>
        );

};

const mapStateToProps = (state) => {

    const brandItemsCount = {};

    state.shop.products.forEach(p => {
        brandItemsCount[p.brand] = brandItemsCount[p.brand] + 1 || 1;
    });


    return {
        brandItemsCount
    }

};

export default connect(mapStateToProps)(BrandFilter);

================================================
FILE: src/components/BrandFilter/BrandFilter.scss
================================================
.custom-checkbox {
  display: block;
  position: relative;
  padding-left: 2rem;
  cursor: pointer;
  user-select: none;

  &__input {
    position: absolute;
    opacity: 0;
    height: 0;
    width: 0;


  }

  &__span {
    position: absolute;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    height: 1.2rem;
    width: 1.2rem;
    background-color: white;
    border: 2px solid gray;

    &::after {
      content: "";
      opacity: 0;
      position: absolute;
      top: 50%;
      left: 50%;
      width: .6rem;
      height: .6rem;
      background-color: dodgerblue;
      transform: translate(-50%, -50%);
    }
  }

  &:hover &__span {
    background-color: #eeeeee;
  }

  &__input:checked + &__span::after {
    opacity: 1;
  }
}

.flex-50 {
  flex: 0 0 100%;
}

@media only screen and (max-width: 768px) {

  .flex-50 {
    flex: 0 0 50%;
  }
}

================================================
FILE: src/components/CartItem/CartItem.js
================================================
import React, {useState} from 'react';
import {connect} from 'react-redux';
import {shortenTitle} from "../../pipes/shortenTitle";
import {formatMoney} from "../../pipes/priceFormatter";
import './CartItem.scss';
import {addProductToCart, decrementCartQuantity, incrementCartQuantity, removeProductToCart} from "../../actions";

const CartItem = (
    {
        title,
        price,
        description,
        quantity,
        id,
        img,
        dispatch
    }
) => {

    console.log(id);
    const [itemQuantity, setItemQuantity] = useState(quantity);
    const removeItem = () => {
        dispatch(removeProductToCart(id));
    };

    const handleQuantityChange = (e) => {
      /*  const value = e.target.value;
        console.log(value)

        if(value > 0 && value <= 10) {
            setItemQuantity(value);
            dispatch(addProductToCart(id));
        } */
    };

    const incrementOrDecrement = (e, type) => {
        const value = itemQuantity;
        console.log(type, value);

        if(type === 'inc' && value < 10) {
            setItemQuantity(itemQuantity + 1);
            dispatch(incrementCartQuantity(id));
        }


        if(type === 'desc' && value > 1) {
            setItemQuantity(itemQuantity - 1);
            dispatch(decrementCartQuantity(id));
        }

    };


    return (
        <div className="row align-items-center mb-3">
            <div className="col-12 col-sm-12 col-md-2 text-center">
                <img className="img-responsive" src={img} style={{height: '60%', width: '60%'}} alt={description}
                      />
            </div>
            <div className="col-12 text-sm-center col-sm-12 text-md-left col-md-6">
                <h4 className="product-name"><strong>{shortenTitle(title)}</strong></h4>
                <h4>
                    <small className="product-description">{description}</small>
                </h4>
            </div>
            <div className="col-12 col-sm-12 text-sm-center col-md-4 text-md-right row product-quantity-container align-items-center">
                <div className="col-6 col-sm-6 col-md-6 text-md-right" style={{paddingTop: '5px'}}>
                    <h6><strong>{formatMoney(price)}$ <span className="text-muted">x</span></strong></h6>
                </div>
                <div className="col-4 col-sm-4 col-md-4">
                    <div className="quantity">
                        <input
                            onClick={(e) => {incrementOrDecrement(e, 'inc')}}
                            type="button" value="+" className="plus" />
                            <input
                                onChange={handleQuantityChange}
                                type="number" step="1" max="10" min="1" value={itemQuantity} title="Qty"
                                   className="qty"
                                   size="4" />
                                <input
                                    onClick={(e) => {incrementOrDecrement(e, 'desc')}}
                                    type="button" value="-" className="minus" />
                    </div>
                </div>
                <div className="col-2 col-sm-2 col-md-2 text-right">
                    <button
                        onClick={removeItem}
                        type="button" className="btn btn-outline-danger btn-xs">
                        <i className="fa fa-trash"  />
                    </button>
                </div>
            </div>
        </div>
    );
};

export default connect()(CartItem);


================================================
FILE: src/components/CartItem/CartItem.scss
================================================


.quantity {
  float: left;
  margin-right: 15px;
  background-color: #eee;
  position: relative;
  width: 80px;
  overflow: hidden
}

.quantity input {
  margin: 0;
  text-align: center;
  width: 15px;
  height: 15px;
  padding: 0;
  float: right;
  color: #000;
  font-size: 20px;
  border: 0;
  outline: 0;
  background-color: #F6F6F6
}

.quantity input.qty {
  position: relative;
  border: 0;
  width: 100%;
  height: 40px;
  padding: 10px 25px 10px 10px;
  text-align: center;
  font-weight: 400;
  font-size: 15px;
  border-radius: 0;
  background-clip: padding-box
}

.quantity .minus, .quantity .plus {
  line-height: 0;
  background-clip: padding-box;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
  -webkit-background-size: 6px 30px;
  -moz-background-size: 6px 30px;
  color: #bbb;
  font-size: 20px;
  position: absolute;
  height: 50%;
  border: 0;
  right: 0;
  padding: 0;
  width: 25px;
  z-index: 3
}

.quantity .minus:hover, .quantity .plus:hover {
  background-color: #dad8da
}

.quantity .minus {
  bottom: 0
}
.shopping-cart {
  margin-top: 20px;
}

@media only screen and (max-width: 768px) {
  .product-name {
    font-size: 1rem;
    margin-top: .5rem;
  }

  .product-description {
    font-size: 1rem;
  }

  .product-quantity-container {
    margin-top: .5rem;
  }
}


================================================
FILE: src/components/Footer/Footer.js
================================================
import React from 'react';

const Footer = () => {
    return (
        <footer className="py-5 bg-dark">
            <div className="container">
                <p className="m-0 text-center text-white">Copyright © Emre Baskan 2019</p>
            </div>
        </footer>
    );
};

export default Footer;

================================================
FILE: src/components/Header/Header.js
================================================
import React from 'react';
import {connect} from 'react-redux';
import {NavLink} from 'react-router-dom';

const Header = ({cartLength}) => {

    return (
        <nav className="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
            <div className="container">
                <NavLink className="navbar-brand" to="/">Ecommerce</NavLink>
                <div>
                    <ul className="navbar-nav ml-auto">
                        <li className="nav-item">
                            <NavLink className="nav-link" to={"/cart"}><i className="fa fa-shopping-cart mr-2"
                                                                          aria-hidden="true" />Cart {cartLength ? `(${cartLength})`: ''}</NavLink>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    );
};


const mapStateToProps = (state) => {
  return {
      cartLength: state.shop.cart.length
  }
};

export default connect(mapStateToProps, null)(Header);


/*
*                         <li className="nav-item active">
                            <a className="nav-link" href="#">Home
                                <span className="sr-only">(current)</span>
                            </a>
                        </li>
                        <li className="nav-item">
                            <a className="nav-link" href="#">About</a>
                        </li>
                        <li className="nav-item">
                            <a className="nav-link" href="#">Services</a>
                        </li>
                        <li className="nav-item">
                            <a className="nav-link" href="#">Contact</a>
                        </li>
* */

================================================
FILE: src/components/LayoutMode/LayoutMode.js
================================================
import React from 'react';
import './LayoutMode.scss';

const LayoutMode = (
    {
        len,
        click,
        isActive
    }
) => {

    let items = [];

    let classess = 'layout-mode__item';

    if(isActive) {
        classess += ' layout-mode__item--active'
    }

    for(let i = 0; i < len; i ++) {
        items.push(<div  className={classess} />);
    };


    return (
        <div className="layout-mode" onClick={() => {click(len)}}>
            {items}
        </div>
    );
};

export default LayoutMode;


================================================
FILE: src/components/LayoutMode/LayoutMode.scss
================================================
.layout-mode {

  display: flex;
  flex-direction: row;
  padding: .3rem;
  border: 2px solid gray;
  cursor: pointer;

  &__item {
    width: .7rem;
    height: .7rem;
    background-color: gray;

    &--active {
      background-color: dodgerblue;
    }

  }

  &__item:not(:last-child) {
    margin-right: .3rem;
  }

  &:not(:last-child) {
    margin-right: .8rem;
  }




  &:hover {
    border: 2px solid #646464;
  }

  &--active {
    border: 2px solid dodgerblue;
  }
}


================================================
FILE: src/components/OrderFilter/OrderFilter.js
================================================
import React, {useState} from 'react';
import {connect} from 'react-redux';
import './OrderFilter.scss';
import {clearOrderBy, ORDER_BY_ASC, ORDER_BY_DESC, orderByAsc, orderByDesc} from "../../actions";

const OrderFilter = ({dispatch}) => {

    let removeSelected;
    const [selected, setSelected] = useState('');

    const handleRadioChange = (e) => {
        const value = e.target.value;
        setSelected(value);
        if(value === ORDER_BY_ASC) {
            dispatch(orderByAsc());
        } else {
            dispatch(orderByDesc());
        }
    };

    const removeFilter = (e) => {

        const buttons = document.getElementsByName('orderByPrice');

        buttons.forEach(el => {
            el.checked = false;
        });

        dispatch(clearOrderBy());
        setSelected('');
    };

    if(selected) {
        removeSelected  =  <span onClick={removeFilter} className="text-remove-selected text-right">Remove filter</span>
    }



    return (
            <div className="card">
                <div className="card-header">
                    <h3>Price {removeSelected} </h3>
                </div>
                <ul className="list-group flex-row  flex-wrap" >
                    <li className="list-group-item flex-fill">
                        <label className="custom-radio-btn"> Low to high
                            <input
                                    value={ORDER_BY_ASC}
                                    type="radio"
                                    onChange={handleRadioChange}
                                   name="orderByPrice" className="custom-radio-btn__input"/>
                            <span className="custom-radio-btn__span"></span>
                        </label>
                    </li>
                    <li className="list-group-item flex-fill">
                        <label className="custom-radio-btn"> High to low
                            <input
                                value={ORDER_BY_DESC}
                                onChange={handleRadioChange}
                                type="radio" name="orderByPrice" className="custom-radio-btn__input"/>
                            <span className="custom-radio-btn__span"></span>
                        </label>
                    </li>
                </ul>
            </div>
    );
};

export default connect()(OrderFilter);

================================================
FILE: src/components/OrderFilter/OrderFilter.scss
================================================
.custom-radio-btn {
  display: block;
  position: relative;
  cursor: pointer;
  padding-left: 2rem;
  user-select: none;

  &__input {
    position: absolute;
    opacity: 0;
    cursor: pointer;
  }

  &__span {
    position: absolute;
    top: 50%;
    left: 0;
    height: 1.3rem;
    width: 1.3rem;
    background-color: #eeeeee;
    border-radius: 12px;
    transform: translateY(-50%);

    &::after {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: .7rem;
      height: .7rem;
      border-radius: 50%;
      background-color: dodgerblue;
      content: "";
      display: none;
    }
  }

  &__input:checked ~ &__span::after {
    display: block;
  }

  &:hover &__span {
    background-color: #dfdfdf;
  }


}

.text-remove-selected {
  font-size: 1rem;
  font-weight: normal;
  cursor: pointer;
  padding-left: 2rem;
}

================================================
FILE: src/components/Pagination/Pagination.js
================================================
import React, {Component} from 'react';
import {connect} from "react-redux";
import {goPage, nextPage, prevPage} from "../../actions";

class Pagination extends Component {


    onPage(n){
        this.props.onGoPage(n);
    }

    isOnLastPage(){
        // console.log(this.props.perPage * this.props.currentPage, this.props.totalItemsCount);
        return this.props.perPage * this.props.currentPage >= this.props.totalItemsCount;
    }

    totalPages() {
        return Math.ceil(this.props.totalItemsCount / this.props.perPage) || 0;
    }

    getMin(){
        return ((this.props.perPage * this.props.currentPage) - this.props.perPage) + 1;
    }

    getMax() {
        let max = this.props.perPage * this.props.currentPage;
        if (max > this.props.totalItemsCount) {
            max = this.props.totalItemsCount;
        }
        return max;
    }
    onPrev = () => {
        this.props.onPrevPage();
    }

    onNext = () =>  {
        this.props.onNextPage();
    }


    getPages = () => {
        const c = Math.ceil(this.props.totalItemsCount / this.props.perPage);
        const p = this.props.currentPage || 1;
        const pagesToShow = this.props.pagesToShow || 9;
        const pages = [];
        pages.push(p);
        const times = pagesToShow - 1;
        for (let i = 0; i < times; i++) {
            if (pages.length < pagesToShow) {
                if (Math.min.apply(null, pages) > 1) {
                    pages.push(Math.min.apply(null, pages) - 1);
                }
            }
            if (pages.length < pagesToShow) {
                if (Math.max.apply(null, pages) < c) {
                    pages.push(Math.max.apply(null, pages) + 1);
                }
            }
        }
        pages.sort((a, b) => a - b);
        return pages;
    }




    render() {

        console.log(this.props);

        const pages =this.getPages().map(pageNum => {

            let buttonClass = 'page-item';

            if(pageNum === this.props.currentPage) {
                buttonClass += ' active';
            }

            return (<li className={buttonClass} onClick={() => {this.onPage(pageNum)}}><button className="page-link" >{pageNum}</button></li>);
        });

        let prevButtonClass = 'page-item';

        if (this.props.currentPage === 1) {
            prevButtonClass += ' disabled';
        }

        const prevButton = (<li className={prevButtonClass}>
            <button
                className="page-link" onClick={this.onPrev} tabIndex="-1">Previous</button>
        </li>);

        let nextButtonClass = 'page-item';

        if(this.isOnLastPage()) {
            nextButtonClass += ' disabled';
        }

        const nextButton = (
            <li className={nextButtonClass}>
                <button
                    disabled={this.isOnLastPage()}
                    className="page-link" onClick={this.onNext}>Next</button>
            </li>
        );



        return (
            <nav aria-label="...">
                <ul className="pagination">
                    {prevButton}
                    {pages}
                    {nextButton}
                </ul>
            </nav>
        );
    }
}


const mapStateToProps = (state) => {
    return {
        ...state.pagination,
        totalItemsCount: state.shop.products.length,
    }
};

export default Pagination;


================================================
FILE: src/components/Pagination/Pagination.scss
================================================


================================================
FILE: src/components/Product/Product.js
================================================
import React, {useState} from 'react';
import {connect} from 'react-redux';
import {Link} from 'react-router-dom';
import {formatMoney} from "../../pipes/priceFormatter";
import {cumulativeOffSet} from "../../utilities/cumulativeOffset";

import './Product.scss';
import SlideDots from "../SlideDots/SlideDots";
import {addProductToCart} from "../../actions";


const Product = (props) => {

    const {
        title,
        price,
        images,
        description,
        id,
    } = props.product;

    const imageRef = React.createRef();
    const [img, setImg] = useState(images[0]);
    const [aItem, setAItem] = useState(0);


    const handleImageChange = (e) => {

        let  clientX;

        if(e.type === 'touchmove') {
            clientX = e.touches[0].clientX;
        } else {
            clientX = e.clientX;
        }

        const currentX = clientX - cumulativeOffSet(imageRef.current).left;

        // console.dir(imageRef.current);

        const part = imageRef.current.clientWidth / images.length;
       // console.log(Math.ceil(currentX / part) - 1);

        let imgIndex = Math.ceil(currentX / part) - 1;
        if (imgIndex < 0) {
            imgIndex = 0;
        }

        if (imgIndex >= images.length) {
            imgIndex = images.length - 1;
        }
        setAItem(imgIndex);
        setImg(images[imgIndex]);
    };

    const handleMouseOut = (e) => {
        setImg(images[0]);
        setAItem(0);
    };

    const changeImage = (i) => {
        setImg(images[i]);
        setAItem(i);
    }

    return (
        <div className="card h-100 product">
            <Link to={`/products/${id}`} className="product__link"><img
                onMouseMove={handleImageChange}
                onMouseOut={handleMouseOut}
                onTouchMove={handleImageChange}
                onTouchEnd={handleMouseOut}
                className="card-img-top product__img" src={img} alt={title} ref={imageRef}/>
                <SlideDots len={images.length} activeItem={aItem} changeItem={changeImage}/>
            </Link>
            <div className="card-body product__text">
                <h4 className="card-title product__title">
                    <Link to={`/products/${id}`}>{title}</Link>
                </h4>
                <h5 className="product__price">${formatMoney(price)}</h5>
                <p className="card-text product__description">{description}</p>
                <button
                    onClick={() => {
                        props.dispatch(addProductToCart({...props.product}))
                    }}
                    className="btn btn-info product__add-to-cart">Add to cart
                </button>
            </div>
        </div>
    );
};

export default connect()(Product);



================================================
FILE: src/components/Product/Product.scss
================================================
.product {
  padding-bottom: 2rem;
  &__img {
    width: 100%;
    height: 100%;
  }

  &__text {
    flex: 0 0 40%;
  }

  &__link {
    flex: 0 0 60%;
    height: 60%;
    padding: 1rem;
    position: relative;
  }

  &__title {
    font-size: .8rem;
  }

  &__price {

  }

  &__description {
    font-size: 0.7rem;
  }

  &:hover {
    box-shadow: 0 1rem 2rem rgba(0,0,0, .2);
  }

  &__add-to-cart {
    position: absolute;
    bottom: .8rem;
    width: 60%;
    left: 50%;
    opacity: 0;
    visibility: hidden;
    transform: translateX(-50%);
    transition: all .2s;
    padding: 3px 12px;

  }

  &:hover &__add-to-cart {
    visibility: visible;
    opacity: 1;
  }

  &:hover .owl-dots {
    display: inline-block;
  }

}

@media only screen and (max-width: 768px) {
  .product {
    height: auto !important;
    &__add-to-cart {
      visibility: visible;
      opacity: 1;
    }

    & .owl-dots {
      display: inline-block;
    }
  }
}

================================================
FILE: src/components/ProductDetail/ProductDetail.js
================================================
import React from 'react';
import {connect} from 'react-redux';
import {formatMoney} from "../../pipes/priceFormatter";
import {addProductToCart} from "../../actions";

const ProductDetail = (props) => {

    const {
        title,
        images,
        brand,
        price,
        cpu,
        camera,
        size,
        weight,
        display,
        battery,
        memory,
        description,
        id
    } = props.product;


    const onCart = () => {
        props.dispatch(addProductToCart(props.product));
    };

    return (
        <aside className="col-sm-7">
            <article className="card-body p-5">
                <h3 className="title mb-3">{title}</h3>

                <p className="price-detail-wrap">
	<span className="price h3 text-warning">
		<span className="currency">$</span><span className="num">{formatMoney(price)}</span>
	</span>
                </p>
                <dl className="item-property">
                    <dt>Description</dt>
                    <dd><p className="text-capitalize">{description}</p></dd>
                </dl>
                <dl className="param param-feature">
                    <dt>Brand</dt>
                    <dd className="text-capitalize">{brand}</dd>
                </dl>
                <dl className="param param-feature">
                    <dt>Size</dt>
                    <dd>{size}</dd>
                </dl>
                <dl className="param param-feature">
                    <dt>Camera</dt>
                    <dd>{camera}</dd>
                </dl>
                <dl className="param param-feature">
                    <dt>CPU</dt>
                    <dd>{cpu}</dd>
                </dl>
                <dl className="param param-feature">
                    <dt>Memory</dt>
                    <dd>{memory}</dd>
                </dl>
                <dl className="param param-feature">
                    <dt>Display</dt>
                    <dd>{display}</dd>
                </dl>
                <dl className="param param-feature">
                    <dt>Battery</dt>
                    <dd>{battery}</dd>
                </dl>
                <hr/>
                <hr/>
                <button
                    onClick={onCart}
                    className="btn btn-lg btn-outline-primary text-uppercase"><i
                    className="fa fa-shopping-cart"/> Add to cart
                </button>
            </article>
        </aside>
    );
};

export default connect()(ProductDetail);


================================================
FILE: src/components/ProductSlider/ProductSlider.js
================================================
import React, {useState} from 'react';
import {cumulativeOffSet} from "../../utilities/cumulativeOffset"
import './ProductSlider.scss';

const ProductSlider = (
    {
        images
    }
) => {
    const imageRef = React.createRef();
    const [img, setImg] = useState(images[0]);
    const [aItem, setAItem] = useState(0);


    const handleImageChange = (e) => {
        const currentX = e.clientX - cumulativeOffSet(imageRef.current).left;

        console.dir(imageRef.current);

        const part = imageRef.current.clientWidth / images.length;
        console.log(Math.ceil(currentX / part) - 1);

        let imgIndex = Math.ceil(currentX / part) - 1;
        if (imgIndex < 0) {
            imgIndex = 0;
        }

        if (imgIndex >= images.length) {
            imgIndex = images.length - 1;
        }
        setAItem(imgIndex);
        setImg(images[imgIndex]);
    };

    const handleMouseOut = (e) => {
        setImg(images[0]);
        setAItem(0);
    };

    const changeImage = (i) => {
        setImg(images[i]);
        setAItem(i);
    }


    return (
        <aside className="col-sm-5 border-right">
            <article className="gallery-wrap">
                <div className="img-big-wrap">
                    <div style={{padding: '2rem'}}><a href="#"><img
                        ref={imageRef}
                        onMouseMove={handleImageChange}
                        onMouseOut={handleMouseOut}
                        src={img}
                        style={{width: '100%',
                                height: '100%'}}
                    /></a></div>
                </div>
                <div className="img-small-wrap">
                    {images.map((img , i ) => (
                        <div className="item-gallery" onClick={() => {changeImage(i)}}><img src={img}/></div>
                    ))}
                </div>
            </article>
        </aside>
    );
};

export default ProductSlider;

================================================
FILE: src/components/ProductSlider/ProductSlider.scss
================================================
.gallery-wrap .img-big-wrap img {
  height: 450px;
  width: auto;
  display: inline-block;
}



.gallery-wrap .img-small-wrap .item-gallery {
  width: 60px;
  height: 60px;
  border: 1px solid #ddd;
  margin: 7px 2px;
  display: inline-block;
  overflow: hidden;
}

.gallery-wrap .img-small-wrap {
  text-align: center;
}
.gallery-wrap .img-small-wrap img {
  max-width: 100%;
  max-height: 100%;
  object-fit: cover;
  border-radius: 4px;
  cursor: pointer;
}

================================================
FILE: src/components/SlideDots/SlideDots.js
================================================
import React from 'react';
import './SlideDots.scss';

const SlideDots = (
    {
        len,
        activeItem,
        changeItem
    }
) => {

    const dots = [];
    for(let i = 0; i < len; i++) {
        let dotClass = 'owl-dot';

        if(activeItem === i) {
            dotClass += ' active';
        }

        dots.push(<button
            onClick={() => {changeItem(i)}}
            role="button"
            className={dotClass}><span></span></button>)
    }

    return (
        <div className="owl-dots">
            {dots}
        </div>
    );
};

export default SlideDots;

================================================
FILE: src/components/SlideDots/SlideDots.scss
================================================
.owl-dots {
  display: none;
  position: absolute;
  bottom: -1rem;
  left: 0;

}

.owl-dots {
  width: 100%;
  text-align: center;
}

.owl-dots .active.owl-dot {
  background-color: #f28b00;
  border-color: #f28b00;
}

.owl-dots .owl-dot {
  display: inline-block;
  zoom: 1;
  margin: 8px 4px;
  border-radius: 10px;
  -moz-border-radius: 10px;
  -o-border-radius: 10px;
  -webkit-border-radius: 10px;
  -ms-webkit-radius: 10px;
  zoom: 1;
  background-color: #fff;
  padding: 3px;
  border: solid 1px #e9e9e9;
  cursor: pointer;
}

================================================
FILE: src/containers/FilterBar/FilterBar.js
================================================
import React, {Component} from 'react';
import BrandFilter from "../../components/BrandFilter/BrandFilter";
import OrderFilter from "../../components/OrderFilter/OrderFilter";

class FilterBar extends Component {
    render() {
        return (
            <div className="col-lg-3">
                <div className="row">
                    <div className="col-12">
                        <BrandFilter/>
                    </div>
                    <div className="col-12">
                        <OrderFilter/>
                    </div>
                </div>
            </div>
        );
    }
}

export default FilterBar;

================================================
FILE: src/containers/ProductList/ProductList.js
================================================
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Product from "../../components/Product/Product";

import {brandFilter} from "../../pipes/brandFilter";
import {orderByFilter} from "../../pipes/orderByFilter";
import LayoutMode from "../../components/LayoutMode/LayoutMode";
import {paginationPipe} from "../../pipes/paginationFilter";
import Pagination from "../../components/Pagination/Pagination";

class ProductList extends Component {

    state = {
        colValue : 'col-lg-4',
        perPage: 12,
        currentPage: 1,
        pagesToShow: 3,
        gridValue: 3
    };

    changeLayout = (n) => {
        this.setState({gridValue: n});

        let realGridValue;

        if(n === 4) {
            realGridValue = 3
        } else {
            realGridValue = 4;
        }

      this.setState({
          colValue: `col-lg-${realGridValue}`
      });
    };


    onPrev = () => {
        const updatedState = {...this.state};
        updatedState.currentPage = this.state.currentPage - 1;
        this.setState(updatedState);
    };


    onNext = () => {
        this.setState({
            ...this.state,
            currentPage: this.state.currentPage + 1
        });
    };

    goPage = (n) => {
        this.setState({
            ...this.state,
            currentPage: n
        });
    };


    render() {

        let isActive = this.state.colValue[this.state.colValue.length -1];

        return (
            <div className="col-lg-9">
                <div className="row mb-3">
                    <div className="col-12 d-none d-lg-block d-xl-block">
                        <div className="card ">
                            <div className="card-header d-flex justify-content-end">
                                <span className="mr-3">Change Layout: </span>
                                <LayoutMode len={3} isActive={this.state.gridValue === 3} click={this.changeLayout} />
                                <LayoutMode len={4} isActive={this.state.gridValue === 4}  click={this.changeLayout} />
                            </div>
                        </div>
                    </div>
                </div>
                <div className="row">
                    {paginationPipe(this.props.products, this.state).map(product =>{
                        let classes = `${this.state.colValue} col-md-6 mb-4`;
                        return (<div className={classes}>
                            <Product key={product.id} product={product} />
                        </div>)
                    })}
                </div>
                <div className="d-flex justify-content-end">
                    <Pagination
                        totalItemsCount={this.props.products.length}
                        currentPage={this.state.currentPage}
                        perPage={this.state.perPage}
                        pagesToShow={this.state.pagesToShow}
                        onGoPage={this.goPage}
                        onPrevPage={this.onPrev}
                        onNextPage={this.onNext}
                    />
                </div>
            </div>
        );
    }
}

const mapStateToProps = state => {
    const brands = state.brandFilter;
    const orderBy = state.orderBy;

    const filterByBrandArr = brandFilter(state.shop.products, brands);
    const filterByOrderArr = orderByFilter(filterByBrandArr, orderBy);


    return {products: filterByOrderArr }
};

export default connect(mapStateToProps, null)(ProductList);


================================================
FILE: src/containers/ProductList/ProductList.scss
================================================

$body-bg: #000;

@import '~bootstrap/scss/bootstrap.scss';

================================================
FILE: src/data/brands.js
================================================
export const brands = ["apple","huawei","meizu","samsung","vestel","xiaomi","asus"];

================================================
FILE: src/data/getData.js
================================================

var imagesMap = {};

var images = document.querySelectorAll('.product-image');

console.log(images);

images.forEach(img => {

    if(!imagesMap[img.title]) {
        imagesMap[img.title] = [];
        imagesMap[img.title].push(img.src);
    } else {
        imagesMap[img.title].push(img.src);
    }

});

for (let key in imagesMap) {

    if(imagesMap[key].length === 0) {
        delete imagesMap[key];
    }

    if(!imagesMap[key][0]) {
        imagesMap[key].splice(0,1);
    }


}

function getRandomArbitrary(min, max) {
    return Math.random() * (max - min) + min;
}

brand
var phones = Object.keys(imagesMap).reduce((acc, key , i) => {

    if(imagesMap[key].length !== 0) {
        var newPhone = {
            price: getRandomArbitrary(1500, 10000),
            cpu: "1.3GHz Apple A6",
            camera: "8mp (3264x2448)",
            size: "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
            weight: "132 grams (4.7 ounces) with battery",
            display: "4.0 326 pixel density",
            battery: "1480 mAh",
            memory: "16GB, 32GB and RAM 1 GB"
        };
        newPhone.title = key;
        newPhone.brand = key.split(' ')[0].toLowerCase();
        newPhone.category = 'phone';
        newPhone.images = imagesMap[key];

        acc.push(newPhone);
    }

    return acc;
}, []);

console.log(JSON.stringify(phones));

================================================
FILE: src/data/phones.js
================================================
export const phones = [{
    "title": "Apple iPhone 7 Plus 32 GB (Apple Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/18/280-413/9801258663986.jpg?v1", "https://productimages.hepsiburada.net/s/18/280-413/9801258696754.jpg?v1", "https://productimages.hepsiburada.net/s/18/280-413/9801258729522.jpg?v1", "https://productimages.hepsiburada.net/s/18/280-413/9801258762290.jpg?v1"],
    "brand": "apple",
    "price": 4241.499828399639,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 0,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Huawei Mate 20 Lite 64 GB (Huawei Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/21/280-413/9933217792050.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9933217628210.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9933217660978.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9933217693746.jpg?v1"],
    "brand": "huawei",
    "price": 1823.6625483451157,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 1,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Huawei P20 Lite 64 GB (Huawei Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/19/280-413/9826975907890.jpg?v1", "https://productimages.hepsiburada.net/s/19/280-413/9826975940658.jpg?v1", "https://productimages.hepsiburada.net/s/19/280-413/9826975973426.jpg?v1", "https://productimages.hepsiburada.net/s/19/280-413/9826976006194.jpg?v1"],
    "brand": "huawei",
    "price": 7429.467511354926,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 2,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Meizu 16TH 64 GB (Meizu Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/24/280-413/10094991409202.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10094991441970.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10094991474738.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10094991507506.jpg?v1"],
    "brand": "meizu",
    "price": 5664.265944453384,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 3,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Meizu X8 64 GB (Meizu Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/25/280-413/10108030091314.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10082391818290.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10082391851058.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10082391883826.jpg?v1"],
    "brand": "meizu",
    "price": 4596.99884783711,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 4,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy A7 2018 64 GB (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/22/280-413/9946187399218.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9946187431986.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9946187464754.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9946187497522.jpg?v1"],
    "brand": "samsung",
    "price": 4108.082941215698,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 5,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy J6 Plus 32 GB (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/22/280-413/9941129494578.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9941129527346.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9941129560114.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9941129592882.jpg?v1"],
    "brand": "samsung",
    "price": 4260.9529075338505,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 6,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Vestel Venus Z20 (Vestel Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/19/280-413/9841497047090.jpg?v1", "https://productimages.hepsiburada.net/s/19/280-413/9841497079858.jpg?v1", "https://productimages.hepsiburada.net/s/19/280-413/9841497112626.jpg?v1", "https://productimages.hepsiburada.net/s/19/280-413/9841497145394.jpg?v1"],
    "brand": "vestel",
    "price": 4730.962860489047,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 7,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Xiaomi Mi 8 Lite 128 GB (İthalatçı Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/22/280-413/9957349523506.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9957349556274.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9957349589042.jpg?v1", "https://productimages.hepsiburada.net/s/22/280-413/9957349621810.jpg?v1"],
    "brand": "xiaomi",
    "price": 5565.737301732921,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 8,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Xiaomi Mi 8 Lite 64 GB (İthalatçı Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/23/280-413/10051147202610.jpg?v1", "https://productimages.hepsiburada.net/s/23/280-413/10051147235378.jpg?v1", "https://productimages.hepsiburada.net/s/23/280-413/10051147268146.jpg?v1", "https://productimages.hepsiburada.net/s/23/280-413/10051147300914.jpg?v1"],
    "brand": "xiaomi",
    "price": 5830.067673371856,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 9,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Apple iPhone 7 32 GB (Apple Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/1/280-413/9502147641394.jpg?v1", "https://productimages.hepsiburada.net/s/1/280-413/9502147674162.jpg?v1", "https://productimages.hepsiburada.net/s/1/280-413/9502147706930.jpg?v1", "https://productimages.hepsiburada.net/s/1/280-413/9502147739698.jpg?v1"],
    "brand": "apple",
    "price": 1525.6236967422828,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 10,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy S10 Plus 128 GB (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/25/280-413/10107992703026.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107992735794.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107992768562.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107992801330.jpg?v1"],
    "brand": "samsung",
    "price": 3429.3471420603028,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 11,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy S10 128 GB (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/25/280-413/10107307425842.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107307458610.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107307491378.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107307524146.jpg?v1"],
    "brand": "samsung",
    "price": 1017.7877018963508,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 12,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy S10e 128 GB (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/25/280-413/10107307032626.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107307065394.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107307098162.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10107307130930.jpg?v1"],
    "brand": "samsung",
    "price": 3235.202225041739,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 13,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy M20 32 GB (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/25/280-413/10094999240754.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10094999273522.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10094999306290.jpg?v1", "https://productimages.hepsiburada.net/s/25/280-413/10094999339058.jpg?v1"],
    "brand": "samsung",
    "price": 5850.5748675199875,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 14,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy S8 (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/3/280-413/9604775739442.jpg?v1", "https://productimages.hepsiburada.net/s/4/280-413/9665566703666.jpg?v1", "https://productimages.hepsiburada.net/s/4/280-413/9665566736434.jpg?v1", "https://productimages.hepsiburada.net/s/4/280-413/9665566769202.jpg?v1"],
    "brand": "samsung",
    "price": 3207.2840718201587,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 15,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Huawei P Smart 2019 64 GB (Huawei Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/23/280-413/10059934859314.jpg?v1", "https://productimages.hepsiburada.net/s/23/280-413/10059934892082.jpg?v1", "https://productimages.hepsiburada.net/s/23/280-413/10059934924850.jpg?v1", "https://productimages.hepsiburada.net/s/23/280-413/10059934957618.jpg?v1"],
    "brand": "huawei",
    "price": 5288.552334214134,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 16,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Xiaomi Mi 8 128 GB (İthalatçı Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/20/280-413/9873948540978.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9873948573746.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9873948606514.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9873948639282.jpg?v1"],
    "brand": "xiaomi",
    "price": 1354.662450097338,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 17,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Apple iPhone 6S Plus 32 GB (Apple Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/1/280-413/9489589993522.jpg?v1", "https://productimages.hepsiburada.net/s/1/280-413/9489589927986.jpg?v1", "https://productimages.hepsiburada.net/s/1/280-413/9489589960754.jpg?v1"],
    "brand": "apple",
    "price": 5467.082548922358,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 18,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Meizu 16 64 GB (Meizu Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/24/280-413/10082399387698.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10082399420466.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10082399453234.jpg?v1", "https://productimages.hepsiburada.net/s/24/280-413/10082399486002.jpg?v1"],
    "brand": "meizu",
    "price": 1173.3514841571446,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 19,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Vestel Venüs E3 (Vestel Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/20/280-413/9885707108402.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9885707141170.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9885707173938.jpg?v1"],
    "brand": "vestel",
    "price": 2371.8351283872053,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 20,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Asus Zenfone Max Pro ZB602KL 64 GB (Asus Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/21/280-413/9924255121458.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9924255154226.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9924255186994.jpg?v1"],
    "brand": "asus",
    "price": 2603.504706144322,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 21,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Samsung Galaxy Note 9 128 GB (Samsung Türkiye Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/20/280-413/9902572142642.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9902572175410.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9902572208178.jpg?v1", "https://productimages.hepsiburada.net/s/20/280-413/9902572240946.jpg?v1"],
    "brand": "samsung",
    "price": 1165.0255199945123,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 22,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}, {
    "title": "Huawei Mate 20 Lite Dual Sim 64 GB (İthalatçı Garantili)",
    "category": "phone",
    "images": ["https://productimages.hepsiburada.net/s/21/280-413/9933217792050.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9933217660978.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9933217693746.jpg?v1", "https://productimages.hepsiburada.net/s/21/280-413/9933217726514.jpg?v1"],
    "brand": "huawei",
    "price": 2693.4407990587074,
    "cpu": "1.3GHz Apple A6",
    "camera": "8mp (3264x2448)",
    "size": "124.4mm x 59.2mm x 8.97mm (4.9 x 2.33 x 0.35)",
    "weight": "132 grams (4.7 ounces) with battery",
    "display": "4.0 326 pixel density",
    "battery": "1480 mAh",
    "memory": "16GB, 32GB and RAM 1 GB",
    "id": 23,
    "description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet numquam aspernatur!"
}]

================================================
FILE: src/index.js
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));

serviceWorker.unregister();


================================================
FILE: src/index.scss
================================================
$body-bg: #fff;




@import '~bootstrap/scss/bootstrap.scss';

html{ height:100%; }
body{ min-height:100%; padding:0; margin:0; position:relative; }

body::after{ content:''; display:block; height:100px; }

footer{
  position:absolute;
  bottom:0;
  width:100%;
  height:100px;
}


================================================
FILE: src/pages/Home/Home.js
================================================
import React from 'react';
import FilterBar from "../../containers/FilterBar/FilterBar";
import ProductList from "../../containers/ProductList/ProductList";
import Pagination from "../../components/Pagination/Pagination";

const Home = () => {
    return (
        <React.Fragment>
            <div className="container" style={{paddingTop: '6rem'}} >
                <div className="row">
                    <FilterBar/>
                    <ProductList/>
                </div>
            </div>
        </React.Fragment>
    );
};


export default Home;


================================================
FILE: src/pages/ProductDetail/ProductDetail.js
================================================
import React from 'react';
import {connect} from 'react-redux';
import ProductDetailComponent from '../../components/ProductDetail/ProductDetail';
import ProductSlider from "../../components/ProductSlider/ProductSlider";

const ProductDetail = (props) => {

    console.log(props);

    return (
        <div className="container" style={{padding: '6rem 0'}}>
            <div className="card">
                <div className="row">
                    <ProductSlider images={props.product.images}/>
                    <ProductDetailComponent product={props.product}/>
                </div>
            </div>
        </div>
    );
};

const mapStateToProps = (state, props) =>  {

    const product = state.shop.products.find(product => product.id === +props.match.params.id);

    return {
        product
    }
};



export default connect(mapStateToProps, null)(ProductDetail);


================================================
FILE: src/pages/ShopingCart/ShoppingCart.js
================================================
import React from 'react';
import {connect} from 'react-redux';
import {formatMoney} from "../../pipes/priceFormatter";
import CartItem from "../../components/CartItem/CartItem";

const ShoppingCart = (props) => {
    return (
        <>
                <div className="container" style={{paddingTop: '6rem'}}>
                    <div className="card shopping-cart">
                        <div className="card-header bg-dark text-light">
                            <i className="fa fa-shopping-cart pr-2" aria-hidden="true"></i>
                            Shipping cart
                            <div className="clearfix"></div>
                        </div>
                        <div className="card-body">
                            {props.cartItemCount ? props.cartItems.map(cart => (
                                <CartItem {...cart} img={cart.images[0]} />
                            )) : <h1 className="display-4 mt-5 text-center">There is no product in your cart</h1> }
                        </div>
                        <div className="card-footer">
                            <div className="pull-right" style={{margin: '10px'}}>
                                <div className="pull-right" style={{margin: '5px'}}>
                                    Total price: <b>{formatMoney(props.totalPrice)}€</b>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </>
    );
};


const mapStateToProps = state => {

    console.log(state, 'state has changed');

    return {
        cartItems: state.shop.cart,
        cartItemCount: state.shop.cart.reduce((count, curItem) => {
            return count + curItem.quantity;
        }, 0),
        totalPrice: state.shop.cart.reduce((count, curItem) => {
            return count + (curItem.price * curItem.quantity);
        }, 0)
    }
}

export default connect(mapStateToProps, null)(ShoppingCart);


================================================
FILE: src/pipes/brandFilter.js
================================================
export const brandFilter = (arr, brand) => {
    if(!brand) return arr;

    return arr.filter(product => brand.includes(product.brand));
};

================================================
FILE: src/pipes/orderByFilter.js
================================================
import {ORDER_BY_ASC} from "../actions";

export const orderByFilter = (arr, type ) => {
    if(!type) return arr;
    console.log('orderbYmethod', type);
    if(type === 'asc') {
        return arr.slice().sort((el1, el2) => el1.price - el2.price);
    } else {
        return arr.slice().sort((el1, el2) => el2.price - el1.price);
    }
};

================================================
FILE: src/pipes/paginationFilter.js
================================================
import {store} from "../App";
import {countItem} from "../actions";

export const paginationPipe = (state,args) => {
    if (!args || !args.perPage || !args.currentPage) {
        return state;
    }
    const location = (args.perPage * (args.currentPage - 1)) || 0 ;

    return state.slice(location, location + args.perPage);
};



================================================
FILE: src/pipes/priceFormatter.js
================================================
export const formatMoney = (price) => {
    return price.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
};

================================================
FILE: src/pipes/shortenTitle.js
================================================
export const shortenTitle = (title) => {
    return title.split(' (')[0];
};

================================================
FILE: src/reducers/brand.filter.reducer.js
================================================
import {ADD_BRAND_TO_FILTER, REMOVE_BRAND_FROM_FILTER} from "../actions";

export const  brandFilterReducer = (state = '', action) => {
    switch (action.type) {
        case ADD_BRAND_TO_FILTER:
            if(state.includes(action.brand)) return state;
            return state += action.brand;
        case REMOVE_BRAND_FROM_FILTER:
            console.log('remove brand', action);
            const reg = new RegExp(action.brand, 'gi');
            return state.replace(reg, '');
        default:
            return state;
    }
};



================================================
FILE: src/reducers/index.js
================================================
import {combineReducers} from 'redux';
import shop from './shop.reducer';
import {brandFilterReducer} from "./brand.filter.reducer";
import {orderByPriceReducer} from "./orderByPrice.filter.reducer";
import {paginationReducer} from "./pagination.reducer";

export default combineReducers({
    shop,
    brandFilter: brandFilterReducer,
    orderBy: orderByPriceReducer,
    pagination: paginationReducer
});


================================================
FILE: src/reducers/orderByPrice.filter.reducer.js
================================================
import {CLEAR_ORDER_BY_PRICE, ORDER_BY_ASC, ORDER_BY_DESC} from "../actions";

export const orderByPriceReducer = (state = '', action) => {
    switch (action.type) {
        case ORDER_BY_ASC:
            return 'asc';
        case ORDER_BY_DESC:
            return 'desc';
        case CLEAR_ORDER_BY_PRICE:
            return '';
        default:
            return state;
    }
}

================================================
FILE: src/reducers/pagination.reducer.js
================================================
import {COUNT_ITEM, GO_PAGE, NEXT_PAGE, PREV_PAGE} from "../actions";

const initialState = {
    perPage: 12,
    currentPage: 1,
    pagesToShow: 3,
    totalItemsCount: 0
};


export const paginationReducer = (state = initialState, action) => {
    switch (action.type) {
        case PREV_PAGE:
            if(state.currentPage === 1) return state;

            return {
                ...state,
                currentPage: state.currentPage - 1
            };
        case NEXT_PAGE:
            return {
                ...state,
                currentPage: state.currentPage + 1
            };
        case GO_PAGE:
            return {
                ...state,
                currentPage: action.currentPage
            };
        case COUNT_ITEM:
            return {
                ...state,
                totalItemsCount: action.totalItemsCount
            };
        default:
            return state;
    }
};


================================================
FILE: src/reducers/shop.reducer.js
================================================
import {
    ADD_PRODUCT_TO_CART,
    DECREMENT_CART_ITEM_QUANTITY,
    INCREMENT_CART_ITEM_QUANTITY,
    REMOVE_PRODUCT_FROM_CART
} from '../actions';
import {phones} from "../data/phones";

const initialState = {
    products: phones,
    cart: []
};


const shopReducer = (state = initialState, action ) => {
    let updatedCart;
    let updatedItemIndex;

    switch (action.type) {
        case INCREMENT_CART_ITEM_QUANTITY:
            updatedCart = [...state.cart];
            updatedItemIndex = updatedCart.findIndex(
                item => item.id === action.payload
            );

            const incrementedItem = {
                ...updatedCart[updatedItemIndex]
            };

            incrementedItem.quantity++;

            updatedCart[updatedItemIndex] = incrementedItem;


            return {...state, cart: updatedCart};

        case DECREMENT_CART_ITEM_QUANTITY:
            updatedCart = [...state.cart];
            updatedItemIndex = updatedCart.findIndex(
                item => item.id === action.payload
            );

            const decrementedItem = {
                ...updatedCart[updatedItemIndex]
            };

            decrementedItem.quantity--;

            updatedCart[updatedItemIndex] = decrementedItem;

            return {...state, cart: updatedCart};

        case ADD_PRODUCT_TO_CART:
            updatedCart = [...state.cart];
            updatedItemIndex = updatedCart.findIndex(item => item.id === action.payload.id);

            if(updatedItemIndex < 0) {
                updatedCart.push({...action.payload, quantity: 1});
            } else {
                const updatedItem = {
                    ...updatedCart[updatedItemIndex]
                };

                updatedItem.quantity++;
                updatedCart[updatedItemIndex] = updatedItem;
            }

            return {...state, cart: updatedCart};
        case REMOVE_PRODUCT_FROM_CART:
            updatedCart = [...state.cart];
            updatedItemIndex = updatedCart.findIndex(
                item => item.id === action.payload
            );

            updatedCart.splice(updatedItemIndex, 1);

            return {...state, cart: updatedCart};
        default:
            return state;

    }
};

export default shopReducer;


================================================
FILE: src/serviceWorker.js
================================================
// This optional code is used to register a service worker.
// register() is not called by default.

// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.

// To learn more about the benefits of this model and instructions on how to
// opt-in, read http://bit.ly/CRA-PWA

const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
    // [::1] is the IPv6 localhost address.
    window.location.hostname === '[::1]' ||
    // 127.0.0.1/8 is considered localhost for IPv4.
    window.location.hostname.match(
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
);

export function register(config) {
  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
    // The URL constructor is available in all browsers that support SW.
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
    if (publicUrl.origin !== window.location.origin) {
      // Our service worker won't work if PUBLIC_URL is on a different origin
      // from what our page is served on. This might happen if a CDN is used to
      // serve assets; see https://github.com/facebook/create-react-app/issues/2374
      return;
    }

    window.addEventListener('load', () => {
      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

      if (isLocalhost) {
        // This is running on localhost. Let's check if a service worker still exists or not.
        checkValidServiceWorker(swUrl, config);

        // Add some additional logging to localhost, pointing developers to the
        // service worker/PWA documentation.
        navigator.serviceWorker.ready.then(() => {
          console.log(
            'This web app is being served cache-first by a service ' +
              'worker. To learn more, visit http://bit.ly/CRA-PWA'
          );
        });
      } else {
        // Is not localhost. Just register service worker
        registerValidSW(swUrl, config);
      }
    });
  }
}

function registerValidSW(swUrl, config) {
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        if (installingWorker == null) {
          return;
        }
        installingWorker.onstatechange = () => {
          if (installingWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              // At this point, the updated precached content has been fetched,
              // but the previous service worker will still serve the older
              // content until all client tabs are closed.
              console.log(
                'New content is available and will be used when all ' +
                  'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
              );

              // Execute callback
              if (config && config.onUpdate) {
                config.onUpdate(registration);
              }
            } else {
              // At this point, everything has been precached.
              // It's the perfect time to display a
              // "Content is cached for offline use." message.
              console.log('Content is cached for offline use.');

              // Execute callback
              if (config && config.onSuccess) {
                config.onSuccess(registration);
              }
            }
          }
        };
      };
    })
    .catch(error => {
      console.error('Error during service worker registration:', error);
    });
}

function checkValidServiceWorker(swUrl, config) {
  // Check if the service worker can be found. If it can't reload the page.
  fetch(swUrl)
    .then(response => {
      // Ensure service worker exists, and that we really are getting a JS file.
      const contentType = response.headers.get('content-type');
      if (
        response.status === 404 ||
        (contentType != null && contentType.indexOf('javascript') === -1)
      ) {
        // No service worker found. Probably a different app. Reload the page.
        navigator.serviceWorker.ready.then(registration => {
          registration.unregister().then(() => {
            window.location.reload();
          });
        });
      } else {
        // Service worker found. Proceed as normal.
        registerValidSW(swUrl, config);
      }
    })
    .catch(() => {
      console.log(
        'No internet connection found. App is running in offline mode.'
      );
    });
}

export function unregister() {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready.then(registration => {
      registration.unregister();
    });
  }
}


================================================
FILE: src/utilities/cumulativeOffset.js
================================================
export const cumulativeOffSet = (element) => {
    let top = 0, left = 0;
    do {
        top += element.offsetTop  || 0;
        left += element.offsetLeft || 0;
        element = element.offsetParent;
    } while(element);

    return {
        top: top,
        left: left
    };
};
Download .txt
gitextract_ub8tvy_4/

├── .gitignore
├── .idea/
│   ├── ecommerce.iml
│   ├── inspectionProfiles/
│   │   └── Project_Default.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── vcs.xml
│   └── workspace.xml
├── README.md
├── package.json
├── public/
│   ├── index.html
│   └── manifest.json
└── src/
    ├── App.js
    ├── App.scss
    ├── App.test.js
    ├── actions/
    │   └── index.js
    ├── components/
    │   ├── BrandFilter/
    │   │   ├── BrandFilter.js
    │   │   └── BrandFilter.scss
    │   ├── CartItem/
    │   │   ├── CartItem.js
    │   │   └── CartItem.scss
    │   ├── Footer/
    │   │   └── Footer.js
    │   ├── Header/
    │   │   └── Header.js
    │   ├── LayoutMode/
    │   │   ├── LayoutMode.js
    │   │   └── LayoutMode.scss
    │   ├── OrderFilter/
    │   │   ├── OrderFilter.js
    │   │   └── OrderFilter.scss
    │   ├── Pagination/
    │   │   ├── Pagination.js
    │   │   └── Pagination.scss
    │   ├── Product/
    │   │   ├── Product.js
    │   │   └── Product.scss
    │   ├── ProductDetail/
    │   │   └── ProductDetail.js
    │   ├── ProductSlider/
    │   │   ├── ProductSlider.js
    │   │   └── ProductSlider.scss
    │   └── SlideDots/
    │       ├── SlideDots.js
    │       └── SlideDots.scss
    ├── containers/
    │   ├── FilterBar/
    │   │   └── FilterBar.js
    │   └── ProductList/
    │       ├── ProductList.js
    │       └── ProductList.scss
    ├── data/
    │   ├── brands.js
    │   ├── getData.js
    │   └── phones.js
    ├── index.js
    ├── index.scss
    ├── pages/
    │   ├── Home/
    │   │   └── Home.js
    │   ├── ProductDetail/
    │   │   └── ProductDetail.js
    │   └── ShopingCart/
    │       └── ShoppingCart.js
    ├── pipes/
    │   ├── brandFilter.js
    │   ├── orderByFilter.js
    │   ├── paginationFilter.js
    │   ├── priceFormatter.js
    │   └── shortenTitle.js
    ├── reducers/
    │   ├── brand.filter.reducer.js
    │   ├── index.js
    │   ├── orderByPrice.filter.reducer.js
    │   ├── pagination.reducer.js
    │   └── shop.reducer.js
    ├── serviceWorker.js
    └── utilities/
        └── cumulativeOffset.js
Download .txt
SYMBOL INDEX (31 symbols across 7 files)

FILE: src/App.js
  class App (line 19) | class App extends Component {
    method render (line 20) | render() {

FILE: src/actions/index.js
  constant ADD_PRODUCT_TO_CART (line 1) | const ADD_PRODUCT_TO_CART = 'ADD_PRODUCT_TO_CART';
  constant REMOVE_PRODUCT_FROM_CART (line 2) | const REMOVE_PRODUCT_FROM_CART = 'REMOVE_PRODUCT_FROM_CART';
  constant INCREMENT_CART_ITEM_QUANTITY (line 3) | const INCREMENT_CART_ITEM_QUANTITY = 'INCREMENT_CART_ITEM_QUANTITY';
  constant DECREMENT_CART_ITEM_QUANTITY (line 4) | const DECREMENT_CART_ITEM_QUANTITY = 'DECREMENT_CART_ITEM_QUANTITY';
  constant ADD_BRAND_TO_FILTER (line 35) | const ADD_BRAND_TO_FILTER = 'ADD_BRAND_TO_FILTER';
  constant REMOVE_BRAND_FROM_FILTER (line 36) | const REMOVE_BRAND_FROM_FILTER = 'REMOVE_BRAND_FROM_FILTER';
  constant ORDER_BY_ASC (line 53) | const ORDER_BY_ASC = 'ORDER_BY_ASC';
  constant ORDER_BY_DESC (line 54) | const ORDER_BY_DESC = 'ORDER_BY_DESC';
  constant CLEAR_ORDER_BY_PRICE (line 55) | const CLEAR_ORDER_BY_PRICE = 'CLEAR_ORDER_BY_PRICE';
  constant PREV_PAGE (line 76) | const PREV_PAGE = 'PREV_PAGE';
  constant NEXT_PAGE (line 77) | const NEXT_PAGE = 'NEXT_PAGE';
  constant GO_PAGE (line 78) | const GO_PAGE = 'GO_PAGE';
  constant COUNT_ITEM (line 79) | const COUNT_ITEM = 'COUNT_ITEM';

FILE: src/components/Pagination/Pagination.js
  class Pagination (line 5) | class Pagination extends Component {
    method onPage (line 8) | onPage(n){
    method isOnLastPage (line 12) | isOnLastPage(){
    method totalPages (line 17) | totalPages() {
    method getMin (line 21) | getMin(){
    method getMax (line 25) | getMax() {
    method render (line 67) | render() {

FILE: src/containers/FilterBar/FilterBar.js
  class FilterBar (line 5) | class FilterBar extends Component {
    method render (line 6) | render() {

FILE: src/containers/ProductList/ProductList.js
  class ProductList (line 11) | class ProductList extends Component {
    method render (line 60) | render() {

FILE: src/data/getData.js
  function getRandomArbitrary (line 32) | function getRandomArbitrary(min, max) {

FILE: src/serviceWorker.js
  function register (line 23) | function register(config) {
  function registerValidSW (line 57) | function registerValidSW(swUrl, config) {
  function checkValidServiceWorker (line 101) | function checkValidServiceWorker(swUrl, config) {
  function unregister (line 129) | function unregister() {
Condensed preview — 57 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (127K chars).
[
  {
    "path": ".gitignore",
    "chars": 310,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": ".idea/ecommerce.iml",
    "chars": 458,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"WEB_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\">\n"
  },
  {
    "path": ".idea/inspectionProfiles/Project_Default.xml",
    "chars": 249,
    "preview": "<component name=\"InspectionProjectProfileManager\">\n  <profile version=\"1.0\">\n    <option name=\"myName\" value=\"Project De"
  },
  {
    "path": ".idea/misc.xml",
    "chars": 174,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"JavaScriptSettings\">\n    <option name=\"l"
  },
  {
    "path": ".idea/modules.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n   "
  },
  {
    "path": ".idea/vcs.xml",
    "chars": 180,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping dire"
  },
  {
    "path": ".idea/workspace.xml",
    "chars": 37889,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"BookmarkManager\">\n    <bookmark url=\"fil"
  },
  {
    "path": "README.md",
    "chars": 3480,
    "preview": "# Here is the live demo <a href=\"http://numberless-leg.surge.sh\" style=\"font-size: 40px\">CLICK TO SEE DEMO</a>\n\n![alt-te"
  },
  {
    "path": "package.json",
    "chars": 665,
    "preview": "{\n  \"name\": \"ecommerce\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"bootstrap\": \"^4.3.1\",\n    \"no"
  },
  {
    "path": "public/index.html",
    "chars": 591,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"shortcut icon\" href=\"%PUBLIC_URL%/"
  },
  {
    "path": "public/manifest.json",
    "chars": 306,
    "preview": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n     "
  },
  {
    "path": "src/App.js",
    "chars": 1379,
    "preview": "import React, { Component } from 'react';\nimport {Provider} from 'react-redux';\nimport {createStore } from 'redux';\nimpo"
  },
  {
    "path": "src/App.scss",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/App.test.js",
    "chars": 248,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\n\nit('renders without crashing', ()"
  },
  {
    "path": "src/actions/index.js",
    "chars": 2135,
    "preview": "export const ADD_PRODUCT_TO_CART = 'ADD_PRODUCT_TO_CART';\nexport const REMOVE_PRODUCT_FROM_CART = 'REMOVE_PRODUCT_FROM_C"
  },
  {
    "path": "src/components/BrandFilter/BrandFilter.js",
    "chars": 1756,
    "preview": "import React, {Component} from 'react';\nimport {connect} from 'react-redux';\nimport './BrandFilter.scss';\nimport {brands"
  },
  {
    "path": "src/components/BrandFilter/BrandFilter.scss",
    "chars": 874,
    "preview": ".custom-checkbox {\n  display: block;\n  position: relative;\n  padding-left: 2rem;\n  cursor: pointer;\n  user-select: none;"
  },
  {
    "path": "src/components/CartItem/CartItem.js",
    "chars": 3555,
    "preview": "import React, {useState} from 'react';\nimport {connect} from 'react-redux';\nimport {shortenTitle} from \"../../pipes/shor"
  },
  {
    "path": "src/components/CartItem/CartItem.scss",
    "chars": 1323,
    "preview": "\n\n.quantity {\n  float: left;\n  margin-right: 15px;\n  background-color: #eee;\n  position: relative;\n  width: 80px;\n  over"
  },
  {
    "path": "src/components/Footer/Footer.js",
    "chars": 307,
    "preview": "import React from 'react';\n\nconst Footer = () => {\n    return (\n        <footer className=\"py-5 bg-dark\">\n            <d"
  },
  {
    "path": "src/components/Header/Header.js",
    "chars": 1746,
    "preview": "import React from 'react';\nimport {connect} from 'react-redux';\nimport {NavLink} from 'react-router-dom';\n\nconst Header "
  },
  {
    "path": "src/components/LayoutMode/LayoutMode.js",
    "chars": 528,
    "preview": "import React from 'react';\nimport './LayoutMode.scss';\n\nconst LayoutMode = (\n    {\n        len,\n        click,\n        i"
  },
  {
    "path": "src/components/LayoutMode/LayoutMode.scss",
    "chars": 479,
    "preview": ".layout-mode {\n\n  display: flex;\n  flex-direction: row;\n  padding: .3rem;\n  border: 2px solid gray;\n  cursor: pointer;\n\n"
  },
  {
    "path": "src/components/OrderFilter/OrderFilter.js",
    "chars": 2386,
    "preview": "import React, {useState} from 'react';\nimport {connect} from 'react-redux';\nimport './OrderFilter.scss';\nimport {clearOr"
  },
  {
    "path": "src/components/OrderFilter/OrderFilter.scss",
    "chars": 893,
    "preview": ".custom-radio-btn {\n  display: block;\n  position: relative;\n  cursor: pointer;\n  padding-left: 2rem;\n  user-select: none"
  },
  {
    "path": "src/components/Pagination/Pagination.js",
    "chars": 3363,
    "preview": "import React, {Component} from 'react';\nimport {connect} from \"react-redux\";\nimport {goPage, nextPage, prevPage} from \"."
  },
  {
    "path": "src/components/Pagination/Pagination.scss",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/components/Product/Product.js",
    "chars": 2769,
    "preview": "import React, {useState} from 'react';\nimport {connect} from 'react-redux';\nimport {Link} from 'react-router-dom';\nimpor"
  },
  {
    "path": "src/components/Product/Product.scss",
    "chars": 953,
    "preview": ".product {\n  padding-bottom: 2rem;\n  &__img {\n    width: 100%;\n    height: 100%;\n  }\n\n  &__text {\n    flex: 0 0 40%;\n  }"
  },
  {
    "path": "src/components/ProductDetail/ProductDetail.js",
    "chars": 2521,
    "preview": "import React from 'react';\nimport {connect} from 'react-redux';\nimport {formatMoney} from \"../../pipes/priceFormatter\";\n"
  },
  {
    "path": "src/components/ProductSlider/ProductSlider.js",
    "chars": 1962,
    "preview": "import React, {useState} from 'react';\nimport {cumulativeOffSet} from \"../../utilities/cumulativeOffset\"\nimport './Produ"
  },
  {
    "path": "src/components/ProductSlider/ProductSlider.scss",
    "chars": 460,
    "preview": ".gallery-wrap .img-big-wrap img {\n  height: 450px;\n  width: auto;\n  display: inline-block;\n}\n\n\n\n.gallery-wrap .img-small"
  },
  {
    "path": "src/components/SlideDots/SlideDots.js",
    "chars": 593,
    "preview": "import React from 'react';\nimport './SlideDots.scss';\n\nconst SlideDots = (\n    {\n        len,\n        activeItem,\n      "
  },
  {
    "path": "src/components/SlideDots/SlideDots.scss",
    "chars": 533,
    "preview": ".owl-dots {\n  display: none;\n  position: absolute;\n  bottom: -1rem;\n  left: 0;\n\n}\n\n.owl-dots {\n  width: 100%;\n  text-ali"
  },
  {
    "path": "src/containers/FilterBar/FilterBar.js",
    "chars": 631,
    "preview": "import React, {Component} from 'react';\nimport BrandFilter from \"../../components/BrandFilter/BrandFilter\";\nimport Order"
  },
  {
    "path": "src/containers/ProductList/ProductList.js",
    "chars": 3522,
    "preview": "import React, {Component} from 'react';\nimport {connect} from 'react-redux';\nimport Product from \"../../components/Produ"
  },
  {
    "path": "src/containers/ProductList/ProductList.scss",
    "chars": 59,
    "preview": "\n$body-bg: #000;\n\n@import '~bootstrap/scss/bootstrap.scss';"
  },
  {
    "path": "src/data/brands.js",
    "chars": 84,
    "preview": "export const brands = [\"apple\",\"huawei\",\"meizu\",\"samsung\",\"vestel\",\"xiaomi\",\"asus\"];"
  },
  {
    "path": "src/data/getData.js",
    "chars": 1365,
    "preview": "\nvar imagesMap = {};\n\nvar images = document.querySelectorAll('.product-image');\n\nconsole.log(images);\n\nimages.forEach(im"
  },
  {
    "path": "src/data/phones.js",
    "chars": 20700,
    "preview": "export const phones = [{\n    \"title\": \"Apple iPhone 7 Plus 32 GB (Apple Türkiye Garantili)\",\n    \"category\": \"phone\",\n  "
  },
  {
    "path": "src/index.js",
    "chars": 248,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.scss';\nimport App from './App';\nimport * as"
  },
  {
    "path": "src/index.scss",
    "chars": 280,
    "preview": "$body-bg: #fff;\n\n\n\n\n@import '~bootstrap/scss/bootstrap.scss';\n\nhtml{ height:100%; }\nbody{ min-height:100%; padding:0; ma"
  },
  {
    "path": "src/pages/Home/Home.js",
    "chars": 559,
    "preview": "import React from 'react';\nimport FilterBar from \"../../containers/FilterBar/FilterBar\";\nimport ProductList from \"../../"
  },
  {
    "path": "src/pages/ProductDetail/ProductDetail.js",
    "chars": 884,
    "preview": "import React from 'react';\nimport {connect} from 'react-redux';\nimport ProductDetailComponent from '../../components/Pro"
  },
  {
    "path": "src/pages/ShopingCart/ShoppingCart.js",
    "chars": 1987,
    "preview": "import React from 'react';\nimport {connect} from 'react-redux';\nimport {formatMoney} from \"../../pipes/priceFormatter\";\n"
  },
  {
    "path": "src/pipes/brandFilter.js",
    "chars": 140,
    "preview": "export const brandFilter = (arr, brand) => {\n    if(!brand) return arr;\n\n    return arr.filter(product => brand.includes"
  },
  {
    "path": "src/pipes/orderByFilter.js",
    "chars": 341,
    "preview": "import {ORDER_BY_ASC} from \"../actions\";\n\nexport const orderByFilter = (arr, type ) => {\n    if(!type) return arr;\n    c"
  },
  {
    "path": "src/pipes/paginationFilter.js",
    "chars": 332,
    "preview": "import {store} from \"../App\";\nimport {countItem} from \"../actions\";\n\nexport const paginationPipe = (state,args) => {\n   "
  },
  {
    "path": "src/pipes/priceFormatter.js",
    "chars": 107,
    "preview": "export const formatMoney = (price) => {\n    return price.toFixed(2).replace(/\\d(?=(\\d{3})+\\.)/g, '$&,');\n};"
  },
  {
    "path": "src/pipes/shortenTitle.js",
    "chars": 76,
    "preview": "export const shortenTitle = (title) => {\n    return title.split(' (')[0];\n};"
  },
  {
    "path": "src/reducers/brand.filter.reducer.js",
    "chars": 538,
    "preview": "import {ADD_BRAND_TO_FILTER, REMOVE_BRAND_FROM_FILTER} from \"../actions\";\n\nexport const  brandFilterReducer = (state = '"
  },
  {
    "path": "src/reducers/index.js",
    "chars": 409,
    "preview": "import {combineReducers} from 'redux';\nimport shop from './shop.reducer';\nimport {brandFilterReducer} from \"./brand.filt"
  },
  {
    "path": "src/reducers/orderByPrice.filter.reducer.js",
    "chars": 383,
    "preview": "import {CLEAR_ORDER_BY_PRICE, ORDER_BY_ASC, ORDER_BY_DESC} from \"../actions\";\n\nexport const orderByPriceReducer = (state"
  },
  {
    "path": "src/reducers/pagination.reducer.js",
    "chars": 931,
    "preview": "import {COUNT_ITEM, GO_PAGE, NEXT_PAGE, PREV_PAGE} from \"../actions\";\n\nconst initialState = {\n    perPage: 12,\n    curre"
  },
  {
    "path": "src/reducers/shop.reducer.js",
    "chars": 2281,
    "preview": "import {\n    ADD_PRODUCT_TO_CART,\n    DECREMENT_CART_ITEM_QUANTITY,\n    INCREMENT_CART_ITEM_QUANTITY,\n    REMOVE_PRODUCT"
  },
  {
    "path": "src/serviceWorker.js",
    "chars": 4948,
    "preview": "// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the ap"
  },
  {
    "path": "src/utilities/cumulativeOffset.js",
    "chars": 286,
    "preview": "export const cumulativeOffSet = (element) => {\n    let top = 0, left = 0;\n    do {\n        top += element.offsetTop  || "
  }
]

About this extraction

This page contains the full source code of the TheCoderDream/React-Ecommerce-App-with-Redux GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 57 files (113.7 KB), approximately 32.0k tokens, and a symbol index with 31 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!