diff --git a/.gitignore b/.gitignore
index ab47aa1..217e803 100644
--- a/.gitignore
+++ b/.gitignore
@@ -116,3 +116,4 @@ deploy.ps1
macbuild.sh
Usage.md
dist-electron
+.idea
\ No newline at end of file
diff --git a/README.md b/README.md
index 3a21f6d..4475bb8 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ In the project directory, you can run:
### `yarn start`
Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+Open [http://localhost:3006](http://localhost:3006) to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
diff --git a/electron/main-src.js b/electron/main-src.js
index 766830f..1be7f9d 100644
--- a/electron/main-src.js
+++ b/electron/main-src.js
@@ -174,7 +174,7 @@ function createWindow() {
// and load the index.html of the app.
// win.loadFile("index.html");
if (isDev) {
- mainWindow.loadURL("http://localhost:3000");
+ mainWindow.loadURL("http://localhost:3006");
} else {
const indexPath = path.join(appPath, "build", "index.html");
mainWindow.loadFile(indexPath);
diff --git a/hasura/config.yaml b/hasura/config.yaml
index e0ce1c4..4d86930 100644
--- a/hasura/config.yaml
+++ b/hasura/config.yaml
@@ -14,7 +14,7 @@ migrations_directory: migrations
seeds_directory: seeds
actions:
kind: synchronous
- handler_webhook_baseurl: http://localhost:3000
+ handler_webhook_baseurl: http://localhost:3006
codegen:
framework: ""
output_dir: ""
diff --git a/hasura/config.yaml.prod b/hasura/config.yaml.prod
index 73e3fe3..a31b57d 100644
--- a/hasura/config.yaml.prod
+++ b/hasura/config.yaml.prod
@@ -14,7 +14,7 @@ migrations_directory: migrations
seeds_directory: seeds
actions:
kind: synchronous
- handler_webhook_baseurl: http://localhost:3000
+ handler_webhook_baseurl: http://localhost:3006
codegen:
framework: ""
output_dir: ""
diff --git a/src/components/atoms/watcher-status/watcher-status.atom.jsx b/src/components/atoms/watcher-status/watcher-status.atom.jsx
index 97868ac..d782911 100644
--- a/src/components/atoms/watcher-status/watcher-status.atom.jsx
+++ b/src/components/atoms/watcher-status/watcher-status.atom.jsx
@@ -1,4 +1,4 @@
-import { Alert } from "antd";
+import { Alert, Typography } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -15,13 +15,17 @@ const mapStateToProps = createStructuredSelector({
});
export function WatcherStatusAtom({ watcherStatus, watcherError }) {
+ const statusClassName =
+ watcherStatus === "Started"
+ ? "settings-watcher-status settings-watcher-status--started"
+ : "settings-watcher-status settings-watcher-status--stopped";
+
return (
-
ipcRenderer.send("test")}
- style={{ color: watcherStatus === "Started" ? "green" : "tomato" }}
- >
-
{watcherStatus}
- {watcherError &&
}
+
ipcRenderer.send("test")}>
+
+ {watcherStatus || "Unknown"}
+
+ {watcherError &&
}
);
}
diff --git a/src/components/molecules/filepath-add/filepath-add.molecule.jsx b/src/components/molecules/filepath-add/filepath-add.molecule.jsx
index 8c942e6..80f2adc 100644
--- a/src/components/molecules/filepath-add/filepath-add.molecule.jsx
+++ b/src/components/molecules/filepath-add/filepath-add.molecule.jsx
@@ -3,9 +3,13 @@ import React from "react";
import ipcTypes from "../../../ipc.types";
const { ipcRenderer } = window;
-export default function FilepathAddMolecule() {
+export default function FilepathAddMolecule(buttonProps) {
const handleClick = () => {
ipcRenderer.send(ipcTypes.fileWatcher.toMain.addPath);
};
- return
;
+ return (
+
+ );
}
diff --git a/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx b/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx
index d09464c..a31eb3f 100644
--- a/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx
+++ b/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx
@@ -1,21 +1,29 @@
-import { Button, Form, Input, InputNumber, Popconfirm, Select, Space, Switch, Typography } from "antd";
+import { Button, Flex, Form, Input, InputNumber, Popconfirm, Select, Switch, Typography } from "antd";
import React from "react";
import LayoutFormRow from "../../atoms/layout-form-row/layout-form-row.atom";
+import "./shop-settings-form.molecule.styles.scss";
export default function ShopSettingsFormMolecule({ form, saveLoading }) {
return (
-
- Shop Settings
- form.submit()}
- >
-
-
+
+
+
+ Shop Settings
+
+ Update the defaults RPS uses when calculating and syncing shop data.
+
+
+ form.submit()}
+ >
+
+
+
-
+
-
+
+
+
-
+
-
-
+
+
);
}
diff --git a/src/components/molecules/shop-settings-form/shop-settings-form.molecule.styles.scss b/src/components/molecules/shop-settings-form/shop-settings-form.molecule.styles.scss
new file mode 100644
index 0000000..e3a662e
--- /dev/null
+++ b/src/components/molecules/shop-settings-form/shop-settings-form.molecule.styles.scss
@@ -0,0 +1,42 @@
+.shop-settings-form {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.shop-settings-form__header {
+ width: 100%;
+}
+
+.shop-settings-form__header .ant-typography {
+ margin-bottom: 0;
+}
+
+.shop-settings-form__header .ant-typography + .ant-typography {
+ margin-top: 4px;
+ max-width: 640px;
+}
+
+.shop-settings-form__row .ant-form-item {
+ margin-bottom: 12px;
+}
+
+.shop-settings-form__row .ant-form-item-label > label {
+ white-space: normal;
+ line-height: 1.3;
+}
+
+.shop-settings-form__row .ant-input-number,
+.shop-settings-form__row .ant-select {
+ width: 100%;
+}
+
+@media (max-width: 768px) {
+ .shop-settings-form__header {
+ align-items: stretch !important;
+ }
+
+ .shop-settings-form__header .ant-btn {
+ width: 100%;
+ }
+}
diff --git a/src/components/molecules/watcher-start/watcher-start.molecule.jsx b/src/components/molecules/watcher-start/watcher-start.molecule.jsx
index aa28435..2a95390 100644
--- a/src/components/molecules/watcher-start/watcher-start.molecule.jsx
+++ b/src/components/molecules/watcher-start/watcher-start.molecule.jsx
@@ -3,14 +3,10 @@ import React from "react";
import ipcTypes from "../../../ipc.types";
const { ipcRenderer } = window;
-export default function WatcherStartMolecule() {
+export default function WatcherStartMolecule(buttonProps) {
const handleClick = () => {
ipcRenderer.send(ipcTypes.fileWatcher.toMain.start);
};
- return (
-
-
-
- );
+ return ;
}
diff --git a/src/components/molecules/watcher-stop/watcher-stop.molecule.jsx b/src/components/molecules/watcher-stop/watcher-stop.molecule.jsx
index 6e3c51a..5498022 100644
--- a/src/components/molecules/watcher-stop/watcher-stop.molecule.jsx
+++ b/src/components/molecules/watcher-stop/watcher-stop.molecule.jsx
@@ -3,14 +3,10 @@ import React from "react";
import ipcTypes from "../../../ipc.types";
const { ipcRenderer } = window;
-export default function WatcherStopMolecule() {
+export default function WatcherStopMolecule(buttonProps) {
const handleClick = () => {
ipcRenderer.send(ipcTypes.fileWatcher.toMain.stop);
};
- return (
-
-
-
- );
+ return ;
}
diff --git a/src/components/organisms/filepaths-list/filepaths-list.organism.jsx b/src/components/organisms/filepaths-list/filepaths-list.organism.jsx
index 37fe898..e24cbaf 100644
--- a/src/components/organisms/filepaths-list/filepaths-list.organism.jsx
+++ b/src/components/organisms/filepaths-list/filepaths-list.organism.jsx
@@ -1,4 +1,4 @@
-import { List, Typography } from "antd";
+import { Empty, Flex, List, Typography } from "antd";
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -22,10 +22,32 @@ export function FilePathsList({ watchedPaths }) {
}, []);
return (
-
-
Watcher File Paths
-
-
+
+
+
+ Watcher File Paths
+
+ {watchedPaths && watchedPaths.length
+ ? `${watchedPaths.length} path${watchedPaths.length === 1 ? "" : "s"} being watched`
+ : "Choose the folders the watcher should monitor."}
+
+
+
+
+
+ ),
+ }}
+ />
);
}
diff --git a/src/components/organisms/watcher-manager/watcher-manager.organism.jsx b/src/components/organisms/watcher-manager/watcher-manager.organism.jsx
index 791466f..b8b0a9d 100644
--- a/src/components/organisms/watcher-manager/watcher-manager.organism.jsx
+++ b/src/components/organisms/watcher-manager/watcher-manager.organism.jsx
@@ -1,16 +1,48 @@
-import { Typography } from "antd";
+import { Button, Flex, Typography } from "antd";
import React from "react";
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import ipcTypes from "../../../ipc.types";
+import { selectWatcherStatus } from "../../../redux/application/application.selectors";
import WatcherStatusAtom from "../../atoms/watcher-status/watcher-status.atom";
-import WatcherStartMolecule from "../../molecules/watcher-start/watcher-start.molecule";
-import WatcherStopMolecule from "../../molecules/watcher-stop/watcher-stop.molecule";
+const { ipcRenderer } = window;
+
+const mapStateToProps = createStructuredSelector({
+ watcherStatus: selectWatcherStatus,
+});
+
+export function WatcherManagerOrganism({ watcherStatus }) {
+ const watcherStarted = watcherStatus === "Started";
+ const handleWatcherToggle = () => {
+ ipcRenderer.send(
+ watcherStarted
+ ? ipcTypes.fileWatcher.toMain.stop
+ : ipcTypes.fileWatcher.toMain.start
+ );
+ };
-export default function WatcherManagerOrganism() {
return (
-
-
Watcher Status
-
-
-
+
+
+ Watcher Status
+
+ Start or stop the watcher without leaving settings.
+
+
+
+
+
+
);
}
+
+export default connect(mapStateToProps)(WatcherManagerOrganism);
diff --git a/src/components/pages/settings/settings.page.jsx b/src/components/pages/settings/settings.page.jsx
index 2b0911b..7793e43 100644
--- a/src/components/pages/settings/settings.page.jsx
+++ b/src/components/pages/settings/settings.page.jsx
@@ -1,4 +1,4 @@
-import { Col, Row } from "antd";
+import { Card, Col, Row, Space, Typography } from "antd";
import React, { useEffect } from "react";
import ipcTypes from "../../../ipc.types";
import NotificationsToggleAtom from "../../atoms/notifications-toggle/notifications-toggle.atom";
@@ -7,6 +7,7 @@ import WatcherPollingMolecule from "../../molecules/watcher-polling/watcher-poll
import FilePathsListOrganism from "../../organisms/filepaths-list/filepaths-list.organism";
import ShopSettingsOrganism from "../../organisms/shop-settings/shop-settings.organism";
import WatcherManagerOrganism from "../../organisms/watcher-manager/watcher-manager.organism";
+import "./settings.page.styles.scss";
const { ipcRenderer } = window;
export default function SettingsPage() {
@@ -15,20 +16,43 @@ export default function SettingsPage() {
}, []);
return (
-
-
-
-
+
+
+ Settings
+
+ Manage watcher behavior, notifications, and shop defaults in one compact workspace.
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+ Automation
+
+ Fine-tune polling, startup behavior, and desktop notifications.
+
+
+
+
+
+
+
+
-
+
+
+
);
}
diff --git a/src/components/pages/settings/settings.page.styles.scss b/src/components/pages/settings/settings.page.styles.scss
new file mode 100644
index 0000000..79afbf3
--- /dev/null
+++ b/src/components/pages/settings/settings.page.styles.scss
@@ -0,0 +1,192 @@
+.settings-page-container {
+ height: 100%;
+ overflow-y: auto;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ padding-bottom: 16px;
+}
+
+.settings-page__hero {
+ padding: 18px 24px;
+ border-radius: 18px;
+ background: linear-gradient(135deg, #ffffff 0%, #f5f9ff 55%, #eef4ff 100%);
+ border: 1px solid #dbe7ff;
+ box-shadow: 0 10px 24px rgba(23, 43, 77, 0.06);
+
+ .ant-typography {
+ margin-bottom: 0;
+ }
+
+ .ant-typography + .ant-typography {
+ margin-top: 4px;
+ }
+}
+
+.settings-page__side-stack {
+ width: 100%;
+}
+
+.settings-page__side-stack > .ant-space-item,
+.settings-page__controls > .ant-space-item {
+ width: 100%;
+}
+
+.settings-page__card {
+ border-radius: 18px;
+ box-shadow: 0 10px 24px rgba(15, 23, 42, 0.06);
+
+ .ant-card-body {
+ padding: 18px 20px;
+ }
+
+ .ant-typography:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.settings-page__card--filepaths {
+ .ant-card-body {
+ padding-bottom: 14px;
+ }
+}
+
+.settings-page__card--automation {
+ .ant-typography + .ant-typography {
+ margin-top: 2px;
+ }
+}
+
+.settings-page__controls {
+ width: 100%;
+}
+
+.settings-page__controls > .ant-space-item > * {
+ padding: 10px 12px;
+ border-radius: 12px;
+ background: #fafcff;
+ border: 1px solid #edf2ff;
+}
+
+.settings-page__controls > .ant-space-item > * > div {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ flex-wrap: wrap;
+}
+
+.settings-page__controls > .ant-space-item > * > div + div {
+ margin-top: 8px;
+}
+
+.settings-page__controls > .ant-space-item > * > div > div:first-child {
+ flex: 1;
+ min-width: 0;
+}
+
+.settings-page__controls .ant-input-number {
+ width: 96px;
+}
+
+.settings-filepaths {
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+}
+
+.settings-filepaths__header {
+ width: 100%;
+}
+
+.settings-filepaths__header .ant-typography {
+ margin-bottom: 0;
+}
+
+.settings-filepaths__list {
+ overflow: hidden;
+ border: 1px solid #edf2ff;
+ border-radius: 14px;
+ background: #fafcff;
+}
+
+.settings-filepaths__list .ant-list-item {
+ padding: 12px 16px;
+}
+
+.settings-filepaths__list .ant-list-empty-text {
+ padding: 28px 16px;
+}
+
+.settings-filepaths__list .ant-empty {
+ margin-block: 8px;
+}
+
+.settings-watcher-manager {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.settings-watcher-manager__header .ant-typography {
+ margin-bottom: 0;
+}
+
+.settings-watcher-manager__content {
+ width: 100%;
+}
+
+.settings-watcher-manager__toggle {
+ min-width: 112px;
+}
+
+.settings-watcher-status-wrap {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+.settings-watcher-status {
+ display: inline-flex;
+ align-items: center;
+ padding: 6px 12px;
+ border-radius: 999px;
+ border: 1px solid transparent;
+}
+
+.settings-watcher-status--started {
+ color: #389e0d;
+ background: #f6ffed;
+ border-color: #b7eb8f;
+}
+
+.settings-watcher-status--stopped {
+ color: #cf1322;
+ background: #fff1f0;
+ border-color: #ffa39e;
+}
+
+.settings-watcher-status__error {
+ max-width: 100%;
+}
+
+@media (max-width: 768px) {
+ .settings-page-container {
+ gap: 16px;
+ padding-bottom: 16px;
+ }
+
+ .settings-page__hero,
+ .settings-page__card .ant-card-body {
+ padding: 20px;
+ }
+
+ .settings-filepaths__header,
+ .settings-watcher-manager__content {
+ align-items: stretch !important;
+ }
+
+ .settings-watcher-manager__toggle {
+ flex: 1;
+ }
+}
diff --git a/vite.config.js b/vite.config.js
index 56cf54e..1a89bd5 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -19,7 +19,7 @@ export default defineConfig({
},
server: {
host: true,
- port: 3000,
+ port: 3006,
open: true
},
build: {