├── src
├── renderer
│ ├── interfaces
│ │ ├── misc.tsx
│ │ ├── mainMessages.tsx
│ │ ├── overview.tsx
│ │ ├── store
│ │ │ └── authReducerActionsInterfaces.tsx
│ │ ├── filters.tsx
│ │ └── items.tsx
│ ├── views
│ │ ├── login
│ │ │ ├── types
│ │ │ │ └── LoginMethod.ts
│ │ │ ├── login.tsx
│ │ │ ├── components
│ │ │ │ └── LoginTabs.tsx
│ │ │ └── HandleSuccess.tsx
│ │ ├── overview
│ │ │ ├── categoryDistribution
│ │ │ │ └── categoriesRGB.tsx
│ │ │ ├── rightGraph.tsx
│ │ │ ├── leftGraph.tsx
│ │ │ ├── EmptyField.tsx
│ │ │ ├── overview.tsx
│ │ │ ├── barChatMajors.tsx
│ │ │ ├── barChart.tsx
│ │ │ ├── sidebar
│ │ │ │ └── sideBar.tsx
│ │ │ ├── filter
│ │ │ │ └── optionsDropdown.tsx
│ │ │ ├── charts
│ │ │ │ └── pieChart.tsx
│ │ │ ├── radarChart copy.tsx
│ │ │ └── overviewOptionsDropdown.tsx
│ │ └── tradeUp
│ │ │ ├── sidebar
│ │ │ └── sideBar.tsx
│ │ │ └── filter
│ │ │ └── optionsDropdown.tsx
│ ├── functionsClasses
│ │ ├── createCSGOImage.tsx
│ │ ├── reducerManager.tsx
│ │ ├── filters
│ │ │ ├── search.tsx
│ │ │ └── custom.tsx
│ │ ├── storageUnits
│ │ │ ├── storageUnitsFunctions.tsx
│ │ │ └── storageUnitsClass.tsx
│ │ ├── downloadReport.tsx
│ │ ├── rendererCommands
│ │ │ └── admin.tsx
│ │ └── prices.tsx
│ ├── components
│ │ └── content
│ │ │ ├── shared
│ │ │ ├── iconsLogo
│ │ │ │ ├── minimize.tsx
│ │ │ │ ├── restore.tsx
│ │ │ │ ├── close.tsx
│ │ │ │ ├── maximize.tsx
│ │ │ │ ├── logo.tsx
│ │ │ │ └── logo 2.tsx
│ │ │ ├── animations.tsx
│ │ │ ├── filters
│ │ │ │ ├── transferAmount.tsx
│ │ │ │ ├── inventoryAmount.tsx
│ │ │ │ ├── accountAmount.tsx
│ │ │ │ └── pricingAmount.tsx
│ │ │ ├── rarities.tsx
│ │ │ ├── emptyState.tsx
│ │ │ ├── titleBarWindows.tsx
│ │ │ ├── steamLogo.tsx
│ │ │ ├── categories.tsx
│ │ │ └── modals & notifcations
│ │ │ │ ├── notification.tsx
│ │ │ │ └── modalTradeResult.tsx
│ │ │ ├── Inventory
│ │ │ ├── inventoryRows
│ │ │ │ ├── QTYRow.tsx
│ │ │ │ ├── rarityRow.tsx
│ │ │ │ ├── storageRow.tsx
│ │ │ │ ├── tradeholdRow.tsx
│ │ │ │ ├── floatRow.tsx
│ │ │ │ ├── collectionsRow.tsx
│ │ │ │ ├── functions.tsx
│ │ │ │ ├── moveableRow.tsx
│ │ │ │ ├── inventoryLinkRow.tsx
│ │ │ │ ├── priceRow.tsx
│ │ │ │ └── stickerPatchesRow.tsx
│ │ │ ├── inventoryFilterSetup.tsx
│ │ │ └── inventory.tsx
│ │ │ ├── storageUnits
│ │ │ ├── to
│ │ │ │ └── toFilterSetup.tsx
│ │ │ └── from
│ │ │ │ ├── fromFilterSetup.tsx
│ │ │ │ └── Content.tsx
│ │ │ └── loadStorageUnitsButton.tsx
│ ├── variables
│ │ └── overviewOptions.tsx
│ ├── context
│ │ └── toMoveContext.tsx
│ ├── store
│ │ ├── helpers
│ │ │ ├── globaloffensiveNotifications.tsx
│ │ │ └── userStatusHelper.tsx
│ │ ├── actions
│ │ │ ├── modalTrade.tsx
│ │ │ ├── userStatsActions.tsx
│ │ │ ├── pricingActions.tsx
│ │ │ ├── tradeUpActions.tsx
│ │ │ ├── modalMove actions.tsx
│ │ │ ├── settings.tsx
│ │ │ ├── moveToActions.tsx
│ │ │ ├── moveFromActions.tsx
│ │ │ └── filtersInventoryActions.tsx
│ │ ├── configureStore.tsx
│ │ ├── inventory
│ │ │ ├── inventoryInterfaces.tsx
│ │ │ ├── inventoryActions.tsx
│ │ │ ├── inventoryReducer.tsx
│ │ │ └── inventoryClass.tsx
│ │ ├── reducer
│ │ │ ├── modalRename.tsx
│ │ │ ├── index.tsx
│ │ │ ├── modalTrade.tsx
│ │ │ ├── userStatus.tsx
│ │ │ ├── pricing.tsx
│ │ │ ├── settings.tsx
│ │ │ ├── modalMove.tsx
│ │ │ ├── tradeupReducer.tsx
│ │ │ ├── moveFromReducers.tsx
│ │ │ └── moveToReducers.tsx
│ │ └── handleMessage.tsx
│ ├── index.tsx
│ └── index.ejs
├── shared
│ └── Interfaces.tsx
│ │ ├── IPCReturn.tsx
│ │ ├── login.tsx
│ │ └── store.tsx
├── emitters.ts
├── main
│ ├── helpers
│ │ ├── eventEmitter.ts
│ │ ├── classes
│ │ │ ├── steam
│ │ │ │ ├── inventoryManager.tsx
│ │ │ │ ├── items
│ │ │ │ │ ├── steam.js
│ │ │ │ │ └── getCommands.js
│ │ │ │ ├── currency.tsx
│ │ │ │ └── backup
│ │ │ │ │ └── currency.json
│ │ │ └── IPCGenerators
│ │ │ │ └── loginGenerator.tsx
│ │ └── login
│ │ │ ├── loginRegular.tsx
│ │ │ └── flowLoginRegularQR.tsx
│ ├── interfaces
│ │ └── mainInterfaces.tsx
│ ├── util.ts
│ └── scripts
│ │ └── versionHelper.tsx
└── __tests__
│ └── App.test.tsx
├── .erb
├── mocks
│ └── fileMock.js
├── img
│ ├── erb-banner.png
│ └── erb-logo.png
├── configs
│ ├── .eslintrc
│ ├── webpack.config.eslint.ts
│ ├── postcss.config.js
│ ├── webpack.config.base.ts
│ ├── webpack.paths.ts
│ ├── webpack.config.renderer.dev.dll.ts
│ └── webpack.config.main.prod.ts
└── scripts
│ ├── .eslintrc
│ ├── link-modules.js
│ ├── delete-source-maps.js
│ ├── check-node-env.js
│ ├── clean.js
│ ├── check-port-in-use.js
│ ├── electron-rebuild.js
│ ├── check-build-exists.ts
│ ├── notarize.js
│ └── check-native-dep.js
├── .erb.zip
├── assets
├── icon.ico
├── icon.png
├── icon.icns
├── casemove.png
├── casemove-preview.png
├── assets.d.ts
├── entitlements.mac.plist
└── icon.svg
├── .editorconfig
├── .gitattributes
├── .eslintignore
├── tailwind.config.js
├── sign.js
├── release
└── app
│ └── package.json
├── tsconfig.json
├── .gitignore
└── .eslintrc.js
/src/renderer/interfaces/misc.tsx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.erb/mocks/fileMock.js:
--------------------------------------------------------------------------------
1 | export default 'test-file-stub';
2 |
--------------------------------------------------------------------------------
/.erb.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/.erb.zip
--------------------------------------------------------------------------------
/assets/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/assets/icon.ico
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/assets/icon.png
--------------------------------------------------------------------------------
/assets/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/assets/icon.icns
--------------------------------------------------------------------------------
/assets/casemove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/assets/casemove.png
--------------------------------------------------------------------------------
/.erb/img/erb-banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/.erb/img/erb-banner.png
--------------------------------------------------------------------------------
/.erb/img/erb-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/.erb/img/erb-logo.png
--------------------------------------------------------------------------------
/assets/casemove-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/udoless/casemove/main/assets/casemove-preview.png
--------------------------------------------------------------------------------
/src/renderer/views/login/types/LoginMethod.ts:
--------------------------------------------------------------------------------
1 | export type LoginMethod = 'QR' | 'WEBTOKEN' | 'REGULAR'
2 |
--------------------------------------------------------------------------------
/src/shared/Interfaces.tsx/IPCReturn.tsx:
--------------------------------------------------------------------------------
1 | export interface CurrencyReturnValue {
2 | currency: string
3 | rate: number
4 | }
5 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/createCSGOImage.tsx:
--------------------------------------------------------------------------------
1 | export function createCSGOImage ( urlEndpath : string ) : string {
2 | return urlEndpath
3 | }
4 |
--------------------------------------------------------------------------------
/.erb/configs/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": "off",
4 | "global-require": "off",
5 | "import/no-dynamic-require": "off"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/emitters.ts:
--------------------------------------------------------------------------------
1 | import EventEmitter from "events";
2 |
3 | class MyEmitter extends EventEmitter {}
4 | const emitterAccount = new MyEmitter();
5 |
6 | export {emitterAccount}
7 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.eslint.ts:
--------------------------------------------------------------------------------
1 | /* eslint import/no-unresolved: off, import/no-self-import: off */
2 |
3 | module.exports = require('./webpack.config.renderer.dev').default;
4 |
--------------------------------------------------------------------------------
/src/main/helpers/eventEmitter.ts:
--------------------------------------------------------------------------------
1 | import EventEmitter from "events";
2 |
3 | class MyEmitter extends EventEmitter {}
4 | const emitterAccount = new MyEmitter();
5 |
6 | export {emitterAccount}
7 |
--------------------------------------------------------------------------------
/.erb/configs/postcss.config.js:
--------------------------------------------------------------------------------
1 | const tailwindcss = require('tailwindcss');
2 | const autoprefixer = require('autoprefixer');
3 |
4 | module.exports = {
5 | plugins: [tailwindcss, autoprefixer],
6 | };
7 |
--------------------------------------------------------------------------------
/.erb/scripts/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": "off",
4 | "global-require": "off",
5 | "import/no-dynamic-require": "off",
6 | "import/no-extraneous-dependencies": "off"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
2 | *.exe binary
3 | *.png binary
4 | *.jpg binary
5 | *.jpeg binary
6 | *.ico binary
7 | *.icns binary
8 | *.eot binary
9 | *.otf binary
10 | *.ttf binary
11 | *.woff binary
12 | *.woff2 binary
13 |
--------------------------------------------------------------------------------
/src/__tests__/App.test.tsx:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import { render } from '@testing-library/react';
3 | import App from '../renderer/App';
4 |
5 | describe('App', () => {
6 | it('should render', () => {
7 | expect(render()).toBeTruthy();
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/src/renderer/interfaces/mainMessages.tsx:
--------------------------------------------------------------------------------
1 | import { ItemRow } from "./items"
2 |
3 | export interface MessageMain {
4 | command: number
5 | text: string
6 | returnValue: any
7 | }
8 |
9 | export interface MessageItems extends MessageMain {
10 | returnValue: ItemRow
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/src/renderer/interfaces/overview.tsx:
--------------------------------------------------------------------------------
1 | export interface OverviewOptionsBy {
2 | price: string
3 | volume: string
4 |
5 | }
6 |
7 | export interface OverviewOptionsLeftCharts {
8 | overall: string
9 | }
10 | export interface OverviewOptionsRightCharts {
11 | itemDistribution: string
12 | }
--------------------------------------------------------------------------------
/src/main/interfaces/mainInterfaces.tsx:
--------------------------------------------------------------------------------
1 |
2 | // Need-update
3 | export interface GithubResponse {
4 | version: number
5 | downloadLink: string
6 | }
7 | export interface UpdateReply {
8 | requireUpdate: boolean
9 | currentVersion: number
10 | githubResponse: GithubResponse
11 |
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/src/renderer/interfaces/store/authReducerActionsInterfaces.tsx:
--------------------------------------------------------------------------------
1 | import { WalletInterface } from "../states";
2 |
3 | export interface SignInActionPackage {
4 | displayName: string
5 | CSGOConnection: boolean
6 | userProfilePicture: string
7 | steamID: string
8 | wallet: WalletInterface
9 | }
10 |
--------------------------------------------------------------------------------
/.erb/scripts/link-modules.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import {
3 | appNodeModulesPath,
4 | srcNodeModulesPath,
5 | } from '../configs/webpack.paths';
6 |
7 | if (!fs.existsSync(srcNodeModulesPath) && fs.existsSync(appNodeModulesPath)) {
8 | fs.symlinkSync(appNodeModulesPath, srcNodeModulesPath, 'junction');
9 | }
10 |
--------------------------------------------------------------------------------
/.erb/scripts/delete-source-maps.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import rimraf from 'rimraf';
3 | import webpackPaths from '../configs/webpack.paths';
4 |
5 | export default function deleteSourceMaps() {
6 | rimraf.sync(path.join(webpackPaths.distMainPath, '*.js.map'));
7 | rimraf.sync(path.join(webpackPaths.distRendererPath, '*.js.map'));
8 | }
9 |
--------------------------------------------------------------------------------
/assets/assets.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint @typescript-eslint/no-explicit-any: off */
2 |
3 | declare module '*.svg' {
4 | const content: string;
5 | export default content;
6 | }
7 |
8 | declare module '*.png' {
9 | const content: string;
10 | export default content;
11 | }
12 |
13 | declare module '*.jpg' {
14 | const content: string;
15 | export default content;
16 | }
17 |
--------------------------------------------------------------------------------
/assets/entitlements.mac.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.cs.allow-unsigned-executable-memory
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/iconsLogo/minimize.tsx:
--------------------------------------------------------------------------------
1 | const TitleBarMinimize = (props) => (
2 |
12 | )
13 |
14 | export default TitleBarMinimize
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/iconsLogo/restore.tsx:
--------------------------------------------------------------------------------
1 | const TitleBarRestore = (props) => (
2 |
14 | )
15 |
16 | export default TitleBarRestore
--------------------------------------------------------------------------------
/.erb/scripts/check-node-env.js:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 |
3 | export default function checkNodeEnv(expectedEnv) {
4 | if (!expectedEnv) {
5 | throw new Error('"expectedEnv" not set');
6 | }
7 |
8 | if (process.env.NODE_ENV !== expectedEnv) {
9 | console.log(
10 | chalk.whiteBright.bgRed.bold(
11 | `"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config`
12 | )
13 | );
14 | process.exit(2);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/assets/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/categoryDistribution/categoriesRGB.tsx:
--------------------------------------------------------------------------------
1 | export const categoriesRGB = {
2 | characters: "rgba(255, 99, 132, 0.2)",
3 | status_icons: "rgba(153, 102, 255, 0.2)",
4 | weapon_cases: "rgba(54, 162, 235, 0.2)",
5 | patches: "rgba(99, 102, 241, 0.2)",
6 | music_kits: "rgba(107, 114, 128, 0.2)",
7 | default_generated: "rgba(75, 192, 192, 0.2)",
8 | stickers: "rgba(255, 206, 86, 0.2)",
9 | tools: "rgba(255, 159, 64, 0.2)"
10 | };
--------------------------------------------------------------------------------
/src/renderer/variables/overviewOptions.tsx:
--------------------------------------------------------------------------------
1 | import { OverviewOptionsBy, OverviewOptionsLeftCharts, OverviewOptionsRightCharts } from "renderer/interfaces/overview";
2 | export const OveviewBy: OverviewOptionsBy = {
3 | price: 'Price',
4 | volume: 'Volume'
5 | }
6 | export const OverviewRightCharts: OverviewOptionsRightCharts = {
7 | itemDistribution: 'Category'
8 | }
9 |
10 | export const OverviewLeftCharts: OverviewOptionsLeftCharts = {
11 | overall: 'Overall'
12 | }
--------------------------------------------------------------------------------
/.erb/scripts/clean.js:
--------------------------------------------------------------------------------
1 | import rimraf from 'rimraf';
2 | import webpackPaths from '../configs/webpack.paths.ts';
3 | import process from 'process';
4 |
5 | const args = process.argv.slice(2);
6 | const commandMap = {
7 | dist: webpackPaths.distPath,
8 | release: webpackPaths.releasePath,
9 | dll: webpackPaths.dllPath,
10 | };
11 |
12 | args.forEach((x) => {
13 | const pathToRemove = commandMap[x];
14 | if (pathToRemove !== undefined) {
15 | rimraf.sync(pathToRemove);
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/iconsLogo/close.tsx:
--------------------------------------------------------------------------------
1 | const TitleBarClose = (props) => (
2 |
17 | )
18 |
19 | export default TitleBarClose
--------------------------------------------------------------------------------
/.erb/scripts/check-port-in-use.js:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 | import detectPort from 'detect-port';
3 |
4 | const port = process.env.PORT || '1212';
5 |
6 | detectPort(port, (err, availablePort) => {
7 | if (port !== String(availablePort)) {
8 | throw new Error(
9 | chalk.whiteBright.bgRed.bold(
10 | `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 npm start`
11 | )
12 | );
13 | } else {
14 | process.exit(0);
15 | }
16 | });
17 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/iconsLogo/maximize.tsx:
--------------------------------------------------------------------------------
1 | const TitleBarMaximize = (props) => (
2 |
15 | )
16 |
17 | export default TitleBarMaximize
18 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 | /*
10 | # Coverage directory used by tools like istanbul
11 | coverage
12 | .eslintcache
13 |
14 | # Dependency directory
15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
16 | node_modules
17 |
18 | # OSX
19 | .DS_Store
20 |
21 | release/app/dist
22 | release/build
23 | .erb/dll
24 |
25 | .idea
26 | npm-debug.log.*
27 | *.css.d.ts
28 | *.sass.d.ts
29 | *.scss.d.ts
30 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/animations.tsx:
--------------------------------------------------------------------------------
1 | import { classNames } from "./filters/inventoryFunctions"
2 |
3 | export const LoadingButton = ({className=""}) => (
4 |
11 | );
12 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/QTYRow.tsx:
--------------------------------------------------------------------------------
1 |
2 | export function RowQTY({ itemRow }) {
3 |
4 | return (
5 | <>
6 |
7 |
8 |
9 | {itemRow.combined_QTY}
10 |
11 |
12 | |
13 | >
14 | );
15 | }
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/filters/transferAmount.tsx:
--------------------------------------------------------------------------------
1 | import { SwitchHorizontalIcon } from '@heroicons/react/solid';
2 |
3 | export default function TransferFilter({totalAmount}) {
4 | return (
5 |
6 | {' '}
10 |
11 | {totalAmount} Items
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/src/renderer/interfaces/filters.tsx:
--------------------------------------------------------------------------------
1 |
2 | export interface FilterRequirement {
3 | label: string
4 | valueToCheck: string
5 | commandType: 'checkBooleanVariable' | 'checkURL' | 'checkName' | 'checkMajor' | 'checkNameAndContainer' | 'checkCapsule'
6 | }
7 | export interface Filter extends FilterRequirement{
8 | include: boolean
9 | }
10 |
11 | export interface Filters {
12 | [key: string]: Array
13 | }
14 |
15 | export interface ClassOptionFilter {
16 | [key: string]: FilterRequirement
17 | }
18 |
19 | export interface FiltersRequirement {
20 | [key: string]: Array
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/helpers/classes/steam/inventoryManager.tsx:
--------------------------------------------------------------------------------
1 | // Sub interfaces
2 | interface itemRow {
3 | item_name: string
4 | item_customname: string | null
5 | item_url: string
6 | item_id: string
7 | position: number
8 | item_wear_name?: string
9 | item_paint_wear?: number
10 | item_origin: number
11 | item_moveable: boolean
12 | item_has_stickers: boolean
13 | equipped_ct: boolean
14 | equipped_t: boolean
15 | def_index: number
16 | stickers: Array
17 | rarity?: number
18 | rarityName: string
19 | tradeUp: boolean
20 | stattrak: boolean
21 | tradeUpConfirmed: boolean
22 | collection?: string
23 | }
24 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/rarities.tsx:
--------------------------------------------------------------------------------
1 | const itemRarities = [
2 | {
3 | value: 'Consumer Grade',
4 | bgColorClass: 'bg-blue-200',
5 | href: '#',
6 | },
7 | {
8 | value: 'Industrial Grade',
9 | bgColorClass: 'bg-blue-400',
10 | href: '#',
11 | },
12 | {
13 | value: 'Mil-Spec',
14 | bgColorClass: 'bg-blue-600',
15 | href: '#',
16 | },
17 | {
18 | value: 'Restricted',
19 | bgColorClass: 'bg-purple-500',
20 | href: '#',
21 | },
22 | {
23 | value: 'Classified',
24 | bgColorClass: 'bg-pink-500',
25 | href: '#',
26 | }
27 | ];
28 |
29 | export default itemRarities;
30 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | import colors from 'tailwindcss/colors';
2 |
3 | module.exports = {
4 | purge: [],
5 | darkMode: 'class', // or 'media' or 'class'
6 | theme: {
7 | fill: {
8 | current: 'currentColor',
9 | },
10 | extend: {
11 | colors: {
12 | 'dark-level-one': "#121212",
13 | 'dark-level-two': "#181818",
14 | 'dark-level-three': "#282828",
15 | 'dark-level-four': "#404040",
16 | 'dark-level-five': "#2B303D",
17 | 'dark-white': "#d6d3cd",
18 | 'regal-blue': '#243c5a',
19 | }
20 | },
21 | },
22 | variants: {
23 | extend: {},
24 | },
25 | plugins: [],
26 | };
27 |
--------------------------------------------------------------------------------
/src/main/util.ts:
--------------------------------------------------------------------------------
1 | /* eslint import/prefer-default-export: off, import/no-mutable-exports: off */
2 | import { URL } from 'url';
3 | import path from 'path';
4 |
5 | export let resolveHtmlPath: (htmlFileName: string) => string;
6 |
7 | if (process.env.NODE_ENV === 'development') {
8 | const port = process.env.PORT || 1212;
9 | resolveHtmlPath = (htmlFileName: string) => {
10 | const url = new URL(`http://localhost:${port}`);
11 | url.pathname = htmlFileName;
12 | return url.href;
13 | };
14 | } else {
15 | resolveHtmlPath = (htmlFileName: string) => {
16 | return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`;
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/rarityRow.tsx:
--------------------------------------------------------------------------------
1 | export function RowRarity({itemRow, settingsData}) {
2 |
3 | return (
4 | <>
5 |
6 | {settingsData.columns.includes('Rarity') ?
7 |
8 |
9 |
10 | {itemRow.rarityName}
11 |
12 |
13 | | : '' }
14 |
15 | >
16 | );
17 | }
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/storageRow.tsx:
--------------------------------------------------------------------------------
1 |
2 | export function RowStorage({itemRow, settingsData}) {
3 |
4 | return (
5 | <>
6 |
7 | {settingsData.columns.includes('Storage') ?
8 |
9 |
10 |
11 | {itemRow.storage_name}
12 |
13 |
14 | | : '' }
15 |
16 | >
17 | );
18 | }
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/tradeholdRow.tsx:
--------------------------------------------------------------------------------
1 |
2 | export function RowTradehold({itemRow, settingsData}) {
3 | const now = new Date();
4 |
5 | return (
6 | <>
7 |
8 | {settingsData.columns.includes('Tradehold') ?
9 |
10 | {itemRow.trade_unlock !== undefined
11 | ? Math.ceil(
12 | (itemRow.trade_unlock.getTime() - now.getTime()) /
13 | (1000 * 60 * 60 * 24)
14 | ) + ' days'
15 | : ''}
16 | | : ''}
17 |
18 | >
19 | );
20 | }
--------------------------------------------------------------------------------
/src/main/helpers/classes/steam/items/steam.js:
--------------------------------------------------------------------------------
1 | const { getUsername, setUsername } = require('../settings');
2 |
3 | async function isLoggedInElsewhere(userSession) {
4 | return new Promise((resolve) => {
5 | userSession.requestRichPresence(
6 | 730,
7 | [userSession.steamID],
8 | 'english',
9 | function (err, items) {
10 | err;
11 | if (typeof items !== 'undefined') {
12 | if (Object.keys(items['users']).length > 0) {
13 | resolve(true);
14 | } else {
15 | resolve(false);
16 | }
17 | }
18 | }
19 | );
20 | });
21 | }
22 |
23 | module.exports = {
24 | isLoggedInElsewhere
25 | };
26 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/floatRow.tsx:
--------------------------------------------------------------------------------
1 |
2 | export function RowFloat({itemRow, settingsData}) {
3 |
4 | return (
5 | <>
6 |
7 | {settingsData.columns.includes('Float') ?
8 |
9 |
10 |
11 | {itemRow.item_paint_wear?.toString()?.substr(0, 9)}
12 |
13 |
14 | | : '' }
15 |
16 | >
17 | );
18 | }
--------------------------------------------------------------------------------
/src/renderer/context/toMoveContext.tsx:
--------------------------------------------------------------------------------
1 | import { createContext, useContext } from 'react';
2 | export type toMoveContext = {
3 | getToMoveContext: any;
4 | setToMoveContext: (c: any) => void;
5 | };
6 |
7 | export const toMoveContext = createContext({
8 | getToMoveContext: {},
9 | setToMoveContext: () => {},
10 | });
11 | export const useToMoveContext = () => useContext(toMoveContext);
12 |
13 | export async function updateToMove(getToMoveContext, options) {
14 | let fromStorage = options.hasOwnProperty('fromStorage')
15 | ? options.fromStorage
16 | : getToMoveContext['fromStorage'];
17 | console.log(fromStorage);
18 | return {
19 | fromStorage: fromStorage,
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/helpers/classes/steam/items/getCommands.js:
--------------------------------------------------------------------------------
1 | var axios = require('axios');
2 | var items = require('./index');
3 |
4 | // RUN PROGRAMS
5 | class fetchItems {
6 | itemsClass = items;
7 | constructor() {
8 | this.itemsClass = new items();
9 | }
10 |
11 | async convertInventory(inventory) {
12 | const responseFiltered = this.itemsClass.inventoryConverter(
13 | inventory,
14 | false
15 | );
16 | return responseFiltered;
17 | }
18 | async convertStorageData(inventory) {
19 | const responseFiltered = this.itemsClass.inventoryConverter(
20 | inventory,
21 | true
22 | );
23 | return responseFiltered;
24 | }
25 | }
26 | module.exports = {
27 | fetchItems,
28 | };
29 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/collectionsRow.tsx:
--------------------------------------------------------------------------------
1 |
2 | export function RowCollections({ itemRow, settingsData }) {
3 | return (
4 | <>
5 | {settingsData.columns.includes('Collections') ?
6 |
7 |
8 |
9 |
10 |
11 | {itemRow?.collection?.replace('The ', '')?.replace(' Collection', '')}
12 |
13 |
14 |
15 |
16 |
17 | | : ''}
18 | >
19 | );
20 | }
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/filters/inventoryAmount.tsx:
--------------------------------------------------------------------------------
1 | import { ArchiveIcon } from '@heroicons/react/solid';
2 |
3 | export default function MoveLeft({totalAmount, textToWrite = "Left"}) {
4 | return (
5 |
6 | {' '}
10 |
11 | {totalAmount}{' '}
12 | {textToWrite}
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/helpers/classes/IPCGenerators/loginGenerator.tsx:
--------------------------------------------------------------------------------
1 | import { LoginCommand, LoginCommandReturnPackage, LoginOptions } from "shared/Interfaces.tsx/store";
2 |
3 | class LoginGenerator {
4 | returnValue: LoginCommand = {
5 | responseStatus: 'defaultError',
6 | returnPackage: {}
7 | }
8 |
9 | setResponseStatus(responseStatus: keyof LoginOptions) {
10 | this.returnValue.responseStatus = responseStatus
11 | }
12 | setEmptyPackage() {
13 | this.returnValue.returnPackage = {}
14 | }
15 |
16 | setPackage(returnPackage: LoginCommandReturnPackage) {
17 | this.returnValue.returnPackage = returnPackage
18 | }
19 |
20 | }
21 |
22 | module.exports = {
23 | LoginGenerator
24 | };
25 | export { LoginGenerator };
26 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/filters/accountAmount.tsx:
--------------------------------------------------------------------------------
1 | import { DatabaseIcon } from '@heroicons/react/solid';
2 |
3 | export default function AccountAmount({totalAmount, textToWrite = "Left"}) {
4 | return (
5 |
6 | {' '}
10 |
11 | {totalAmount}{' '}
12 | {textToWrite}
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/.erb/scripts/electron-rebuild.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import { execSync } from 'child_process';
3 | import fs from 'fs';
4 | import { dependencies } from '../../release/app/package.json';
5 | import webpackPaths from '../configs/webpack.paths';
6 |
7 | if (
8 | Object.keys(dependencies || {}).length > 0 &&
9 | fs.existsSync(webpackPaths.appNodeModulesPath)
10 | ) {
11 | const electronRebuildCmd =
12 | '../../node_modules/.bin/electron-rebuild --parallel --force --types prod,dev,optional --module-dir .';
13 | const cmd =
14 | process.platform === 'win32'
15 | ? electronRebuildCmd.replace(/\//g, '\\')
16 | : electronRebuildCmd;
17 | execSync(cmd, {
18 | cwd: webpackPaths.appPath,
19 | stdio: 'inherit',
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/src/renderer/store/helpers/globaloffensiveNotifications.tsx:
--------------------------------------------------------------------------------
1 | export const GCConnectionStatus = {
2 | HAVE_SESSION: 0,
3 | GC_GOING_DOWN: 1,
4 | NO_SESSION: 2,
5 | NO_SESSION_IN_LOGON_QUEUE: 3,
6 | NO_STEAM: 4
7 | };
8 |
9 |
10 | export const globalMessages = {
11 | NameItem: 1006,
12 | UnlockCrate: 1007,
13 | XRayItemReveal: 1008,
14 | XRayItemClaim: 1009,
15 | CasketTooFull: 1011,
16 | CasketContents: 1012,
17 | CasketAdded: 1013,
18 | CasketRemoved: 1014,
19 | CasketInvFull: 1015,
20 | NameBaseItem: 1019,
21 | RemoveItemName: 1030,
22 | RemoveSticker: 1053,
23 | ApplySticker: 1086,
24 | StatTrakSwap: 1088,
25 | ActivateFanToken: 9178,
26 | ActivateOperationCoin: 9179,
27 | GraffitiUnseal: 9185,
28 | GenerateSouvenir: 9204
29 | };
30 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/modalTrade.tsx:
--------------------------------------------------------------------------------
1 | export const setTradeMove = () => {
2 | return {
3 | type: 'TRADE_MODAL_OPEN_CLOSE',
4 | }
5 | }
6 | export const setTradeConfirm = (inven) => {
7 | return {
8 | type: 'TRADE_MODAL_CONFIRM',
9 | payload: {
10 | inventory: inven
11 | }
12 | }
13 | }
14 |
15 | export const setTradeReset = () => {
16 | return {
17 | type: 'TRADE_MODAL_RESET'
18 | }
19 | }
20 |
21 | export const setTradeFoundMatch = (matchRow) => {
22 | return {
23 | type: 'TRADE_MODAL_MATCH_FOUND',
24 | payload: {
25 | matchRow: matchRow
26 | }
27 | }
28 | }
29 | export const setTradeMoveResult = () => {
30 | return {
31 | type: 'TRADE_MODAL_OPEN_RESULT',
32 | }
33 | }
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryFilterSetup.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | characteristics,
3 | containers,
4 | FilterManager,
5 | } from 'renderer/functionsClasses/filters/filters';
6 |
7 | export function InventoryGetFilterManager() {
8 | const ClassFilters = new FilterManager();
9 | // Add characteristics
10 | Object.values(characteristics).forEach((filter) => {
11 |
12 | ClassFilters.addFilter('Include', filter, true);
13 | });
14 | Object.values(characteristics).forEach((filter) => {
15 |
16 | ClassFilters.addFilter('Exclude', filter, false);
17 | });
18 |
19 | // Add Containers
20 | Object.values(containers).forEach((filter) => {
21 |
22 | ClassFilters.addFilter('Containers', filter, true);
23 | });
24 |
25 | return ClassFilters;
26 | }
27 |
--------------------------------------------------------------------------------
/src/renderer/store/helpers/userStatusHelper.tsx:
--------------------------------------------------------------------------------
1 | import axios from "axios"
2 | import { createCSGOImage } from "../../functionsClasses/createCSGOImage";
3 | export async function getURL(steamID: string): Promise {
4 | let defaultReturnString = createCSGOImage("econ/characters/customplayer_tm_separatist")
5 | return new Promise((resolve) => {
6 | axios
7 | .get(`http://steamcommunity.com/profiles/${steamID}/?xml=1`)
8 | .then(function(response) {
9 | const parser = new DOMParser();
10 | resolve(parser?.parseFromString(response.data,"text/xml")?.getElementsByTagName("profile")[0]?.getElementsByTagName("avatarMedium")[0]?.childNodes[0]?.nodeValue || defaultReturnString
11 | )
12 | })
13 | }).catch(error => console.log(error));
14 | }
15 |
--------------------------------------------------------------------------------
/src/renderer/index.tsx:
--------------------------------------------------------------------------------
1 | import { render } from "react-dom";
2 | import { Provider } from "react-redux";
3 | import App from "./App";
4 | import { PersistGate } from 'redux-persist/integration/react'
5 | import returnVar from './store/configureStore'
6 |
7 | const myVar = returnVar()
8 |
9 |
10 | declare global {
11 | interface Window {
12 | electron: {
13 | store: {
14 | get: (key: string) => any;
15 | set: (key: string, val: any) => void;
16 | // any other methods you've defined...
17 | },
18 | ipcRenderer: any
19 | }
20 |
21 | }
22 | }
23 |
24 | render(
25 |
26 |
27 |
28 |
29 |
30 |
31 | , document.getElementById("root"));
--------------------------------------------------------------------------------
/.erb/scripts/check-build-exists.ts:
--------------------------------------------------------------------------------
1 | // Check if the renderer and main bundles are built
2 | import path from 'path';
3 | import chalk from 'chalk';
4 | import fs from 'fs';
5 | import webpackPaths from '../configs/webpack.paths';
6 |
7 | const mainPath = path.join(webpackPaths.distMainPath, 'main.js');
8 | const rendererPath = path.join(webpackPaths.distRendererPath, 'renderer.js');
9 |
10 | if (!fs.existsSync(mainPath)) {
11 | throw new Error(
12 | chalk.whiteBright.bgRed.bold(
13 | 'The main process is not built yet. Build it by running "npm run build:main"'
14 | )
15 | );
16 | }
17 |
18 | if (!fs.existsSync(rendererPath)) {
19 | throw new Error(
20 | chalk.whiteBright.bgRed.bold(
21 | 'The renderer process is not built yet. Build it by running "npm run build:renderer"'
22 | )
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/sign.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 |
3 | exports.default = async function(configuration) {
4 | // do not include passwords or other sensitive data in the file
5 | // rather create environment variables with sensitive data
6 | const TIMESTAMP = process.env.SIGNING_TIMESTAMP;
7 | const SIGNING_PATH = process.env.SIGNING_PATH;
8 | console.log("Signing with timestamp: " + TIMESTAMP);
9 | console.log("Signing path: " + SIGNING_PATH);
10 |
11 | require("child_process").execSync(
12 | // your commande here ! For exemple and with JSign :
13 | `signtool sign /tr ${TIMESTAMP} /td sha256 /fd sha256 /a "${configuration.path}"`,
14 | {cwd: SIGNING_PATH}
15 | );
16 |
17 | // Sleep for 5 seconds to allow the signing to complete
18 | await new Promise(resolve => setTimeout(resolve, 5000));
19 | };
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/filters/pricingAmount.tsx:
--------------------------------------------------------------------------------
1 | import { CashIcon } from '@heroicons/react/solid';
2 | import { classNames } from './inventoryFunctions';
3 |
4 | export default function PricingAmount({totalAmount, pricingAmount = 0, IconToUse = CashIcon, colorOf = "text-yellow-500"}) {
5 | return (
6 |
7 | {' '}
11 | {totalAmount}
12 | {pricingAmount == 0 ?
13 | '' :
14 | ( {pricingAmount} )
15 | }
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/src/shared/Interfaces.tsx/login.tsx:
--------------------------------------------------------------------------------
1 |
2 |
3 | export interface DispatchStoreBuildingObject {
4 | name: string
5 | action: Function
6 | }
7 | export type DispatchStoreHandleBuildingOptionsClass = {
8 | [key in keyof DispatchStoresettingsOptions]: DispatchStoreBuildingObject;
9 | }
10 |
11 | export interface DispatchStoresettingsOptions {
12 | locale: string
13 | os: string
14 | columns: string
15 | devmode: string
16 | currency: string
17 | steamLoginShow: string
18 | }
19 |
20 |
21 | // Store
22 | export interface DispatchIPCBuildingObject {
23 | endpoint: Function
24 | action: Function
25 | }
26 | export type DispatchIPCHandleBuildingOptionsClass = {
27 | [key in keyof DispatchIPCsettingsOptions]: DispatchIPCBuildingObject;
28 | }
29 |
30 | export interface DispatchIPCsettingsOptions {
31 | currency: string
32 | }
33 |
--------------------------------------------------------------------------------
/release/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "casemove",
3 | "productName": "casemove",
4 | "version": "2.3.7",
5 | "description": "Counter-Strike 2 Storage unit manager that helps you move stuff. ",
6 | "main": "./dist/main/main.js",
7 | "author": {
8 | "name": "Nombers",
9 | "email": "casemovenombers@gmail.com",
10 | "url": "https://github.com/nombersDev/casemove"
11 | },
12 | "scripts": {
13 | "electron-rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js",
14 | "link-modules": "node -r ts-node/register ../../.erb/scripts/link-modules.js",
15 | "postinstall": "npm run electron-rebuild && npm run link-modules"
16 | },
17 | "dependencies": {
18 | "globaloffensive": "^3.1.0",
19 | "steam-user": "^4.28.1",
20 | "steam-totp": "^2.1.1",
21 | "steam-session": "^1.1.1"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/renderer/store/configureStore.tsx:
--------------------------------------------------------------------------------
1 | // configureStore.js
2 |
3 | import { createStore } from 'redux'
4 | import { persistStore, persistReducer } from 'redux-persist'
5 | import storage from 'redux-persist/lib/storage' // defaults to localStorage for web
6 | import rootReducers from './reducer'
7 |
8 |
9 | const persistConfig = {
10 | key: 'root',
11 | storage,
12 | }
13 |
14 | const persistedReducer = persistReducer(persistConfig, rootReducers)
15 |
16 | export default () => {
17 | let reduxStore = createStore(persistedReducer)
18 | if (process.env.NODE_ENV === 'development') {
19 | reduxStore = createStore(persistedReducer,
20 | // @ts-ignore
21 | window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
22 | }
23 |
24 | let persistor = persistStore(reduxStore)
25 | return { reduxStore, persistor }
26 | }
--------------------------------------------------------------------------------
/src/renderer/store/inventory/inventoryInterfaces.tsx:
--------------------------------------------------------------------------------
1 | import { ItemRow } from "renderer/interfaces/items";
2 |
3 | // CONFIG
4 | export interface InventoryMethods {
5 | 'INVENTORY_SET_INVENTORY': string
6 | 'INVENTORY_STORAGES_ADD_TO': string
7 | 'INVENTORY_STORAGES_CLEAR_CASKET': string
8 | 'INVENTORY_STORAGES_SET_SORT_STORAGES': string
9 | 'INVENTORY_STORAGES_CLEAR_ALL': string
10 | 'MOVE_FROM_CLEAR': string
11 | 'SIGN_OUT': string
12 | }
13 |
14 | export type InventoryMatchingObject = {
15 | [reducerType in keyof InventoryMethods]: Function;
16 | };
17 |
18 | export interface ActionInterface {
19 | type: keyof InventoryMethods
20 | }
21 |
22 | // ACTIONS
23 | export interface SetInventory extends ActionInterface {
24 | payload: {
25 | inventory: Array
26 | combinedInventory: Array
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2021",
4 | "module": "commonjs",
5 | "lib": ["dom", "esnext"],
6 | "declaration": true,
7 | "declarationMap": true,
8 | "jsx": "react-jsx",
9 | "strict": true,
10 | "pretty": true,
11 | "sourceMap": true,
12 | "baseUrl": "./src",
13 | /* Additional Checks */
14 | "noUnusedLocals": true,
15 | "noUnusedParameters": true,
16 | "noImplicitReturns": true,
17 | "noFallthroughCasesInSwitch": true,
18 | /* Module Resolution Options */
19 | "moduleResolution": "node",
20 | "esModuleInterop": true,
21 | "allowSyntheticDefaultImports": true,
22 | "resolveJsonModule": true,
23 | "allowJs": true,
24 | "outDir": "release/app/dist",
25 | "noImplicitAny": false
26 | },
27 | "exclude": ["test", "release/build", "release/app/dist", ".erb/dll"]
28 | }
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Coverage directory used by tools like istanbul
11 | coverage
12 | .eslintcache
13 |
14 | # Dependency directory
15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
16 | node_modules
17 |
18 | # OSX
19 | .DS_Store
20 |
21 | release/app/dist
22 | release/build
23 | .erb/dll
24 | .env
25 |
26 | .idea
27 | npm-debug.log.*
28 | *.css.d.ts
29 | *.sass.d.ts
30 | *.scss.d.ts
31 | .DS_Store
32 | .DS_Store
33 | src/main/helpers/classes/dev/*
34 | src/renderer/views/purchase/*
35 | src/renderer/store/reducer/modalPurchase.tsx
36 | src/renderer/store/reducer/purchase.tsx
37 | src/renderer/components/content/shared/modals & notifcations/modalPurchase.tsx
38 | src/renderer/store/actions/modalPurchase Actions.tsx
39 | src/renderer/store/actions/purchaseActions.tsx
40 |
--------------------------------------------------------------------------------
/src/renderer/store/reducer/modalRename.tsx:
--------------------------------------------------------------------------------
1 | import { RenameModal } from "renderer/interfaces/states";
2 |
3 | const initialState: RenameModal = {
4 | renameOpen: false,
5 | modalPayload: {
6 | itemID: '',
7 | itemName: ''
8 | },
9 | };
10 |
11 | const modalRenameReducer = (state = initialState, action) => {
12 | switch (action.type) {
13 | case 'SET_RENAME_MODAL':
14 | return {
15 | ...state,
16 | renameOpen: true,
17 | modalPayload: action.payload
18 | }
19 | case 'CLOSE_RENAME_MODAL':
20 | return {
21 | ...state,
22 | renameOpen: false
23 | }
24 | case 'SIGN_OUT':
25 | return {
26 | ...initialState
27 | }
28 | default:
29 | return {...state}
30 |
31 | }
32 | };
33 |
34 |
35 | export default modalRenameReducer;
36 |
--------------------------------------------------------------------------------
/src/renderer/components/content/storageUnits/to/toFilterSetup.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | characteristics,
3 | containers,
4 | FilterManager,
5 | } from 'renderer/functionsClasses/filters/filters';
6 |
7 | export function toGetFilterManager() {
8 | const ClassFilters = new FilterManager();
9 | // Add characteristics
10 | Object.values(characteristics).forEach((filter) => {
11 | if (filter.label != 'Storage moveable') {
12 | ClassFilters.addFilter('Include', filter, true);
13 | }
14 | });
15 |
16 | // Add characteristics
17 | Object.values(characteristics).forEach((filter) => {
18 | if (filter.label != 'Storage moveable') {
19 | ClassFilters.addFilter('Exclude', filter, false);
20 | }
21 | });
22 | // Add Containers
23 | Object.values(containers).forEach((filter) => {
24 |
25 | ClassFilters.addFilter('Containers', filter, true);
26 | });
27 | return ClassFilters;
28 | }
29 |
--------------------------------------------------------------------------------
/src/renderer/components/content/storageUnits/from/fromFilterSetup.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | characteristics,
3 | containers,
4 | FilterManager,
5 | } from 'renderer/functionsClasses/filters/filters';
6 |
7 | export function fromGetFilterManager() {
8 | const ClassFilters = new FilterManager();
9 | // Add characteristics
10 | Object.values(characteristics).forEach((filter) => {
11 | if (filter.label != 'Storage moveable') {
12 | ClassFilters.addFilter('Include', filter, true);
13 | }
14 | });
15 |
16 | // Add characteristics
17 | Object.values(characteristics).forEach((filter) => {
18 | if (filter.label != 'Storage moveable') {
19 | ClassFilters.addFilter('Exclude', filter, false);
20 | }
21 | });
22 | // Add Containers
23 | Object.values(containers).forEach((filter) => {
24 |
25 | ClassFilters.addFilter('Containers', filter, true);
26 | });
27 | return ClassFilters;
28 | }
29 |
--------------------------------------------------------------------------------
/src/renderer/components/content/storageUnits/from/Content.tsx:
--------------------------------------------------------------------------------
1 | import { HashRouter as Router, Route } from 'react-router-dom';
2 | import FromMainComponent from './fromHolder';
3 |
4 | function StorageUnits() {
5 | return (
6 | <>
7 | {/* Page title & actions */}
8 |
9 |
10 |
11 | Transfer from storage units
12 |
13 |
14 |
15 |
16 | >
17 | );
18 | }
19 |
20 | export default function StorageUnitsComponent() {
21 | return (
22 |
23 |
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/reducerManager.tsx:
--------------------------------------------------------------------------------
1 | const names = {
2 | userdetails: 'authReducer',
3 | inventory: 'inventoryReducer',
4 | inventoryFilters: 'inventoryFiltersReducer',
5 | modalMove: 'modalMoveReducer',
6 | modalRename: 'modalRenameReducer',
7 | moveFrom: 'moveFromReducer',
8 | moveTo: 'moveToReducer',
9 | settings: 'settingsReducer',
10 | pricing: 'pricingReducer',
11 | tradeUp: 'tradeUpReducer',
12 | modalTrade: 'modalTradeReducer'
13 | }
14 |
15 | export class ReducerManager{
16 |
17 | useSelector: Function
18 | names = names
19 | preExising: any = {}
20 |
21 | constructor(useSelector: Function) {
22 | this.useSelector = useSelector
23 | }
24 |
25 | getStorage(namesOption?: string) {
26 |
27 | if (namesOption == undefined) {
28 | return this.useSelector((state: any) => state);
29 | }
30 | return this.useSelector((state: any) => state[namesOption]);
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/renderer/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Casemove
7 |
8 |
27 |
28 |
29 |
30 |
38 |
39 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: 'erb',
3 | rules: {
4 | // A temporary hack related to IDE not resolving correct package.json
5 | 'import/no-extraneous-dependencies': 'off',
6 | // Since React 17 and typescript 4.1 you can safely disable the rule
7 | 'react/react-in-jsx-scope': 'off',
8 | },
9 | parserOptions: {
10 | ecmaVersion: 2020,
11 | sourceType: 'module',
12 | project: './tsconfig.json',
13 | tsconfigRootDir: __dirname,
14 | createDefaultProgram: true,
15 | },
16 | settings: {
17 | 'import/resolver': {
18 | // See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
19 | node: {},
20 | webpack: {
21 | config: require.resolve('./.erb/configs/webpack.config.eslint.ts'),
22 | },
23 | },
24 | 'import/parsers': {
25 | '@typescript-eslint/parser': ['.ts', '.tsx'],
26 | },
27 | },
28 | };
29 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/emptyState.tsx:
--------------------------------------------------------------------------------
1 | export default function EmptyComponent() {
2 | return (
3 |
4 |
19 |
Nothing here
20 |
21 | Expecting something here? Try the reload button or hide toogle.
22 |
23 |
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/rightGraph.tsx:
--------------------------------------------------------------------------------
1 | import { useSelector } from "react-redux";
2 | import { ReducerManager } from "renderer/functionsClasses/reducerManager";
3 | import { Settings } from "renderer/interfaces/states";
4 | import EmptyField from "./EmptyField";
5 | import ItemDistributionByVolume from "./categoryDistribution/categoryDistribution";
6 |
7 | export default function RightGraph() {
8 | let ReducerClass = new ReducerManager(useSelector);
9 | let settingsData: Settings = ReducerClass.getStorage(ReducerClass.names.settings)
10 |
11 | let by = settingsData.overview.by
12 | let right = settingsData.overview.chartRight
13 |
14 | let returnObject = {
15 | itemDistribution: ItemDistributionByVolume
16 | }
17 |
18 | let Fitting = returnObject[right]
19 | if (Fitting == undefined) {
20 | Fitting = EmptyField
21 | }
22 | console.log(by)
23 |
24 |
25 |
26 |
27 |
28 | return (
29 | <>
30 |
31 | >
32 | );
33 | }
34 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/userStatsActions.tsx:
--------------------------------------------------------------------------------
1 | import { SignInActionPackage } from "renderer/interfaces/store/authReducerActionsInterfaces"
2 |
3 |
4 |
5 | export const signIn = (forwardPackage: SignInActionPackage) => {
6 | return {
7 | type: 'SIGN_IN',
8 | payload: forwardPackage
9 | }
10 | }
11 |
12 | export const signOut = () => {
13 | return {
14 | type: 'SIGN_OUT'
15 | }
16 | }
17 |
18 | export const setConnection = (connectionStatus: boolean) => {
19 | return {
20 | type: 'SET_CONNECTION',
21 | payload: {
22 | hasConnection: connectionStatus
23 | }
24 | }
25 | }
26 | export const setWalletBalance = (walletBalance) => {
27 | return {
28 | type: 'SET_WALLET_BALANCE',
29 | payload: walletBalance
30 | }
31 | }
32 | export const setGC = (connectionStatus: boolean) => {
33 | return {
34 | type: 'SET_GC',
35 | payload: {
36 | CSGOConnection: connectionStatus
37 | }
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/.erb/scripts/notarize.js:
--------------------------------------------------------------------------------
1 | const { notarize } = require('electron-notarize');
2 | const { build } = require('../../package.json');
3 | exports.default = async function notarizeMacos(context) {
4 | const { electronPlatformName, appOutDir } = context;
5 | if (electronPlatformName !== 'darwin') {
6 | return;
7 | }
8 | require('dotenv').config();
9 |
10 | if (process.env.CI !== "true") {
11 | console.warn('Skipping notarizing step. Packaging is not running in CI');
12 | return;
13 | }
14 |
15 | if (!('APPLE_ID' in process.env && 'APPLE_ID_PASS' in process.env)) {
16 | console.warn('Skipping notarizing step. APPLE_ID and APPLE_ID_PASS env variables must be set');
17 | return;
18 | }
19 |
20 | const appName = context.packager.appInfo.productFilename;
21 |
22 | await notarize({
23 | appBundleId: build.appId,
24 | appPath: `${appOutDir}/${appName}.app`,
25 | appleId: process.env.APPLE_ID,
26 | appleIdPassword: process.env.APPLE_ID_PASS,
27 | teamId: process.env.APPLE_TEAM_ID,
28 | });
29 | };
30 |
--------------------------------------------------------------------------------
/src/renderer/interfaces/items.tsx:
--------------------------------------------------------------------------------
1 |
2 | export interface ItemRow {
3 | item_name: string
4 | item_customname: string | null
5 | item_url: string
6 | item_id: string
7 | position: number
8 | item_wear_name: string
9 | item_paint_wear?: number
10 | item_origin: number
11 | item_moveable: boolean
12 | item_has_stickers: boolean
13 | equipped_ct: boolean
14 | equipped_t: boolean
15 | def_index: number
16 | stickers: Array
17 | rarity: number
18 | rarityName: string
19 | tradeUp: boolean
20 | stattrak: boolean
21 | tradeUpConfirmed: boolean
22 | collection: string
23 | combined_ids: Array
24 | combined_QTY: number
25 | bgColorClass: string
26 | category: string
27 | major: string
28 | storage_id: string
29 | item_storage_total: number
30 | percentage: number
31 | }
32 |
33 | export interface ItemRowStorage extends ItemRow {
34 | storage_id: string
35 | item_storage_total: number
36 | storage_name: string
37 | }
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/leftGraph.tsx:
--------------------------------------------------------------------------------
1 | import { useSelector } from "react-redux";
2 | import { ReducerManager } from "renderer/functionsClasses/reducerManager";
3 | import { Settings } from "renderer/interfaces/states";
4 | import EmptyField from "./EmptyField";
5 | import OverallVolume from "./leftGraph/barChartOverall";
6 |
7 | export default function LeftGraph() {
8 | let ReducerClass = new ReducerManager(useSelector);
9 | let settingsData: Settings = ReducerClass.getStorage(ReducerClass.names.settings)
10 |
11 | let by = settingsData.overview.by
12 | let left = settingsData.overview.chartleft
13 |
14 | let returnObject = {
15 | overall: {
16 | volume: OverallVolume,
17 | price: OverallVolume
18 | }
19 | }
20 |
21 | let Fitting = returnObject[left][by]
22 | if (Fitting == undefined) {
23 | Fitting = EmptyField
24 | }
25 | console.log(Fitting)
26 |
27 |
28 |
29 |
30 |
31 | return (
32 | <>
33 |
34 | >
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/pricingActions.tsx:
--------------------------------------------------------------------------------
1 | import { ItemRow } from "renderer/interfaces/items"
2 |
3 | export const pricing_addPrice = (itemRows) => {
4 | return {
5 | type: 'PRICING_ADD_TO',
6 | payload: {
7 | itemRows: itemRows
8 | }
9 | }
10 | }
11 | export const pricing_removePrice = (priceResult, itemName) => {
12 | return {
13 | type: 'PRICING_REMOVE',
14 | payload: {
15 | price: priceResult,
16 | itemName: itemName
17 | }
18 | }
19 | }
20 | export const pricing_add_storage_total = (amountToAdd) => {
21 | return {
22 | type: 'PRICING_ADD_STORAGE_TOTAL',
23 | payload: {
24 | storageAmount: amountToAdd
25 | }
26 | }
27 | }
28 |
29 | export const pricing_add_to_requested = (itemRows: Array) => {
30 | return {
31 | type: 'PRICING_ADD_TO_REQUESTED',
32 | payload: {
33 | itemRows: itemRows
34 | }
35 | }
36 | }
37 | export const pricing_clearAll = () => {
38 | return {
39 | type: 'PRICING_CLEAR'
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/functions.tsx:
--------------------------------------------------------------------------------
1 |
2 |
3 | import { State } from "renderer/interfaces/states";
4 | import { inventorySetSortStorage } from "renderer/store/inventory/inventoryActions";
5 | import { SetSortOption } from "renderer/store/actions/moveFromActions";
6 | import { sortDataFunction } from "../../shared/filters/inventoryFunctions";
7 |
8 | export async function onSortChange(dispatch: Function, sortValue: string, currentState: State) {
9 | dispatch(SetSortOption(sortValue));
10 | const storageResult = await sortDataFunction(
11 | sortValue,
12 | currentState.inventoryReducer.storageInventory,
13 | currentState.pricingReducer.prices, currentState.settingsReducer?.source?.title
14 | );
15 | const storageResultFiltered = await sortDataFunction(
16 | sortValue,
17 | currentState.inventoryFiltersReducer.storageFiltered,
18 | currentState.pricingReducer.prices, currentState.settingsReducer?.source?.title
19 | );
20 | dispatch(inventorySetSortStorage(storageResult, storageResultFiltered));
21 | }
22 |
--------------------------------------------------------------------------------
/src/shared/Interfaces.tsx/store.tsx:
--------------------------------------------------------------------------------
1 | import { ItemRow } from "renderer/interfaces/items";
2 | import { WalletInterface } from "renderer/interfaces/states";
3 |
4 | export interface LoginCommandReturnPackage {
5 | steamID: string
6 | displayName: string
7 | haveGCSession: boolean
8 | csgoInventory: Array
9 | walletToSend: WalletInterface
10 | }
11 | export interface LoginCommand {
12 | responseStatus: keyof LoginOptions,
13 | returnPackage: {} | LoginCommandReturnPackage
14 | }
15 |
16 | export type HandleLoginObjectClass = {
17 | [key in keyof LoginOptions]: Function;
18 | }
19 |
20 | export interface LoginNotification {
21 | success: boolean
22 | title: string
23 | text: string
24 | }
25 |
26 | export interface LoginOptions {
27 | loggedIn: string,
28 | steamGuardError: string,
29 | steamGuardCodeIncorrect: string
30 | defaultError: string
31 | playingElsewhere: string
32 | wrongLoginToken: string
33 | webtokenNotJSON: string
34 | webtokenNotLoggedIn: string
35 | }
36 |
37 | export type LoginNotificationObject = {
38 | [key in keyof LoginOptions]: LoginNotification;
39 | };
40 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/moveableRow.tsx:
--------------------------------------------------------------------------------
1 | import { CheckCircleIcon } from "@heroicons/react/solid";
2 |
3 | export function RowMoveable({itemRow, settingsData}) {
4 |
5 | return (
6 | <>
7 | {settingsData.columns.includes('Moveable') ? (
8 |
12 |
13 | {itemRow.item_moveable == true ? (
14 |
18 | ) : (
19 | ''
20 | )}
21 |
22 | |
23 | ) : (
24 | ''
25 | )}
26 |
27 | >
28 | );
29 | }
--------------------------------------------------------------------------------
/src/renderer/store/reducer/index.tsx:
--------------------------------------------------------------------------------
1 | import { combineReducers } from "redux";
2 | // import inventoryReducer from "../inventory/inventoryReducer";
3 | import authReducer from "./userStatus";
4 | import inventoryFiltersReducer from './inventoryFiltersRed'
5 | import modalMoveReducer from './modalMove'
6 | import modalRenameReducer from './modalRename'
7 | import moveFromReducer from './moveFromReducers'
8 | import moveToReducer from './moveToReducers'
9 | import settingsReducer from "./settings";
10 | import pricingReducer from "./pricing";
11 | import tradeUpReducer from "./tradeupReducer";
12 | import modalTradeReducer from './modalTrade'
13 | import { inventoryReducer } from "../inventory/inventoryClass";
14 |
15 | const rootReducers = combineReducers({
16 | authReducer,
17 | inventoryReducer,
18 | inventoryFiltersReducer,
19 | modalMoveReducer,
20 | modalRenameReducer,
21 | moveFromReducer,
22 | moveToReducer,
23 | settingsReducer,
24 | pricingReducer,
25 | tradeUpReducer,
26 | modalTradeReducer
27 | })
28 |
29 | export default rootReducers;
30 |
31 | export type RootState = ReturnType
32 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/EmptyField.tsx:
--------------------------------------------------------------------------------
1 | /* This example requires Tailwind CSS v2.0+ */
2 | export default function EmptyField() {
3 | return (
4 |
25 | )
26 | }
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.base.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Base webpack config used across other specific configs
3 | */
4 |
5 | import webpack from 'webpack';
6 | import webpackPaths from './webpack.paths';
7 | import { dependencies as externals } from '../../release/app/package.json';
8 |
9 | export default {
10 | externals: [...Object.keys(externals || {})],
11 |
12 | stats: 'errors-only',
13 |
14 | module: {
15 | rules: [
16 | {
17 | test: /\.[jt]sx?$/,
18 | exclude: /node_modules/,
19 | use: {
20 | loader: 'ts-loader',
21 | },
22 | },
23 | ],
24 | },
25 |
26 | output: {
27 | path: webpackPaths.srcPath,
28 | // https://github.com/webpack/webpack/issues/1114
29 | library: {
30 | type: 'commonjs2',
31 | },
32 | },
33 |
34 | /**
35 | * Determine the array of extensions that should be used to resolve modules.
36 | */
37 | resolve: {
38 | extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
39 | modules: [webpackPaths.srcPath, 'node_modules'],
40 | },
41 |
42 | plugins: [
43 | new webpack.EnvironmentPlugin({
44 | NODE_ENV: 'production',
45 | }),
46 | ],
47 | };
48 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.paths.ts:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const rootPath = path.join(__dirname, '../..');
4 |
5 | const dllPath = path.join(__dirname, '../dll');
6 |
7 | const srcPath = path.join(rootPath, 'src');
8 | const srcMainPath = path.join(srcPath, 'main');
9 | const srcRendererPath = path.join(srcPath, 'renderer');
10 |
11 | const releasePath = path.join(rootPath, 'release');
12 | const appPath = path.join(releasePath, 'app');
13 | const appPackagePath = path.join(appPath, 'package.json');
14 | const appNodeModulesPath = path.join(appPath, 'node_modules');
15 | const srcNodeModulesPath = path.join(srcPath, 'node_modules');
16 |
17 | const distPath = path.join(appPath, 'dist');
18 | const distMainPath = path.join(distPath, 'main');
19 | const distRendererPath = path.join(distPath, 'renderer');
20 |
21 | const buildPath = path.join(releasePath, 'build');
22 |
23 | export default {
24 | rootPath,
25 | dllPath,
26 | srcPath,
27 | srcMainPath,
28 | srcRendererPath,
29 | releasePath,
30 | appPath,
31 | appPackagePath,
32 | appNodeModulesPath,
33 | srcNodeModulesPath,
34 | distPath,
35 | distMainPath,
36 | distRendererPath,
37 | buildPath,
38 | };
39 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/inventoryLinkRow.tsx:
--------------------------------------------------------------------------------
1 | import { ExternalLinkIcon } from "@heroicons/react/solid";
2 | import { Link } from "react-router-dom";
3 |
4 | export function RowLinkInventory({ itemRow, settingsData, userDetails }) {
5 |
6 | return (
7 | <>
8 | {settingsData.columns.includes('Inventory link') ? (
9 |
13 |
14 |
20 |
24 |
25 |
26 | |
27 | ) : (
28 | ''
29 | )}
30 |
31 | >
32 | );
33 | }
--------------------------------------------------------------------------------
/src/renderer/store/actions/tradeUpActions.tsx:
--------------------------------------------------------------------------------
1 |
2 | export const tradeUpAddRemove = (productRow) => {
3 | return {
4 | type: 'TRADEUP_ADD_REMOVE',
5 | payload: productRow
6 | }
7 | }
8 |
9 | export const tradeUpSetPossible = (productRow) => {
10 | return {
11 | type: 'TRADEUP_SET_POSSIBLE',
12 | payload: productRow
13 | }
14 | }
15 |
16 | export const tradeUpResetPossible = () => {
17 | return {
18 | type: 'TRADEUP_RESET'
19 | }
20 | }
21 |
22 | export const tradeUpSetSearch = (searchField) => {
23 | return {
24 | type: 'TRADEUP_SET_SEARCH',
25 | payload: {
26 | searchField: searchField
27 | }
28 | }
29 | }
30 |
31 | export const tradeUpSetMin = (min) => {
32 | return {
33 | type: 'TRADEUP_SET_MIN',
34 | payload: min
35 | }
36 | }
37 | export const tradeUpSetMax = (max) => {
38 | return {
39 | type: 'TRADEUP_SET_MAX',
40 | payload: max
41 | }
42 | }
43 | export const tradeUpCollectionsAddRemove = (collection) => {
44 | return {
45 | type: 'TRADEUP_ADDREMOVE_COLLECTION',
46 | payload: collection
47 | }
48 | }
49 |
50 | export const tradeUpOptionsAddRemove = (option) => {
51 | return {
52 | type: 'TRADEUP_ADDREMOVE_OPTION',
53 | payload: option
54 | }
55 | }
--------------------------------------------------------------------------------
/src/renderer/store/inventory/inventoryActions.tsx:
--------------------------------------------------------------------------------
1 | import { SetInventory } from "./inventoryInterfaces"
2 |
3 | export const setInventoryAction = (forwardPackage: any): SetInventory => {
4 | return {
5 | type: 'INVENTORY_SET_INVENTORY',
6 | payload: {
7 | inventory: forwardPackage.inventory,
8 | combinedInventory: forwardPackage.combinedInventory
9 | }
10 | }
11 | }
12 |
13 | export const addStorageInventoryData = (storageRowsRaw, storageData, casketID, sortValue) => {
14 | return {
15 | type: 'INVENTORY_STORAGES_ADD_TO',
16 | payload: {
17 | storageRowsRaw: storageRowsRaw,
18 | storageData: storageData,
19 | casketID: casketID,
20 | sortValue: sortValue
21 | }
22 | }
23 | }
24 |
25 | export const inventorySetSortStorage = (storageData, storageFiltered) => {
26 | return {
27 | type: 'INVENTORY_STORAGES_SET_SORT_STORAGES',
28 | payload: {
29 | storageData,
30 | storageFiltered
31 | }
32 | }
33 | }
34 |
35 | export const clearStorageIDData = (casketID) => {
36 | return {
37 | type: 'INVENTORY_STORAGES_CLEAR_CASKET',
38 | payload: {
39 | casketID: casketID
40 | }
41 | }
42 | }
43 |
44 | export const clearStorage = () => {
45 | return {
46 | type: 'INVENTORY_STORAGES_CLEAR_ALL'
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/modalMove actions.tsx:
--------------------------------------------------------------------------------
1 | export const setRenameModal = (itemID, itemName) => {
2 | return {
3 | type: 'SET_RENAME_MODAL',
4 | payload: {
5 | itemID: itemID,
6 | itemName: itemName
7 | }
8 | }
9 | }
10 |
11 | export const closeRenameModal = () => {
12 | return {
13 | type: 'CLOSE_RENAME_MODAL'
14 | }
15 | }
16 |
17 |
18 | export const moveModalQuerySet = (queryList) => {
19 | return {
20 | type: 'MOVE_MODAL_QUERY_SET',
21 | payload: {
22 | query: queryList
23 | }
24 | }
25 | }
26 | export const modalResetStorageIdsToClearFrom = () => {
27 | return {
28 | type: 'MODAL_RESET_STORAGE_IDS_TO_CLEAR_FROM'
29 | }
30 | }
31 | export const closeMoveModal = () => {
32 | return {
33 | type: 'CLOSE_MOVE_MODAL'
34 | }
35 | }
36 |
37 | export const cancelModal = (key) => {
38 | return {
39 | type: 'MOVE_MODAL_CANCEL',
40 | payload: {
41 | doCancel: key
42 | }
43 | }
44 | }
45 |
46 | export const moveModalAddToFail = () => {
47 | return {
48 | type: 'MODAL_ADD_TO_FAILED',
49 | }
50 | }
51 |
52 |
53 | export const moveModalUpdate = () => {
54 | return {
55 | type: 'MOVE_MODAL_UPDATE'
56 | }
57 | }
58 |
59 | export const moveModalResetPayload = () => {
60 | return {
61 | type: 'MOVE_MODAL_RESET_PAYLOAD'
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/priceRow.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { ConvertPricesFormatted } from "renderer/functionsClasses/prices";
3 |
4 |
5 | export function RowPrice({itemRow, settingsData, pricesReducer}) {
6 | const PricesClass = new ConvertPricesFormatted(settingsData, pricesReducer)
7 | const price = PricesClass.getPrice(itemRow)
8 | const formattedPrice = PricesClass.getFormattedPrice(itemRow)
9 | const formattedPriceCombined = PricesClass.getFormattedPriceCombined(itemRow)
10 |
11 | return (
12 | <>
13 |
14 | {settingsData.columns.includes('Price') ?
15 |
16 |
17 |
18 | {formattedPriceCombined}
19 |
20 |
21 |
22 |
23 | {!price
24 | ? ''
25 | : itemRow.combined_QTY == 1
26 | ? ''
27 | : formattedPrice}
28 |
29 |
30 | | : '' }
31 |
32 | >
33 | );
34 | }
--------------------------------------------------------------------------------
/src/renderer/store/handleMessage.tsx:
--------------------------------------------------------------------------------
1 |
2 | // 1: Inventory changed
3 | // 2: User log in / log out
4 | // 3: CSGO Connection
5 |
6 | import combineInventory from "renderer/components/content/shared/filters/inventoryFunctions"
7 | import { setInventoryAction } from "./inventory/inventoryActions"
8 | import { setConnection, setGC, signOut, setWalletBalance } from "./actions/userStatsActions"
9 |
10 | export async function handleLogonSuccess(message) {
11 | console.log(message)
12 | }
13 |
14 | export async function handleUserEvent(message, settings) {
15 | const statusCode = message[0]
16 | const description = message[1]
17 | switch (statusCode) {
18 | case 1:
19 | const subMessage = message[2]
20 | return setInventoryAction({inventory: subMessage[1], combinedInventory: await combineInventory(subMessage[1], settings)})
21 |
22 | case 2:
23 | if (description == 'disconnected') {
24 | return setConnection(false)
25 | }
26 | if (description == 'reconnected') {
27 | return setConnection(true)
28 | }
29 | if (description == 'fatalError') {
30 | return signOut()
31 | }
32 | return
33 |
34 | case 3:
35 | if (description == 'disconnectedFromGC') {
36 | return setGC(false)
37 | } else {
38 | return setGC(true)
39 | }
40 | case 4:
41 | return setWalletBalance(description)
42 | default:
43 | return
44 |
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/renderer/store/reducer/modalTrade.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { ModalTrade } from "renderer/interfaces/states";
3 |
4 | const initialState: ModalTrade = {
5 | moveOpen: false,
6 | openResult: false,
7 | inventoryFirst: [],
8 | rowToMatch: {}
9 | };
10 |
11 | const modalTradeReducer = (state = initialState, action) => {
12 | switch (action.type) {
13 | case 'TRADE_MODAL_OPEN_CLOSE':
14 | return {
15 | ...state,
16 | moveOpen: !state.moveOpen
17 | }
18 | case 'TRADE_MODAL_CONFIRM':
19 | return {
20 | ...state,
21 | moveOpen: false,
22 | inventoryFirst: action.payload.inventory
23 | }
24 |
25 | case 'TRADE_MODAL_MATCH_FOUND':
26 | return {
27 | ...state,
28 | openResult: true,
29 | inventoryFirst: initialState.inventoryFirst,
30 | rowToMatch: action.payload.matchRow
31 | }
32 | case 'TRADE_MODAL_RESET':
33 | return {
34 | ...initialState
35 | }
36 | case 'TRADE_MODAL_OPEN_RESULT':
37 | if (state.moveOpen == true) {
38 | return {
39 | ...state,
40 | moveOpen: false,
41 | openResult: !state.openResult
42 | }
43 | }
44 | return {
45 | ...state,
46 | openResult: !state.openResult
47 | }
48 |
49 |
50 |
51 | case 'SIGN_OUT':
52 | return {
53 | ...initialState
54 | }
55 | default:
56 | return {...state}
57 |
58 | }
59 | };
60 |
61 |
62 | export default modalTradeReducer;
63 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/settings.tsx:
--------------------------------------------------------------------------------
1 | import { Overview } from "renderer/interfaces/states"
2 | import { CurrencyReturnValue } from "shared/Interfaces.tsx/IPCReturn"
3 |
4 | export const setColumns = (valueToSet) => {
5 | return {
6 | type: 'SETTINGS_SET_COLUMNS',
7 | payload: valueToSet
8 | }
9 | }
10 | export const setCurrencyValue = (valueToSet) => {
11 | return {
12 | type: 'SETTINGS_SET_CURRENCY',
13 | payload: valueToSet
14 | }
15 | }
16 | export const setLocale = (valueToSet) => {
17 | return {
18 | type: 'SETTINGS_SET_LOCALE',
19 | payload: valueToSet
20 | }
21 | }
22 | export const setSourceValue = (valueToSet) => {
23 | return {
24 | type: 'SETTINGS_SET_SOURCE',
25 | payload: valueToSet
26 | }
27 | }
28 | export const setCurrencyRate = (returnPackage: CurrencyReturnValue) => {
29 | return {
30 | type: 'SETTINGS_ADD_CURRENCYPRICE',
31 | payload: {
32 | currency: returnPackage.currency,
33 | rate: returnPackage.rate
34 | }
35 | }
36 | }
37 | export const setOS = (os) => {
38 | return {
39 | type: 'SETTINGS_SET_OS',
40 | payload: os
41 | }
42 | }
43 | export const setSteamLoginShow = (loginShow) => {
44 | return {
45 | type: 'SETTINGS_SET_STEAMLOGINSHOW',
46 | payload: loginShow
47 | }
48 | }
49 | export const setDevmode = (devmode) => {
50 | return {
51 | type: 'SETTINGS_SET_DEVMODE',
52 | payload: devmode
53 | }
54 | }
55 | export const setOverview = (newObject: Overview) => {
56 | return {
57 | type: 'SETTINGS_SET_OVERVIEW',
58 | payload: newObject
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/helpers/login/loginRegular.tsx:
--------------------------------------------------------------------------------
1 | import { EAuthTokenPlatformType, LoginSession } from 'steam-session';
2 | import { StartLoginSessionWithCredentialsDetails } from 'steam-session/dist/interfaces-external';
3 | import { LoginOptions } from '../../../shared/Interfaces.tsx/store';
4 | import { storeRefreshToken } from '../classes/steam/settings';
5 |
6 | export async function flowLoginRegular(
7 | loginDetails: StartLoginSessionWithCredentialsDetails,
8 | doStoreLogin: boolean
9 | ): Promise<{
10 | responseStatus: keyof LoginOptions;
11 | refreshToken?: string;
12 | }> {
13 | return new Promise(async (resolve) => {
14 | let session = new LoginSession(EAuthTokenPlatformType.SteamClient);
15 | session.on('authenticated', async () => {
16 | console.log(
17 | `Logged into Steam as authenticated - ${session.accountName}`
18 | );
19 |
20 | if (doStoreLogin) {
21 | storeRefreshToken(session.accountName, session.refreshToken);
22 | }
23 |
24 | resolve({
25 | responseStatus: 'loggedIn',
26 | refreshToken: session.refreshToken,
27 | });
28 | });
29 |
30 | session.once('timeout', () => {
31 | resolve({
32 | responseStatus: 'defaultError',
33 | });
34 | });
35 |
36 | session.once('error', (err) => {
37 | console.log('Error', err);
38 | resolve({
39 | responseStatus: 'defaultError',
40 | });
41 | });
42 | try {
43 | await session.startWithCredentials(loginDetails);
44 | } catch (e) {
45 | console.log(e);
46 | resolve({
47 | responseStatus: 'defaultError',
48 | });
49 | }
50 | });
51 | }
52 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/filters/search.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { ItemRow } from "renderer/interfaces/items";
3 | import { InventoryFilters, MoveFromReducer, MoveToReducer } from "renderer/interfaces/states";
4 |
5 |
6 | export function searchFilter(itemsArray: Array, inventoryFilters: InventoryFilters, chosenReducer: InventoryFilters | MoveFromReducer | MoveToReducer | undefined): Array {
7 | let searchString: string = ''
8 | if (chosenReducer != undefined) {
9 | searchString = chosenReducer.searchInput
10 | }
11 | return itemsArray.filter(function (row) {
12 |
13 | if (
14 | inventoryFilters.categoryFilter.length != 0 ) {
15 | if (!inventoryFilters.categoryFilter?.includes(row.bgColorClass as string)) {
16 | return false
17 | }
18 | }
19 | if (
20 | row.item_name
21 | ?.toLowerCase()
22 | .trim()
23 | .includes(searchString?.toLowerCase().trim())
24 | ) {
25 | return true; // skip
26 | }
27 | if (
28 | row.item_wear_name
29 | ?.toLowerCase()
30 | .trim()
31 | .includes(searchString?.toLowerCase().trim())
32 | ) {
33 | return true; // skip
34 | }
35 | if (
36 | row.item_customname
37 | ?.toLowerCase()
38 | .trim()
39 | .includes(searchString?.toLowerCase().trim())
40 | ) {
41 | return true; // skip
42 | }
43 | if (searchString == undefined || searchString == '' ) {
44 | return true; // skip
45 | }
46 | return false;
47 | });
48 | }
49 |
--------------------------------------------------------------------------------
/src/renderer/store/reducer/userStatus.tsx:
--------------------------------------------------------------------------------
1 | import { AuthReducer } from "renderer/interfaces/states";
2 |
3 | const initialState: AuthReducer = {
4 | displayName: null ,
5 | CSGOConnection: false,
6 | userProfilePicture: null ,
7 | steamID: null,
8 | isLoggedIn: false ,
9 | hasConnection: false,
10 | walletBalance: {
11 | hasWallet: false,
12 | currency: '',
13 | balance: 0
14 | }
15 | };
16 |
17 | const authReducer = (state = initialState, action) => {
18 | switch (action.type) {
19 | case 'SIGN_IN':
20 | return {
21 | ...state,
22 | displayName: action.payload.displayName,
23 | CSGOConnection: action.payload.CSGOConnection,
24 | userProfilePicture: action.payload.userProfilePicture,
25 | steamID: action.payload.steamID,
26 | isLoggedIn: true,
27 | hasConnection: true,
28 | walletBalance: action.payload.wallet
29 | }
30 | case 'SIGN_OUT':
31 | return {
32 | ...initialState
33 | }
34 |
35 | case 'SET_CONNECTION':
36 | return {
37 | ...state,
38 | hasConnection: action.payload.hasConnection
39 | }
40 | case 'SET_WALLET_BALANCE':
41 | return {
42 | ...state,
43 | walletBalance: action.payload
44 | }
45 |
46 |
47 | case 'SET_GC':
48 | return {
49 | ...state,
50 | CSGOConnection: action.payload.CSGOConnection
51 | }
52 | case 'LOGOUT':
53 | return {
54 | ...initialState
55 | }
56 | default:
57 | return state
58 |
59 | }
60 | };
61 |
62 | export default authReducer;
63 |
--------------------------------------------------------------------------------
/src/renderer/views/login/login.tsx:
--------------------------------------------------------------------------------
1 | import { Disclosure } from '@headlessui/react'
2 | import { useState } from 'react'
3 | import LoginForm from './loginForm'
4 | import UserGrid from './userManagement'
5 | import { BrowserRouter as Router, Route } from 'react-router-dom';
6 | Disclosure
7 | function LoginPageContent() {
8 | const [getLock, setLock] = useState([''])
9 | const [deleteUser, setdeleteUser] = useState('')
10 |
11 | return (
12 | <>
13 | {/*
14 | This example requires updating your template:
15 |
16 | ```
17 |
18 |
19 | ```
20 | */}
21 |
22 |
23 |
24 | {/* Account switcher */}
25 |
26 |
27 |
28 | setLock(username)} runDeleteUser={() => setdeleteUser('')} deleteUser={deleteUser} />
29 |
30 |
31 | {/* Login */}
32 |
36 |
37 | setLock([''])} runDeleteUser={(username) => setdeleteUser(username)}/>
38 |
39 |
40 |
41 | >
42 | )
43 | }
44 |
45 | export default function LoginPage() {
46 | return (
47 |
48 |
49 |
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/helpers/login/flowLoginRegularQR.tsx:
--------------------------------------------------------------------------------
1 | import { EAuthTokenPlatformType, LoginSession } from 'steam-session';
2 | import { LoginOptions } from '../../../shared/Interfaces.tsx/store';
3 | import { storeRefreshToken } from '../classes/steam/settings';
4 | import { emitterAccount } from '../../../emitters';
5 |
6 | export async function flowLoginRegularQR(doStoreLogin: boolean): Promise<{
7 | responseStatus: keyof LoginOptions;
8 | session?: LoginSession;
9 | }> {
10 | return new Promise(async (resolve) => {
11 | let session = new LoginSession(EAuthTokenPlatformType.SteamClient);
12 | console.log('Start with QR');
13 |
14 | session.on('authenticated', async () => {
15 | console.log(`Logged into Steam as ${session.accountName}`);
16 |
17 | if (doStoreLogin) {
18 | storeRefreshToken(session.accountName, session.refreshToken);
19 | }
20 |
21 | resolve({
22 | responseStatus: 'loggedIn',
23 | session,
24 | });
25 | });
26 |
27 | session.once('timeout', () => {
28 | resolve({
29 | responseStatus: 'defaultError',
30 | });
31 | });
32 |
33 | session.once('error', (_err) => {
34 | console.log('Error');
35 | resolve({
36 | responseStatus: 'defaultError',
37 | });
38 | });
39 | try {
40 | emitterAccount.once('qrLogin:cancel', () => {
41 | session.removeAllListeners('authenticated');
42 | session.removeAllListeners('timeout');
43 | session.removeAllListeners('error');
44 | session.cancelLoginAttempt();
45 | });
46 | const { qrChallengeUrl } = await session.startWithQR();
47 | emitterAccount.emit('qrLogin:show', qrChallengeUrl);
48 | } catch {
49 | resolve({
50 | responseStatus: 'defaultError',
51 | });
52 | }
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/overview.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { useSelector } from 'react-redux';
3 | import { BrowserRouter as Router, Route } from 'react-router-dom';
4 | import RunOverview from './runOverview';
5 |
6 | function overviewContent() {
7 | const tradeUpData = useSelector((state: any) => state.tradeUpReducer);
8 | const pricesResult = useSelector((state: any) => state.pricingReducer);
9 | const settingsData = useSelector((state: any) => state.settingsReducer);
10 | let totalFloat = 0;
11 | let totalPrice = 0;
12 | tradeUpData.tradeUpProducts.forEach((element) => {
13 | totalFloat += element.item_paint_wear;
14 | totalPrice +=
15 | pricesResult.prices[element.item_name + element.item_wear_name || '']?.['steam_listing'] *
16 | settingsData.currencyPrice[settingsData.currency];
17 | });
18 | totalFloat = totalFloat / tradeUpData.tradeUpProducts.length;
19 | let totalEV = 0;
20 | tradeUpData.possibleOutcomes.forEach((element) => {
21 | let individualPrice =
22 | pricesResult?.prices[element.item_name + element.item_wear_name || '']?.['steam_listing'] * settingsData.currencyPrice[settingsData.currency];
23 | totalEV += individualPrice * (element.percentage / 100);
24 | console.log(
25 | element,
26 | element.percentage,
27 | individualPrice * (element.percentage / 100)
28 | );
29 | });
30 | totalEV
31 | totalPrice
32 |
33 | return (
34 | <>
35 |
45 | >
46 | );
47 | }
48 | export default function OverviewPage() {
49 | return (
50 |
51 |
52 |
53 | );
54 | }
55 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/moveToActions.tsx:
--------------------------------------------------------------------------------
1 | export const moveToSetHide = () => {
2 | return {
3 | type: 'MOVE_TO_SET_HIDE'
4 | }
5 | }
6 | export const moveToSetFull = () => {
7 | return {
8 | type: 'MOVE_TO_SET_FULL'
9 | }
10 | }
11 | export const moveToClearAll = () => {
12 | return {
13 | type: 'MOVE_TO_CLEAR_ALL'
14 | }
15 | }
16 | export const doCancel = (doCancel) => {
17 | return {
18 | type: 'DO_CANCEL',
19 | payload: {
20 | doCancel: doCancel
21 | }
22 | }
23 | }
24 | export const moveTosetSearchField = (searchField) => {
25 | return {
26 | type: 'MOVE_TO_SET_SEARCH',
27 | payload: {
28 | searchField: searchField
29 | }
30 | }
31 | }
32 | export const moveTosetSearchFieldStorage = (searchField) => {
33 | return {
34 | type: 'MOVE_TO_SET_SEARCH_STORAGE',
35 | payload: {
36 | searchField: searchField
37 | }
38 | }
39 | }
40 |
41 | export const moveToAddCasketToStorages = (casketID, casketVolume) => {
42 | return {
43 | type: 'MOVE_TO_ADD_TO',
44 | payload: {
45 | casketID: casketID,
46 | casketVolume: casketVolume
47 | }
48 | }
49 | }
50 |
51 | export const moveToSetStorageAmount = (storageAmount) => {
52 | return {
53 | type: 'SET_STORAGE_AMOUNT',
54 | payload: {
55 | storageAmount: storageAmount
56 | }
57 | }
58 | }
59 | export const moveToAddRemove = (casketID, itemID, totalItems, itemName) => {
60 | return {
61 | type: 'MOVE_TO_TOTAL_TO_ADD',
62 | payload: {
63 | casketID: casketID,
64 | toMove: totalItems,
65 | itemID: itemID,
66 | itemName:itemName
67 |
68 | }
69 | }
70 | }
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/main/scripts/versionHelper.tsx:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import { GithubResponse } from 'main/interfaces/mainInterfaces';
3 |
4 |
5 | async function getGithubVersion(platform: string): Promise {
6 | return new Promise((resolve) => {
7 | axios
8 | .get('https://api.github.com/repos/nombersDev/casemove/releases')
9 | .then((response) => {
10 | const responseData: JSON = response.data;
11 |
12 | for (const [_key, value] of Object.entries(responseData)) {
13 | if (value.prerelease == false) {
14 | console.log('githubVersion', value.tag_name.replaceAll('.', ''));
15 | let downloadLink: string = value['html_url'];
16 | console.log('Platform: ', platform)
17 |
18 | // Find the relevant download link
19 | switch (platform) {
20 | case 'win32':
21 | value.assets.forEach((element) => {
22 | if (element.name.includes('.exe') && !element.name?.toLowerCase()?.includes('blockmap')) {
23 | downloadLink = element.browser_download_url;
24 | }
25 | });
26 | break;
27 |
28 | case 'linux':
29 | value.assets.forEach((element) => {
30 | if (element.name.includes('.dmg')) {
31 | downloadLink = element.browser_download_url;
32 | }
33 | });
34 | break;
35 |
36 | default:
37 | break
38 | }
39 |
40 | resolve({
41 | version: parseInt(value.tag_name.replaceAll('.', '').replaceAll('v', '')),
42 | downloadLink: downloadLink,
43 | });
44 | break;
45 | }
46 | }
47 | });
48 | });
49 | }
50 |
51 | export { getGithubVersion };
52 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/titleBarWindows.tsx:
--------------------------------------------------------------------------------
1 | import TitleBarClose from "./iconsLogo/close";
2 | import TitleBarMaximize from "./iconsLogo/maximize";
3 | import TitleBarMinimize from "./iconsLogo/minimize";
4 |
5 | export default function TitleBarWindows() {
6 |
7 | async function sendAction(whichOption) {
8 | window.electron.ipcRenderer.handleWindowsActions(whichOption)
9 | }
10 | return (
11 | <>
12 | {/* Page title & actions */}
13 |
14 |
15 |
23 |
24 |
25 |
32 |
33 |
34 |
41 |
42 |
43 | >
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/moveFromActions.tsx:
--------------------------------------------------------------------------------
1 | export const moveFromSetFull = () => {
2 | return {
3 | type: 'MOVE_FROM_SET_FULL'
4 | }
5 | }
6 |
7 | export const moveFromSetSortBack = () => {
8 | return {
9 | type: 'MOVE_FROM_SET_SORT_BACK'
10 | }
11 | }
12 | export const moveFromClearAll = () => {
13 | return {
14 | type: 'MOVE_FROM_CLEAR_ALL'
15 | }
16 | }
17 | export const moveFromReset = () => {
18 | return {
19 | type: 'MOVE_FROM_CLEAR'
20 | }
21 | }
22 | export const moveFromsetSearchField = (searchField) => {
23 | return {
24 | type: 'MOVE_FROM_SET_SEARCH',
25 | payload: {
26 | searchField: searchField
27 | }
28 | }
29 | }
30 | export const moveFromsetSearchFieldStorage = (searchField) => {
31 | return {
32 | type: 'MOVE_FROM_SET_SEARCH_STORAGE',
33 | payload: {
34 | searchField: searchField
35 | }
36 | }
37 | }
38 | export const SetSortOption = (sortValue) => {
39 | return {
40 | type: 'SET_SORT',
41 | payload: {
42 | sortValue: sortValue
43 | }
44 | }
45 | }
46 |
47 | export const moveFromAddCasketToStorages = (casketID) => {
48 | return {
49 | type: 'MOVE_FROM_ADD_TO',
50 | payload: {
51 | casketID: casketID
52 | }
53 | }
54 | }
55 |
56 | export const moveFromAddRemove = (casketID: string, itemID: string, totalItems: Array, itemName: string) => {
57 | return {
58 | type: 'MOVE_FROM_TOTAL_TO_ADD',
59 | payload: {
60 | casketID: casketID,
61 | toMove: totalItems,
62 | itemID: itemID,
63 | itemName:itemName
64 |
65 | }
66 | }
67 | }
68 |
69 | export const moveFromRemoveCasket = (casketID) => {
70 | return {
71 | type: 'MOVE_FROM_ALL_CASKET_RESULTS',
72 | payload: {
73 | casketID: casketID
74 |
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.renderer.dev.dll.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Builds the DLL for development electron renderer process
3 | */
4 |
5 | import webpack from 'webpack';
6 | import path from 'path';
7 | import { merge } from 'webpack-merge';
8 | import baseConfig from './webpack.config.base';
9 | import webpackPaths from './webpack.paths';
10 | import { dependencies } from '../../package.json';
11 | import checkNodeEnv from '../scripts/check-node-env';
12 |
13 | checkNodeEnv('development');
14 |
15 | const dist = webpackPaths.dllPath;
16 |
17 | export default merge(baseConfig, {
18 | context: webpackPaths.rootPath,
19 |
20 | devtool: 'eval',
21 |
22 | mode: 'development',
23 |
24 | target: 'electron-renderer',
25 |
26 | externals: ['fsevents', 'crypto-browserify'],
27 |
28 | /**
29 | * Use `module` from `webpack.config.renderer.dev.js`
30 | */
31 | module: require('./webpack.config.renderer.dev').default.module,
32 |
33 | entry: {
34 | renderer: Object.keys(dependencies || {}),
35 | },
36 |
37 | output: {
38 | path: dist,
39 | filename: '[name].dev.dll.js',
40 | library: {
41 | name: 'renderer',
42 | type: 'var',
43 | },
44 | },
45 |
46 | plugins: [
47 | new webpack.DllPlugin({
48 | path: path.join(dist, '[name].json'),
49 | name: '[name]',
50 | }),
51 |
52 | /**
53 | * Create global constants which can be configured at compile time.
54 | *
55 | * Useful for allowing different behaviour between development builds and
56 | * release builds
57 | *
58 | * NODE_ENV should be production so that modules do not perform certain
59 | * development checks
60 | */
61 | new webpack.EnvironmentPlugin({
62 | NODE_ENV: 'development',
63 | }),
64 |
65 | new webpack.LoaderOptionsPlugin({
66 | debug: true,
67 | options: {
68 | context: webpackPaths.srcPath,
69 | output: {
70 | path: webpackPaths.dllPath,
71 | },
72 | },
73 | }),
74 | ],
75 | });
76 |
--------------------------------------------------------------------------------
/src/renderer/store/reducer/pricing.tsx:
--------------------------------------------------------------------------------
1 | import { Prices } from "renderer/interfaces/states";
2 |
3 | const initialState: Prices = {
4 | prices: {},
5 | storageAmount: 0,
6 | productsRequested: [],
7 | };
8 |
9 | const pricingReducer = (state = initialState, action) => {
10 | switch (action.type) {
11 |
12 |
13 | case 'PRICING_ADD_STORAGE_TOTAL':
14 | console.log(action.payload.storageAmount)
15 | return {
16 | ...state,
17 | storageAmount: state.storageAmount + action.payload.storageAmount,
18 | };
19 | case 'PRICING_ADD_TO':
20 | let currentPrices = state.prices;
21 | action.payload.itemRows.forEach(element => {
22 | currentPrices[element.item_name + element.item_wear_name || ''] = element.pricing;
23 | });
24 | console.log(currentPrices)
25 | return {
26 | ...state,
27 | prices: currentPrices,
28 | };
29 |
30 | case 'PRICING_ADD_TO_REQUESTED':
31 | let currentRequested = state.productsRequested;
32 | action.payload.itemRows.forEach(element => {
33 | let nameToPuse = element.item_name + element.item_wear_name || ''
34 | currentRequested.push(nameToPuse)
35 | });
36 | return {
37 | ...state,
38 | productsRequested: currentRequested,
39 | };
40 | case 'PRICING_REMOVE':
41 | let removeCurrentPrices = state.prices;
42 |
43 | if (removeCurrentPrices[action.payload.itemName] !== undefined) {
44 | delete removeCurrentPrices[action.payload.itemName];
45 | }
46 | return {
47 | ...state,
48 | prices: removeCurrentPrices,
49 | };
50 | case 'PRICING_CLEAR':
51 | return {
52 | ...initialState,
53 | };
54 | case 'MOVE_FROM_CLEAR':
55 | return {
56 | ...state,
57 | storageAmount: initialState.storageAmount
58 | }
59 |
60 | case 'SIGN_OUT':
61 | return {
62 | ...initialState,
63 | };
64 | default:
65 | return { ...state };
66 | }
67 | };
68 |
69 | export default pricingReducer;
70 |
--------------------------------------------------------------------------------
/.erb/scripts/check-native-dep.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import chalk from 'chalk';
3 | import { execSync } from 'child_process';
4 | import { dependencies } from '../../package.json';
5 |
6 | if (dependencies) {
7 | const dependenciesKeys = Object.keys(dependencies);
8 | const nativeDeps = fs
9 | .readdirSync('node_modules')
10 | .filter((folder) => fs.existsSync(`node_modules/${folder}/binding.gyp`));
11 | if (nativeDeps.length === 0) {
12 | process.exit(0);
13 | }
14 | try {
15 | // Find the reason for why the dependency is installed. If it is installed
16 | // because of a devDependency then that is okay. Warn when it is installed
17 | // because of a dependency
18 | const { dependencies: dependenciesObject } = JSON.parse(
19 | execSync(`npm ls ${nativeDeps.join(' ')} --json`).toString()
20 | );
21 | const rootDependencies = Object.keys(dependenciesObject);
22 | const filteredRootDependencies = rootDependencies.filter((rootDependency) =>
23 | dependenciesKeys.includes(rootDependency)
24 | );
25 | if (filteredRootDependencies.length > 0) {
26 | const plural = filteredRootDependencies.length > 1;
27 | console.log(`
28 | ${chalk.whiteBright.bgYellow.bold(
29 | 'Webpack does not work with native dependencies.'
30 | )}
31 | ${chalk.bold(filteredRootDependencies.join(', '))} ${
32 | plural ? 'are native dependencies' : 'is a native dependency'
33 | } and should be installed inside of the "./release/app" folder.
34 | First, uninstall the packages from "./package.json":
35 | ${chalk.whiteBright.bgGreen.bold('npm uninstall your-package')}
36 | ${chalk.bold(
37 | 'Then, instead of installing the package to the root "./package.json":'
38 | )}
39 | ${chalk.whiteBright.bgRed.bold('npm install your-package')}
40 | ${chalk.bold('Install the package to "./release/app/package.json"')}
41 | ${chalk.whiteBright.bgGreen.bold('cd ./release/app && npm install your-package')}
42 | Read more about native dependencies at:
43 | ${chalk.bold(
44 | 'https://electron-react-boilerplate.js.org/docs/adding-dependencies/#module-structure'
45 | )}
46 | `);
47 | process.exit(1);
48 | }
49 | } catch (e) {
50 | console.log('Native dependencies could not be checked');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/renderer/components/content/loadStorageUnitsButton.tsx:
--------------------------------------------------------------------------------
1 | import { CollectionIcon } from "@heroicons/react/solid";
2 | import { useState } from "react";
3 | import { useDispatch, useSelector } from "react-redux";
4 | import { ReducerManager } from "renderer/functionsClasses/reducerManager";
5 | import { getAllStorages } from "renderer/functionsClasses/storageUnits/storageUnitsFunctions";
6 | import { State } from "renderer/interfaces/states";
7 | import { LoadingButton } from "./shared/animations";
8 | import { classNames } from "./shared/filters/inventoryFunctions";
9 |
10 | export function LoadButton() {
11 | let ReducerClass = new ReducerManager(useSelector);
12 | let currentState: State = ReducerClass.getStorage();
13 | const dispatch = useDispatch();
14 | // Get all storage unit data
15 | async function getAllStor() {
16 | setLoadingButton(true)
17 | getAllStorages(dispatch, currentState).then(() => {
18 | setLoadingButton(false)
19 | })
20 | }
21 |
22 | const [getLoadingButton, setLoadingButton] = useState(false);
23 | return (
24 | <>
25 |
45 | >
46 | );
47 | }
48 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.main.prod.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Webpack config for production electron main process
3 | */
4 |
5 | import path from 'path';
6 | import webpack from 'webpack';
7 | import { merge } from 'webpack-merge';
8 | import TerserPlugin from 'terser-webpack-plugin';
9 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
10 | import baseConfig from './webpack.config.base';
11 | import webpackPaths from './webpack.paths';
12 | import checkNodeEnv from '../scripts/check-node-env';
13 | import deleteSourceMaps from '../scripts/delete-source-maps';
14 |
15 | checkNodeEnv('production');
16 | deleteSourceMaps();
17 |
18 | const devtoolsConfig =
19 | process.env.DEBUG_PROD === 'true'
20 | ? {
21 | devtool: 'source-map',
22 | }
23 | : {};
24 |
25 | export default merge(baseConfig, {
26 | ...devtoolsConfig,
27 |
28 | mode: 'production',
29 |
30 | target: 'electron-main',
31 |
32 | entry: {
33 | main: path.join(webpackPaths.srcMainPath, 'main.ts'),
34 | preload: path.join(webpackPaths.srcMainPath, 'preload.js'),
35 | },
36 |
37 | output: {
38 | path: webpackPaths.distMainPath,
39 | filename: '[name].js',
40 | },
41 |
42 | optimization: {
43 | minimizer: [
44 | new TerserPlugin({
45 | parallel: true,
46 | }),
47 | ],
48 | },
49 |
50 | plugins: [
51 | new BundleAnalyzerPlugin({
52 | analyzerMode:
53 | process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled',
54 | openAnalyzer: process.env.OPEN_ANALYZER === 'true',
55 | }),
56 |
57 | /**
58 | * Create global constants which can be configured at compile time.
59 | *
60 | * Useful for allowing different behaviour between development builds and
61 | * release builds
62 | *
63 | * NODE_ENV should be production so that modules do not perform certain
64 | * development checks
65 | */
66 | new webpack.EnvironmentPlugin({
67 | NODE_ENV: 'production',
68 | DEBUG_PROD: false,
69 | START_MINIMIZED: false,
70 | }),
71 | ],
72 |
73 | /**
74 | * Disables webpack processing of __dirname and __filename.
75 | * If you run the bundle in node.js it falls back to these values of node.js.
76 | * https://github.com/webpack/webpack/issues/2010
77 | */
78 | node: {
79 | __dirname: false,
80 | __filename: false,
81 | },
82 | });
83 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventoryRows/stickerPatchesRow.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { Link } from "react-router-dom";
3 | import { createCSGOImage } from "../../../../functionsClasses/createCSGOImage";
4 | import { classNames } from "../../shared/filters/inventoryFunctions";
5 |
6 | export function RowStickersPatches({itemRow, settingsData}) {
7 | const [stickerHover, setStickerHover] = useState('');
8 |
9 | return (
10 | <>
11 |
12 | {settingsData.columns.includes('Stickers/patches') ?
13 |
14 |
15 |
16 | {itemRow.stickers?.map((sticker, index) => (
17 |
23 | ![]()
26 | setStickerHover(index + itemRow.item_id)
27 | }
28 | onMouseLeave={() => setStickerHover('')}
29 | className={classNames(
30 | stickerHover == index + itemRow.item_id
31 | ? 'transform-gpu hover:-translate-y-1 hover:scale-110'
32 | : '',
33 | 'max-w-none h-8 w-8 rounded-full hover:shadow-sm text-black hover:bg-gray-50 transition duration-500 ease-in-out hover:text-white hover:bg-green-600 ring-2 object-cover ring-transparent bg-gradient-to-t from-gray-100 to-gray-300 dark:from-gray-300 dark:to-gray-400'
34 | )}
35 | src={
36 | createCSGOImage(sticker.sticker_url)
37 | }
38 | alt={sticker.sticker_name}
39 | title={sticker.sticker_name}
40 | />
41 |
42 | ))}
43 |
44 |
45 | | : '' }
46 |
47 | >
48 | );
49 | }
50 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/storageUnits/storageUnitsFunctions.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { ItemRow, ItemRowStorage } from "renderer/interfaces/items";
3 | import { State } from "renderer/interfaces/states";
4 | import { HandleStorageData } from "./storageUnitsClass";
5 |
6 | function sorting(valueOne, valueTwo) {
7 | if (valueOne < valueTwo) {
8 | return -1;
9 | }
10 | if (valueOne > valueTwo) {
11 | return 1;
12 | }
13 | return 0;
14 | }
15 | class Sort {
16 | itemArray: Array
17 | constructor(itemArray: Array) {
18 | this.itemArray = itemArray
19 | }
20 |
21 | async item_customname() {
22 | return this.itemArray.sort(function(a, b) {
23 | return sorting(a.item_customname || '0000', b.item_customname || '0000')
24 | })
25 |
26 | }
27 | }
28 |
29 | export async function getAllStorages(
30 | dispatch: Function,
31 | state: State
32 | ) {
33 |
34 | // Filter the storage inventory
35 | const casketResults = await state.inventoryReducer.inventory.filter(function (row) {
36 | if (!row.item_url.includes('casket')) {
37 | return false; // skip
38 | }
39 | if (row.item_storage_total == 0) {
40 | return false; // skip
41 | }
42 | if (
43 | state.moveFromReducer.searchInputStorage != '' &&
44 | !row?.item_customname?.toLowerCase()?.includes(state.moveFromReducer.searchInputStorage)
45 | ) {
46 | return false; // skip
47 | }
48 | if (row.item_storage_total == 1000 && state.moveFromReducer.hideFull) {
49 | return false; // skip
50 | }
51 | return true;
52 | });
53 |
54 | async function sendArrayAddStorage(returnValue: Array) {
55 | let StorageClass = new HandleStorageData(dispatch, state)
56 | let addArray: Array = []
57 | for (const [_key, project] of Object.entries(returnValue)) {
58 | if (!state.moveFromReducer.activeStorages.includes(project.item_id)) {
59 | addArray = [...addArray, ...await StorageClass.addStorage(
60 | project as ItemRowStorage,
61 | addArray
62 |
63 | )]
64 | }
65 | }
66 | return
67 | }
68 |
69 | // Handle storage data
70 | let SortingClass = new Sort(casketResults)
71 | return SortingClass.item_customname().then((returnValue) => {
72 | return sendArrayAddStorage(returnValue)
73 | })
74 |
75 |
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/renderer/store/reducer/settings.tsx:
--------------------------------------------------------------------------------
1 | import { Settings } from 'renderer/interfaces/states';
2 |
3 | const initialState: Settings = {
4 | fastMove: false,
5 | currency: 'USD',
6 | locale: 'EN-GB',
7 | os: '',
8 | steamLoginShow: true,
9 | devmode: false,
10 | columns: [
11 | 'Price',
12 | 'Stickers/patches',
13 | 'Storage',
14 | 'Tradehold',
15 | 'Moveable',
16 | 'Inventory link',
17 | ],
18 | currencyPrice: {},
19 | source: {
20 | title: 'steam_listing',
21 | name: 'Steam Community Market',
22 | avatar: 'https://steamcommunity.com/favicon.ico',
23 | },
24 | overview: {
25 | by: 'price',
26 | chartleft: 'overall',
27 | chartRight: 'itemDistribution',
28 | },
29 | };
30 |
31 | const settingsReducer = (state = initialState, action) => {
32 | switch (action.type) {
33 | case 'SETTINGS_SET_FASTMOVE':
34 | return {
35 | ...state,
36 | fastMove: action.payload,
37 | };
38 | case 'SETTINGS_SET_COLUMNS':
39 | return {
40 | ...state,
41 | columns: action.payload,
42 | };
43 | case 'SETTINGS_SET_CURRENCY':
44 | if (action.payload == true) {
45 | return {
46 | ...state,
47 | };
48 | }
49 | return {
50 | ...state,
51 | currency: action.payload,
52 | };
53 |
54 | case 'SETTINGS_SET_STEAMLOGINSHOW':
55 | return {
56 | ...state,
57 | steamLoginShow: action.payload,
58 | };
59 |
60 | case 'SETTINGS_SET_LOCALE':
61 | return {
62 | ...state,
63 | locale: action.payload,
64 | };
65 | case 'SETTINGS_SET_OS':
66 | return {
67 | ...state,
68 | os: action.payload,
69 | };
70 | case 'SETTINGS_SET_DEVMODE':
71 | return {
72 | ...state,
73 | devmode: action.payload,
74 | };
75 | case 'SETTINGS_SET_OVERVIEW':
76 | return {
77 | ...state,
78 | overview: action.payload,
79 | };
80 | case 'SETTINGS_ADD_CURRENCYPRICE':
81 | let currencyDict = state.currencyPrice;
82 | currencyDict[action.payload.currency] = action.payload.rate;
83 | return {
84 | ...state,
85 | currency: action.payload.currency,
86 | currencyPrice: currencyDict,
87 | };
88 |
89 | default:
90 | return { ...state };
91 | }
92 | };
93 |
94 | export default settingsReducer;
95 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/barChatMajors.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Bar } from 'react-chartjs-2';
3 | import { useSelector } from 'react-redux';
4 | import {itemSubCategories} from 'renderer/components/content/shared/categories';
5 | import Chart from 'chart.js/auto';
6 | Chart
7 |
8 |
9 | export default function BarAppMajor() {
10 |
11 | // Bar options
12 | // @ts-ignore
13 | const options = {
14 | plugins: {
15 | legend: {
16 | labels: {
17 | color: '#d6d3cd',
18 | },
19 |
20 | },
21 | title: {
22 | display: true,
23 | text: 'Majors',
24 | color: '#d6d3cd'
25 | }
26 | }
27 | };
28 |
29 | // Go through inventory and find matching categories
30 | const inventory = useSelector((state: any) => state.inventoryReducer);
31 |
32 | // Convert inventory to chart data
33 | let inventoryDataToUse: Array = [];
34 | let storageUnitDataToUse: Array = [];
35 |
36 | Object.keys(itemSubCategories.majors).forEach(category => {
37 | const inventoryResult = inventory.combinedInventory.filter(itemRow => itemRow.major == category);
38 | const storageResult = inventory.storageInventory.filter(itemRow => itemRow.major == category);
39 | let categoryCounter = 0
40 | inventoryResult.forEach(element => {
41 | categoryCounter = categoryCounter + element.combined_QTY
42 | });
43 | let storageCounter = 0
44 | storageResult.forEach(element => {
45 | storageCounter = storageCounter + element.combined_QTY
46 | });
47 |
48 | inventoryDataToUse.push(categoryCounter)
49 | storageUnitDataToUse.push(storageCounter)
50 | });
51 | console.log(storageUnitDataToUse)
52 |
53 |
54 | const data = {
55 | labels: Object.keys(itemSubCategories.majors),
56 |
57 |
58 | datasets: [
59 | {
60 | label: 'Inventory',
61 | data: inventoryDataToUse,
62 | backgroundColor: 'rgba(255, 99, 132, 0.2)',
63 | borderColor: 'rgba(255, 99, 132, 1)',
64 | borderWidth: 1,
65 | },
66 | {
67 | label: 'Storage Units',
68 | data: storageUnitDataToUse,
69 | backgroundColor: 'rgb(50, 91, 136, 0.2)',
70 | borderColor: 'rgb(50, 91, 136, 1)',
71 | borderWidth: 1,
72 | },
73 | ],
74 | };
75 | // @ts-ignore
76 | return (
77 | <>
78 |
79 |
80 | >
81 | );
82 | }
83 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/downloadReport.tsx:
--------------------------------------------------------------------------------
1 | import { ItemRow, ItemRowStorage } from "renderer/interfaces/items";
2 | import { Prices, Settings } from "renderer/interfaces/states";
3 | import { ConvertPricesFormatted } from "./prices";
4 |
5 | async function handleDownload(storageData) {
6 | let csvContent =
7 | 'Item Name,Item Custom Name,Price,Price Combined,Item Moveable,Storage Name,Tradehold,Category,Combined QTY,Item Wear Name,Item Paint Wear,Item Has Stickers/Patches,Stickers\n';
8 | var csv = storageData
9 | .map(function (d) {
10 | let storageName = d.storage_name;
11 | if (storageName == undefined) {
12 | storageName = '#Inventory';
13 | }
14 |
15 | let stickersData = d.stickers;
16 | // @ts-ignore
17 | if (stickersData != []) {
18 | let newStickers = [] as any;
19 | stickersData.forEach((element) => {
20 | newStickers.push(element.sticker_name);
21 | });
22 | stickersData = newStickers.join(';');
23 | }
24 | const returnDict = {
25 | item_name: d.item_name,
26 | item_customname: d.item_customname,
27 | price: d.item_price,
28 | price_combined: d.item_price_combined,
29 | item_moveable: d.item_moveable,
30 | storage_name: storageName,
31 | trade_unlock: d.trade_unlock,
32 | category: d.category,
33 | combined_QTY: d.combined_QTY,
34 | item_wear_name: d.item_wear_name,
35 | item_paint_wear: d.item_paint_wear,
36 | item_has_stickers: d.item_has_stickers,
37 | item_stickers: stickersData,
38 | };
39 | return JSON.stringify(Object.values(returnDict));
40 | })
41 | .join('\n')
42 | .replaceAll('null', '')
43 | .replace(/(^\[)|(\]$)/gm, '');
44 | csv = csvContent + csv;
45 | window.electron.ipcRenderer.downloadFile(csv);
46 | }
47 |
48 | export async function downloadReport(settingsData: Settings, pricesReducer: Prices, itemArray: Array ) {
49 | const PricesClassFormatted = new ConvertPricesFormatted(settingsData, pricesReducer)
50 | itemArray.forEach((element: any) => {
51 | element.item_price = PricesClassFormatted.getFormattedPrice(element);
52 | element.item_price_combined = PricesClassFormatted.getFormattedPriceCombined(element);
53 | });
54 |
55 | handleDownload(itemArray);
56 | }
57 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/iconsLogo/logo.tsx:
--------------------------------------------------------------------------------
1 | const Logo = (props) => (
2 |
21 | );
22 |
23 | export default Logo;
24 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/steamLogo.tsx:
--------------------------------------------------------------------------------
1 | const SteamLogo = (props) => (
2 |
14 | )
15 |
16 | export default SteamLogo
17 |
18 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/iconsLogo/logo 2.tsx:
--------------------------------------------------------------------------------
1 | const Logo = (props) => (
2 |
19 | );
20 |
21 | export default Logo;
22 |
--------------------------------------------------------------------------------
/src/main/helpers/classes/steam/currency.tsx:
--------------------------------------------------------------------------------
1 | const CC = require('currency-converter-lt');
2 |
3 | async function setBackUp(currencyClass) {
4 | let rates = require('./backup/currency.json')
5 | currencyClass.setRates(rates.rates)
6 | }
7 |
8 | async function getLiveRates(currencyClass) {
9 | console.log('here')
10 | let currencyConverter = new CC({isDecimalComma:true});
11 | currencyConverter.from('USD').to('EUR').amount(100).convert().then((response) => {
12 | console.log(response)
13 |
14 | let secondConverter = new CC();
15 | secondConverter.from('USD').to('EUR').amount(100).convert().then((secondResponse) => {
16 | if (response < secondResponse) {
17 | currencyClass.setCurrencyClass(currencyConverter)
18 | } else {
19 | currencyClass.setCurrencyClass(secondConverter)
20 | }
21 | })
22 | }).catch(_error => {
23 | console.log('Error initilizing')
24 | } )
25 | console.log('here 2')
26 | }
27 |
28 | class currency {
29 | rates = {};
30 | currencyConverter
31 | seenRates = {}
32 |
33 | constructor() {
34 | setBackUp(this)
35 | getLiveRates(this)
36 | }
37 |
38 | // Setup backup
39 | setRates(rates) {
40 | this.rates = rates
41 | }
42 |
43 | // Setup for live rates
44 | setCurrencyClass(converter) {
45 | this.currencyConverter = converter
46 | }
47 |
48 |
49 | getRate(exchangeTo) {
50 | return new Promise((resolve) => {
51 | if (this.seenRates[exchangeTo] != undefined) {
52 | resolve(this.seenRates[exchangeTo])
53 | }
54 | if (this.currencyConverter == undefined) {
55 | resolve(this.rates[exchangeTo])
56 | }
57 | this.currencyConverter.from('USD').to(exchangeTo).amount(100).convert().then((response) => {
58 | let rate = response / 100
59 | if (typeof rate === 'number' && !Number.isNaN(rate)) {
60 | this.seenRates[exchangeTo] = rate
61 | resolve(rate)
62 | } else {
63 | resolve(this.rates[exchangeTo])
64 | }
65 | }).catch(error => {
66 | console.log('error occurred', error)
67 | resolve(this.rates[exchangeTo])
68 | })
69 | });
70 | }
71 | }
72 |
73 | // const currencyClass = new currency()
74 |
75 | // sleep time expects milliseconds
76 | //function sleep (time) {
77 | // return new Promise((resolve) => setTimeout(resolve, time));
78 | //}
79 |
80 | // Usage!
81 | //sleep(5000).then(() => {
82 | // currencyClass.getRate('EUR').then((returnValue) => {
83 | // console.log(returnValue)
84 | // })
85 | //});
86 |
87 |
88 | module.exports = {
89 | currency
90 | };
91 | export { currency };
92 |
93 |
--------------------------------------------------------------------------------
/src/renderer/components/content/Inventory/inventory.tsx:
--------------------------------------------------------------------------------
1 | import { BrowserRouter as Router, Route } from 'react-router-dom';
2 | import InventoryFilters from './filterHeader';
3 | import InventoryRowsComponent from './inventoryRows';
4 | import { useState } from 'react';
5 | import { LoadingButton } from '../shared/animations';
6 | import { RefreshIcon } from '@heroicons/react/solid';
7 |
8 | function content() {
9 | const [getLoadingButton, setLoadingButton] = useState(false);
10 | setLoadingButton;
11 |
12 | // Get the inventory
13 | async function refreshInventory() {
14 | window.electron.ipcRenderer.refreshInventory();
15 | }
16 |
17 | return (
18 | <>
19 | {/* Page title & actions */}
20 |
21 |
22 |
23 | Inventory
24 |
25 |
26 |
27 |
42 |
43 |
44 | {/* Pinned projects */}
45 |
46 |
47 | {/* Projects list (only on smallest breakpoint) */}
48 |
49 |
50 |
51 | Storages
52 |
53 |
54 |
55 |
56 | {/* Projects table (small breakpoint and up) */}
57 |
62 | >
63 | );
64 | }
65 | export default function inventoryContent() {
66 | return (
67 |
68 |
69 |
70 | );
71 | }
72 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/rendererCommands/admin.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | setColumns,
3 | setCurrencyRate,
4 | setCurrencyValue,
5 | setDevmode,
6 | setLocale,
7 | setOS,
8 | setSteamLoginShow
9 | } from 'renderer/store/actions/settings';
10 | import {
11 | DispatchIPCBuildingObject,
12 | DispatchIPCHandleBuildingOptionsClass,
13 | DispatchStoreBuildingObject,
14 | DispatchStoreHandleBuildingOptionsClass,
15 | } from 'shared/Interfaces.tsx/login';
16 |
17 | export class IPCCommunication {
18 | ipc = window.electron.ipcRenderer;
19 | store = window.electron.store;
20 |
21 | async get(command: Function) {
22 | return await command().then((returnValue) => {
23 | return returnValue;
24 | });
25 | }
26 | async storeGet(settingToGet: string) {
27 | return await this.store.get(settingToGet).then((returnValue) => {
28 | return returnValue;
29 | });
30 | }
31 | }
32 |
33 | // Dispatch Store
34 | export class DispatchStore extends IPCCommunication {
35 | dispatch: Function;
36 | buildingObject: DispatchStoreHandleBuildingOptionsClass = {
37 |
38 | locale: {
39 | name: 'locale',
40 | action: setLocale
41 | },
42 | os: {
43 | name: 'os',
44 | action: setOS
45 | },
46 | columns: {
47 | name: 'columns',
48 | action: setColumns
49 | },
50 | devmode: {
51 | name: 'devmode.value',
52 | action: setDevmode
53 | },
54 | currency: {
55 | name: 'currency',
56 | action: setCurrencyValue
57 | },
58 | steamLoginShow: {
59 | name: 'steamLogin',
60 | action: setSteamLoginShow
61 | }
62 | };
63 | constructor(dispatch: Function) {
64 | super();
65 | this.dispatch = dispatch;
66 | }
67 |
68 | async run(buildingObject: DispatchStoreBuildingObject) {
69 | this.storeGet(buildingObject.name).then((returnValue) => {
70 | if (returnValue != undefined) {
71 | this.dispatch(buildingObject.action(returnValue));
72 | }
73 | });
74 | }
75 | }
76 |
77 | // Dispatch IPC
78 | export class DispatchIPC extends IPCCommunication {
79 | dispatch: Function;
80 | buildingObject: DispatchIPCHandleBuildingOptionsClass = {
81 | currency: {
82 | endpoint: this.ipc.getCurrencyRate,
83 | action: setCurrencyRate,
84 | },
85 | };
86 |
87 | constructor(dispatch: Function) {
88 | super();
89 | this.dispatch = dispatch;
90 | }
91 |
92 | async run(buildingObject: DispatchIPCBuildingObject) {
93 | this.get(buildingObject.endpoint).then((returnValue) => {
94 | if (returnValue != undefined) {
95 | this.dispatch(buildingObject.action(returnValue));
96 | }
97 | });
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/renderer/store/inventory/inventoryReducer.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Inventory } from "renderer/interfaces/states";
3 |
4 | const initialState: Inventory = {
5 | inventory: [],
6 | combinedInventory: [],
7 | storageInventory: [],
8 | storageInventoryRaw: [],
9 | totalAccountItems: 0,
10 | itemsLookUp: {}
11 | };
12 |
13 | const inventoryReducer = (state = initialState, action) => {
14 | switch (action.type) {
15 | case 'INVENTORY_SET_INVENTORY':
16 | let storageTotal = 0
17 | action.payload.inventory.forEach(element => {
18 | storageTotal += 1
19 | if (element.item_url == "econ/tools/casket") {
20 | storageTotal += element.item_storage_total
21 | }
22 | });
23 |
24 |
25 | return {
26 | ...state,
27 | inventory: action.payload.inventory,
28 | combinedInventory: action.payload.combinedInventory,
29 | totalAccountItems: storageTotal
30 | }
31 | case 'INVENTORY_STORAGES_ADD_TO':
32 | console.log(state)
33 | const add_to_filtered = state.storageInventory?.filter(id => id.storage_id != action.payload.casketID) || []
34 | const add_to_filtered_raw = state.storageInventoryRaw?.filter(id => id.storage_id != action.pay) || []
35 | action.payload.storageData.forEach(storageRow => add_to_filtered.push(storageRow))
36 | action.payload.storageRowsRaw.forEach(storageRow => add_to_filtered_raw.push(storageRow))
37 |
38 | return {
39 | ...state,
40 | storageInventory: add_to_filtered,
41 | storageInventoryRaw: add_to_filtered_raw
42 | }
43 | case 'INVENTORY_STORAGES_CLEAR_CASKET':
44 | const AddToFiltered = state.storageInventory.filter(id => id.storage_id != action.payload.casketID)
45 | const AddToFilteredRaw = state.storageInventoryRaw.filter(id => id.storage_id != action.payload.casketID)
46 |
47 | return {
48 | ...state,
49 | storageInventory: AddToFiltered,
50 | storageInventoryRaw: AddToFilteredRaw
51 | }
52 | case 'INVENTORY_STORAGES_SET_SORT_STORAGES':
53 | return {
54 | ...state,
55 | storageInventory: action.payload.storageData
56 | }
57 | case 'INVENTORY_STORAGES_CLEAR_ALL':
58 | return {
59 | ...state,
60 | storageInventory: initialState.storageInventory,
61 | storageInventoryRaw: initialState.storageInventoryRaw
62 | }
63 | case 'MOVE_FROM_CLEAR':
64 | return {
65 | ...state
66 | }
67 | case 'MOVE_FROM_RESET':
68 | return {
69 | ...state,
70 | storageInventory: initialState.storageInventory,
71 | storageInventoryRaw: initialState.storageInventoryRaw
72 |
73 | }
74 | case 'SIGN_OUT':
75 | return {
76 | ...initialState
77 | }
78 | default:
79 | return { ...state }
80 |
81 | }
82 | };
83 |
84 | export default inventoryReducer;
85 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/filters/custom.tsx:
--------------------------------------------------------------------------------
1 | import { Filter } from "renderer/interfaces/filters";
2 | import { ItemRow } from "renderer/interfaces/items";
3 |
4 |
5 | class CheckFilter {
6 | itemRow: ItemRow
7 | filter: Filter
8 |
9 | constructor(itemRow: ItemRow, filter: Filter) {
10 | this.itemRow = itemRow
11 | this.filter = filter
12 | }
13 |
14 | // Check if string is in URL
15 | CheckVariableIncludes(variableName: string): boolean {
16 | return this.itemRow?.[variableName]?.includes(this.filter.valueToCheck)
17 | }
18 |
19 | // Check if variable exists and boolean
20 | checkBooleanVariable(): boolean {
21 | return this.itemRow?.[this.filter.valueToCheck] || false
22 | }
23 |
24 | // Check if Container and sub value
25 | checkContainerSubValue(variableName: string): boolean {
26 | return this.itemRow.category == 'Containers' && this.CheckVariableIncludes(variableName) || false
27 | }
28 |
29 | }
30 |
31 |
32 |
33 | function filterLogic(itemRow: ItemRow, IndividualFilter: Filter): boolean {
34 | const FilterClass = new CheckFilter(itemRow, IndividualFilter)
35 | let returnValue: boolean = false;
36 | switch (IndividualFilter.commandType) {
37 | case 'checkBooleanVariable':
38 | returnValue = FilterClass.checkBooleanVariable()
39 | break
40 |
41 | case 'checkName':
42 | returnValue = FilterClass.CheckVariableIncludes('item_name')
43 | break
44 |
45 | case 'checkURL':
46 | returnValue = FilterClass.CheckVariableIncludes('item_url')
47 | break
48 |
49 | case 'checkMajor':
50 | returnValue = FilterClass.CheckVariableIncludes('major')
51 | break
52 |
53 | case 'checkNameAndContainer':
54 | returnValue = FilterClass.checkContainerSubValue('item_name')
55 | break
56 |
57 | case 'checkCapsule':
58 | returnValue = FilterClass.checkContainerSubValue('item_name')
59 | if (itemRow.item_name.includes('Challengers') || itemRow.item_name.includes('Legends') || itemRow.item_name.includes('Contenders')) {
60 | if (!itemRow.item_name.includes('Patch')) {
61 | returnValue = true;
62 |
63 | }
64 | }
65 |
66 | break;
67 |
68 | default:
69 | break
70 | }
71 | if (IndividualFilter.include) {
72 | return returnValue
73 | } else {
74 | return !returnValue
75 | }
76 | }
77 |
78 | export async function filterItemRows(arrayToFilter: Array, filters: Array): Promise> {
79 | let returnArray = arrayToFilter;
80 |
81 | filters.forEach(filt => {
82 |
83 | returnArray = returnArray.filter(itemRow => {
84 | return filterLogic(itemRow, filt)
85 | });
86 | });
87 |
88 | return returnArray
89 | }
--------------------------------------------------------------------------------
/src/renderer/store/reducer/modalMove.tsx:
--------------------------------------------------------------------------------
1 | import { ModalMove } from "renderer/interfaces/states";
2 |
3 | const initialState: ModalMove = {
4 | moveOpen: false,
5 | notifcationOpen: false,
6 | storageIdsToClearFrom: [],
7 | modalPayload: {
8 | number: 0,
9 | itemID: '',
10 | isLast: false
11 | },
12 | doCancel: [],
13 | query: [],
14 | totalFailed: 0
15 | };
16 |
17 | const modalMoveReducer = (state = initialState, action) => {
18 | switch (action.type) {
19 | case 'MOVE_MODAL_QUERY_SET':
20 | let queryData = [...action.payload.query]
21 | queryData.shift()
22 | return {
23 | ...state,
24 | moveOpen: true,
25 | modalPayload: action.payload.query[0].payload,
26 | query: queryData
27 | }
28 |
29 | case 'MOVE_MODAL_UPDATE':
30 | if (state.query.length == 0) {
31 | return {
32 | ...state,
33 | modalPayload: initialState.modalPayload,
34 | moveOpen: false
35 | }
36 | }
37 | let initialStoragesToClear = state.storageIdsToClearFrom
38 | if (!initialStoragesToClear.includes(state.query[0].payload.storageID)) {
39 | initialStoragesToClear.push(state.query[0].payload.storageID)
40 | }
41 | if (state.doCancel.includes(state.query[0].payload.key)) {
42 | return {
43 | ...state
44 | }
45 | }
46 | let newQuery = [...state.query]
47 | newQuery.shift()
48 | return {
49 | ...state,
50 | moveOpen: true,
51 | modalPayload: state.query[0].payload,
52 | storageIdsToClearFrom: initialStoragesToClear,
53 | query: newQuery
54 | }
55 | case 'CLOSE_MOVE_MODAL':
56 | return {
57 | ...state,
58 | moveOpen: false,
59 | totalFailed: initialState.totalFailed
60 | }
61 | case 'MOVE_MODAL_RESET_PAYLOAD':
62 | return {
63 | ...state,
64 | query: initialState.query
65 | }
66 | case 'MOVE_MODAL_CANCEL':
67 | return {
68 | ...state,
69 | doCancel: [...state.doCancel, action.payload.doCancel],
70 | totalFailed: initialState.totalFailed
71 | }
72 | case 'MODAL_RESET_STORAGE_IDS_TO_CLEAR_FROM':
73 | return {
74 | ...state,
75 | storageIdsToClearFrom: initialState.storageIdsToClearFrom
76 | }
77 | case 'MODAL_ADD_TO_FAILED':
78 | return {
79 | ...state,
80 | totalFailed: state.totalFailed + 1
81 | }
82 | case 'SIGN_OUT':
83 | return {
84 | ...initialState
85 | }
86 | default:
87 | return {...state}
88 |
89 | }
90 | };
91 |
92 |
93 | export default modalMoveReducer;
94 |
--------------------------------------------------------------------------------
/src/renderer/views/login/components/LoginTabs.tsx:
--------------------------------------------------------------------------------
1 | import { LockClosedIcon, QrcodeIcon, WifiIcon } from '@heroicons/react/solid';
2 | import { LoginMethod } from '../types/LoginMethod';
3 | import { classNames } from '../../../components/content/shared/filters/inventoryFunctions';
4 |
5 | interface TabProps {
6 | name: string;
7 | icon: any;
8 | key: LoginMethod;
9 | }
10 |
11 | const tabs: TabProps[] = [
12 | { name: 'QR', icon: QrcodeIcon, key: 'QR' },
13 | { name: 'Webtoken', icon: WifiIcon, key: 'WEBTOKEN' },
14 | { name: 'Regular', icon: LockClosedIcon, key: 'REGULAR' },
15 | ];
16 |
17 | type LoginTabsProps = {
18 | selectedTab: LoginMethod;
19 | setSelectedTab: (tab: LoginMethod) => void;
20 | };
21 |
22 | export default function LoginTabs({
23 | selectedTab,
24 | setSelectedTab,
25 | }: LoginTabsProps) {
26 | const defaultValue: LoginMethod = 'REGULAR';
27 | return (
28 |
29 |
30 |
31 |
34 | {/* Use an "onChange" listener to redirect the user to the selected tab URL. */}
35 |
45 |
46 |
47 |
69 |
70 |
71 |
72 | );
73 | }
74 |
--------------------------------------------------------------------------------
/src/renderer/views/login/HandleSuccess.tsx:
--------------------------------------------------------------------------------
1 | import combineInventory, { sortDataFunctionTwo } from "renderer/components/content/shared/filters/inventoryFunctions";
2 | import { filterItemRows } from "renderer/functionsClasses/filters/custom";
3 | import { DispatchIPC, DispatchStore } from "renderer/functionsClasses/rendererCommands/admin"
4 | import { State } from "renderer/interfaces/states";
5 | import { SignInActionPackage } from "renderer/interfaces/store/authReducerActionsInterfaces"
6 | import { inventorySetFilter } from "renderer/store/actions/filtersInventoryActions";
7 | import { setInventoryAction } from "renderer/store/inventory/inventoryActions";
8 | import { signIn } from "renderer/store/actions/userStatsActions";
9 | import { getURL } from "renderer/store/helpers/userStatusHelper";
10 | import { LoginCommandReturnPackage } from "shared/Interfaces.tsx/store"
11 | import { createCSGOImage } from "../../functionsClasses/createCSGOImage";
12 | async function getProfilePicture(steamID: string): Promise {
13 | try {
14 | const profilePicture = await getURL(steamID);
15 | return profilePicture as string;
16 | } catch (error) {
17 | return createCSGOImage("econ/characters/customplayer_tm_separatist");
18 | }
19 | }
20 | export async function handleSuccess(returnSuccessPackage: LoginCommandReturnPackage, dispatch: Function, currentState: State) {
21 | // Get Redux values
22 | const StoreClass = new DispatchStore(dispatch)
23 | const IPCClass = new DispatchIPC(dispatch)
24 |
25 | // Locale
26 | StoreClass.run(StoreClass.buildingObject.locale)
27 |
28 | // Currency
29 | IPCClass.run(IPCClass.buildingObject.currency)
30 | await new Promise((r) => setTimeout(r, 2500));
31 |
32 |
33 | // Create a store object
34 | let signInPackage: SignInActionPackage = {
35 | userProfilePicture: await getProfilePicture(returnSuccessPackage.steamID),
36 | displayName: returnSuccessPackage.displayName,
37 | CSGOConnection: returnSuccessPackage.haveGCSession,
38 | steamID: returnSuccessPackage.steamID,
39 | wallet: returnSuccessPackage.walletToSend
40 | }
41 |
42 | // Get the profile picture
43 |
44 | dispatch(signIn(signInPackage))
45 |
46 | // Inventory
47 | let combinedInventory = await combineInventory(
48 | returnSuccessPackage.csgoInventory,
49 | currentState.settingsReducer
50 | )
51 | dispatch(
52 | setInventoryAction({
53 | inventory: returnSuccessPackage.csgoInventory,
54 | combinedInventory
55 | })
56 | );
57 |
58 | // Filtered inventory
59 | let filteredInv = await filterItemRows(
60 | combinedInventory,
61 | currentState.inventoryFiltersReducer.inventoryFilter
62 | );
63 | filteredInv = await sortDataFunctionTwo(
64 | currentState.inventoryFiltersReducer.sortValue,
65 | filteredInv,
66 | currentState.pricingReducer.prices,
67 | currentState.settingsReducer?.source?.title
68 | );
69 |
70 | dispatch(
71 | inventorySetFilter(
72 | currentState.inventoryFiltersReducer.inventoryFilter,
73 | currentState.inventoryFiltersReducer.sortValue,
74 | filteredInv
75 | )
76 | );
77 | }
78 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/barChart.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Bar } from 'react-chartjs-2';
3 | import { useSelector } from 'react-redux';
4 | import {itemCategories} from 'renderer/components/content/shared/categories';
5 | import Chart from 'chart.js/auto';
6 | Chart
7 |
8 |
9 | export default function BarApp() {
10 | let categoriesFixed: Array = [];
11 |
12 | let resultingData = {} as any;
13 | itemCategories.forEach((element) => {
14 | categoriesFixed.push(element.name);
15 | resultingData[element.name] = {
16 | inventory: 0,
17 | storageUnits: 0
18 | }
19 | });
20 |
21 | // Radar options
22 | const options = {
23 | parsing: {
24 | key: 'nested.value',
25 | },
26 | legend: {
27 | position: 'top',
28 | labels: {
29 | fontColor: 'white',
30 | },
31 | },
32 | plugins: {
33 | title: {
34 | display: true,
35 | text: 'Items distribution'
36 | }
37 | },
38 | scales: {
39 | r: {
40 | angleLines: {
41 | color: 'rgba(255, 255, 255, 0.2)',
42 | },
43 |
44 | grid: {
45 | color: 'rgba(255, 255, 255, 0.2)',
46 | },
47 | ticks: {
48 | color: 'white',
49 | showLabelBackdrop: false,
50 | },
51 | },
52 | },
53 | };
54 |
55 | // Go through inventory and find matching categories
56 | const inventory = useSelector((state: any) => state.inventoryReducer);
57 | inventory.combinedInventory.forEach(element => {
58 | if (resultingData[element.category]) {
59 | resultingData[element.category].inventory = resultingData?.[element.category]?.inventory + element.combined_QTY
60 | }
61 | });
62 |
63 | // Go through Storage Units
64 | inventory.storageInventory.forEach(element => {
65 | console.log(element)
66 | if (resultingData[element.category]) {
67 | resultingData[element.category].storageUnits = resultingData?.[element.category]?.storageUnits + element.combined_QTY
68 | }
69 | });
70 |
71 | // Convert inventory to chart data
72 | let inventoryDataToUse: Array = [];
73 | let storageUnitDataToUse: Array = [];
74 |
75 | categoriesFixed.forEach(category => {
76 | inventoryDataToUse.push(resultingData[category].inventory)
77 | storageUnitDataToUse.push(resultingData[category].storageUnits)
78 | });
79 | console.log(storageUnitDataToUse)
80 |
81 |
82 | const data = {
83 | labels: categoriesFixed,
84 |
85 | datasets: [
86 | {
87 | label: 'Inventory',
88 | data: inventoryDataToUse,
89 | backgroundColor: 'rgba(255, 99, 132, 0.2)',
90 | borderColor: 'rgba(255, 99, 132, 1)',
91 | borderWidth: 1,
92 | },
93 | {
94 | label: 'Storage Units',
95 | data: storageUnitDataToUse,
96 | backgroundColor: 'rgb(50, 91, 136, 0.2)',
97 | borderColor: 'rgb(50, 91, 136, 1)',
98 | borderWidth: 1,
99 | },
100 | ],
101 | };
102 |
103 | return (
104 | <>
105 |
106 | >
107 | );
108 | }
109 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/prices.tsx:
--------------------------------------------------------------------------------
1 | import { ItemRow } from 'renderer/interfaces/items';
2 | import { Prices, Settings } from 'renderer/interfaces/states';
3 | import { pricing_add_to_requested } from 'renderer/store/actions/pricingActions';
4 |
5 | export class ConvertPrices {
6 | settingsData: Settings;
7 | prices: Prices;
8 |
9 | constructor(settingsData: Settings, prices: Prices) {
10 | this.settingsData = settingsData;
11 | this.prices = prices;
12 | }
13 |
14 | _getName(itemRow: ItemRow) {
15 | return itemRow.item_name + itemRow.item_wear_name || '';
16 | }
17 |
18 | getPrice(itemRow:ItemRow, nanToZero=false) {
19 | let itemPrice =
20 | this.prices.prices[this._getName(itemRow)]?.[
21 | this.settingsData.source.title
22 | ] * this.settingsData.currencyPrice[this.settingsData.currency];
23 |
24 | if (nanToZero && isNaN(itemPrice)) {
25 | return 0
26 | }
27 |
28 | return itemPrice
29 | }
30 | }
31 |
32 | export class ConvertPricesFormatted extends ConvertPrices {
33 | constructor(settingsData: Settings, prices: Prices) {
34 | super(settingsData, prices);
35 | }
36 |
37 | formatPrice(price: number) {
38 | return new Intl.NumberFormat(this.settingsData.locale, {
39 | style: 'currency',
40 | currency: this.settingsData.currency,
41 | }).format(price);
42 | }
43 |
44 | getFormattedPrice(itemRow: ItemRow) {
45 | return this.formatPrice(this.getPrice(itemRow));
46 | }
47 | getFormattedPriceCombined(itemRow: ItemRow) {
48 | let comQty = itemRow?.combined_QTY as number;
49 | return new Intl.NumberFormat(this.settingsData.locale, {
50 | style: 'currency',
51 | currency: this.settingsData.currency,
52 | }).format(comQty * this.getPrice(itemRow));
53 | }
54 | }
55 |
56 | async function requestPrice(priceToGet: Array) {
57 | window.electron.ipcRenderer.getPrice(priceToGet);
58 | }
59 |
60 | async function dispatchRequested(
61 | dispatch: Function,
62 | rowsToGet: Array
63 | ) {
64 | dispatch(pricing_add_to_requested(rowsToGet));
65 | }
66 |
67 | export class RequestPrices extends ConvertPrices {
68 | dispatch: Function;
69 | constructor(dispatch: Function, settingsData: Settings, prices: Prices) {
70 | super(settingsData, prices);
71 | this.dispatch = dispatch;
72 | }
73 |
74 | _checkRequested(itemRow: ItemRow): boolean {
75 | return (
76 | this.prices.productsRequested.includes(this._getName(itemRow)) == false
77 | );
78 | }
79 |
80 | handleRequested(itemRow: ItemRow): void {
81 | if (isNaN(this.getPrice(itemRow)) == true && this._checkRequested(itemRow)) {
82 | let rowsToSend = [itemRow];
83 | requestPrice(rowsToSend);
84 | dispatchRequested(this.dispatch, rowsToSend);
85 | }
86 | }
87 |
88 | handleRequestArray(itemRows: Array): void {
89 | let rowsToSend = [] as Array
90 | itemRows.forEach((itemRow) => {
91 | if (isNaN(this.getPrice(itemRow)) == true && this._checkRequested(itemRow)) {
92 | rowsToSend.push(itemRow)
93 | }
94 | });
95 | if (rowsToSend.length > 0) {
96 | requestPrice(rowsToSend);
97 | dispatchRequested(this.dispatch, rowsToSend);
98 |
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/sidebar/sideBar.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { useDispatch, useSelector } from 'react-redux';
3 | import { classNames } from 'renderer/components/content/shared/filters/inventoryFunctions';
4 | import { tradeUpAddRemove } from 'renderer/store/actions/tradeUpActions';
5 | import { createCSGOImage } from '../../../functionsClasses/createCSGOImage';
6 | import PossibleOutcomes from './possibleOutcomes';
7 |
8 | export default function TradeUpSideBar() {
9 | const tradeUpData = useSelector((state: any) => state.tradeUpReducer);
10 | const [itemHover, setItemHover] = useState('');
11 | const dispatch = useDispatch();
12 |
13 | let totalFloat = 0;
14 | tradeUpData.tradeUpProducts.forEach((element) => {
15 | totalFloat += element.item_paint_wear;
16 | });
17 | totalFloat = totalFloat / tradeUpData.tradeUpProducts.length;
18 |
19 |
20 | let productsToUse = [...tradeUpData.tradeUpProducts];
21 |
22 | while (true) {
23 | if (productsToUse.length != 10) {
24 | productsToUse.push({ item_name: 'EMPTY' });
25 | } else {
26 | break;
27 | }
28 | }
29 |
30 | return (
31 |
32 |
33 |
34 |
35 |
36 | {productsToUse.map((projectRow) => (
37 |
41 | {projectRow.item_name == 'EMPTY' ? (
42 |
48 | ) : (
49 |
67 | )}
68 |
69 | ))}
70 |
71 |
72 |
73 |
74 |
77 |
78 | );
79 | }
80 |
--------------------------------------------------------------------------------
/src/renderer/views/tradeUp/sidebar/sideBar.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { useDispatch, useSelector } from 'react-redux';
3 | import { classNames } from 'renderer/components/content/shared/filters/inventoryFunctions';
4 | import { tradeUpAddRemove } from 'renderer/store/actions/tradeUpActions';
5 | import { createCSGOImage } from '../../../functionsClasses/createCSGOImage';
6 | import PossibleOutcomes from './possibleOutcomes';
7 |
8 | export default function TradeUpSideBar() {
9 | const tradeUpData = useSelector((state: any) => state.tradeUpReducer);
10 | const [itemHover, setItemHover] = useState('');
11 | const dispatch = useDispatch();
12 |
13 | let totalFloat = 0;
14 | tradeUpData.tradeUpProducts.forEach((element) => {
15 | totalFloat += element.item_paint_wear;
16 | });
17 | totalFloat = totalFloat / tradeUpData.tradeUpProducts.length;
18 |
19 |
20 | let productsToUse = [...tradeUpData.tradeUpProducts];
21 |
22 | while (true) {
23 | if (productsToUse.length != 10) {
24 | productsToUse.push({ item_name: 'EMPTY' });
25 | } else {
26 | break;
27 | }
28 | }
29 |
30 | return (
31 |
32 |
33 |
34 |
35 |
36 | {productsToUse.map((projectRow) => (
37 |
41 | {projectRow.item_name == 'EMPTY' ? (
42 |
48 | ) : (
49 |
67 | )}
68 |
69 | ))}
70 |
71 |
72 |
73 |
74 |
77 |
78 | );
79 | }
80 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/categories.tsx:
--------------------------------------------------------------------------------
1 | export const itemCategories = [
2 | {
3 | value: 'characters',
4 | name: 'Agents',
5 | bgColorClass: 'bg-pink-500',
6 | href: '#',
7 | },
8 | {
9 | value: 'status_icons',
10 | name: 'Collectibles & Passes',
11 | bgColorClass: 'bg-red-500',
12 | href: '#',
13 | },
14 | {
15 | value: 'weapon_cases',
16 | name: 'Containers',
17 | bgColorClass: 'bg-indigo-500',
18 | href: '#',
19 | },
20 | {
21 | value: 'patches',
22 | name: 'Patches',
23 | bgColorClass: 'bg-indigo-200',
24 | href: '#',
25 | },
26 | {
27 | value: 'music_kits',
28 | name: 'Music kits',
29 | bgColorClass: 'bg-gray-500',
30 | href: '#',
31 | },
32 | {
33 | value: 'default_generated',
34 | name: 'Skins & Knives',
35 | bgColorClass: 'bg-green-500',
36 | href: '#',
37 | },
38 | {
39 | value: 'stickers',
40 | name: 'Stickers',
41 | bgColorClass: 'bg-yellow-500',
42 | href: '#',
43 | },
44 | { value: 'tools', name: 'Tools', bgColorClass: 'bg-yellow-800', href: '#' },
45 | ];
46 |
47 |
48 |
49 | export const itemSubCategories = {
50 | majors: {
51 | "Antwerp 2022": {
52 | name: "Antwerp 2022",
53 | key: "Antwerp 2022",
54 | year: 2021
55 | },
56 | "Stockholm 2021": {
57 | name: "Stockholm 2021",
58 | key: "Stockholm 2021",
59 | year: 2021
60 | },
61 | "2020 RMR": {
62 | name: "2020 RMR",
63 | key: "2020 RMR",
64 | year: 2020
65 | },
66 | "Berlin 2019": {
67 | name: "Berlin 2019",
68 | key: "Berlin 2019",
69 | year: 2019
70 | },
71 | "Katowice 2019": {
72 | name: "Katowice 2019",
73 | key: "Katowice 2019",
74 | year: 2019
75 | },
76 | "London 2018": {
77 | name: "London 2018",
78 | key: "London 2018",
79 | year: 2018
80 | },
81 | "Boston 2018": {
82 | name: "Boston 2018",
83 | key: "Boston 2018",
84 | year: 2018
85 | },
86 | "Krakow 2017": {
87 | name: "Krakow 2017",
88 | key: "Krakow 2017",
89 | year: 2017
90 | },
91 | "Atlanta 2017": {
92 | name: "Atlanta 2017",
93 | key: "Atlanta 2017",
94 | year: 2018
95 | },
96 | "Cologne 2016": {
97 | name: "Cologne 2016",
98 | key: "Cologne 2016",
99 | year: 2016
100 | },
101 | "Columbus 2016": {
102 | name: "Columbus 2016",
103 | key: "Columbus 2016",
104 | year: 2016
105 | },
106 | "Cluj-Napoca 2015": {
107 | name: "Cluj-Napoca 2015",
108 | key: "Cluj-Napoca 2015",
109 | year: 2015
110 | },
111 | "Cologne 2015": {
112 | name: "Cologne 2015",
113 | key: "Cologne 2015",
114 | year: 2015
115 | },
116 | "Katowice 2015": {
117 | name: "Katowice 2015",
118 | key: "Katowice 2015",
119 | year: 2015
120 | },
121 | "DreamHack 2014": {
122 | name: "DreamHack 2014",
123 | key: "DreamHack 2014",
124 | year: 2014
125 | },
126 | "Cologne 2014": {
127 | name: "Cologne 2014",
128 | key: "Cologne 2014",
129 | year: 2014
130 | },
131 | "Katowice 2014": {
132 | name: "Katowice 2014",
133 | key: "Katowice 2014",
134 | year: 2014
135 | }
136 | }
137 | }
--------------------------------------------------------------------------------
/src/renderer/store/reducer/tradeupReducer.tsx:
--------------------------------------------------------------------------------
1 | import { TradeUpActions } from "renderer/interfaces/states";
2 |
3 | const initialState: TradeUpActions = {
4 | tradeUpProducts: [],
5 | tradeUpProductsIDS: [],
6 | possibleOutcomes: [],
7 | searchInput: '',
8 | MinFloat: 0,
9 | MaxFloat: 1,
10 | collections: [],
11 | options: ["Hide equipped"],
12 | };
13 |
14 | const tradeUpReducer = (state = initialState, action) => {
15 | switch (action.type) {
16 | case 'TRADEUP_ADD_REMOVE':
17 | let toMoveAlreadyExists = state.tradeUpProducts.filter(row => row.item_id != action.payload.item_id)
18 | console.log(action.payload.item_id, toMoveAlreadyExists)
19 | if (toMoveAlreadyExists.length == state.tradeUpProducts.length) {
20 | toMoveAlreadyExists.push(action.payload)
21 | }
22 | let newTradeUpIDS = [] as any
23 | toMoveAlreadyExists.forEach(element => {
24 | newTradeUpIDS.push(element.item_id)
25 |
26 | });
27 | if (toMoveAlreadyExists.length != 10) {
28 | return {
29 | ...state,
30 | tradeUpProducts: toMoveAlreadyExists,
31 | tradeUpProductsIDS: newTradeUpIDS,
32 | possibleOutcomes: initialState.possibleOutcomes
33 | }
34 | } else {
35 | return {
36 | ...state,
37 | tradeUpProducts: toMoveAlreadyExists,
38 | tradeUpProductsIDS: newTradeUpIDS,
39 | }
40 | }
41 |
42 | case 'TRADEUP_ADDREMOVE_COLLECTION':
43 | let collectionAlreadyExists = state.collections.filter(row => row != action.payload)
44 | if (collectionAlreadyExists.length == state.collections.length) {
45 | collectionAlreadyExists.push(action.payload)
46 | }
47 | return {
48 | ...state,
49 | collections: collectionAlreadyExists
50 | }
51 |
52 | case 'TRADEUP_ADDREMOVE_OPTION':
53 | let optionAlready = state.options.filter(row => row != action.payload)
54 | if (optionAlready.length == state.options.length) {
55 | optionAlready.push(action.payload)
56 | }
57 | return {
58 | ...state,
59 | options: optionAlready
60 | }
61 | case 'TRADEUP_SET_SEARCH':
62 | return {
63 | ...state,
64 | searchInput: action.payload.searchField
65 | }
66 | case 'TRADEUP_SET_MIN':
67 | return {
68 | ...state,
69 | MinFloat: action.payload
70 | }
71 | case 'TRADEUP_SET_MAX':
72 | return {
73 | ...state,
74 | MaxFloat: action.payload
75 | }
76 | case 'TRADEUP_SET_POSSIBLE':
77 | return {
78 | ...state,
79 | possibleOutcomes: action.payload
80 | }
81 | case 'TRADEUP_RESET':
82 | return {
83 | ...initialState,
84 | collections: state.collections
85 | }
86 |
87 |
88 |
89 | case 'SIGN_OUT':
90 | return {
91 | ...initialState
92 | }
93 |
94 |
95 |
96 | default:
97 | return {...state}
98 |
99 | }
100 | };
101 |
102 | export default tradeUpReducer;
103 |
--------------------------------------------------------------------------------
/src/main/helpers/classes/steam/backup/currency.json:
--------------------------------------------------------------------------------
1 | {
2 | "rates": {
3 | "AFN":89.39913,
4 | "ALL":114.2613,
5 | "DZD":146.518,
6 | "AOA":435.8264,
7 | "ARS":122.4815,
8 | "AMD":429.9106,
9 | "AWG":1.8005,
10 | "AUD":1.420905,
11 | "AZN":1.7,
12 | "BSD":1.007131,
13 | "BHD":0.3768777,
14 | "BBD":2.033562,
15 | "BDT":93.65155,
16 | "BZD":2.030139,
17 | "BMD":1,
18 | "BTN":78.35473,
19 | "BOB":6.934398,
20 | "BAM":1.859508,
21 | "BWP":12.15659,
22 | "BRL":4.987385,
23 | "BND":1.391139,
24 | "BGN":1.85946,
25 | "BIF":2071.297,
26 | "XPF":113.69,
27 | "KHR":4091.082,
28 | "CAD":1.27725,
29 | "CVE":104.8346,
30 | "KYD":0.8393231,
31 | "CLP":844.63,
32 | "CLF":0.02571138183,
33 | "CNY":6.7089,
34 | "COP":3879.54,
35 | "CDF":2005,
36 | "CRC":691.5383,
37 | "HRK":7.1518,
38 | "CZK":23.49575,
39 | "DKK":7.075095,
40 | "DJF":179.3021,
41 | "DOP":55.39456,
42 | "XCD":2.70255,
43 | "EGP":18.71327,
44 | "ETB":52.39237,
45 | "FJD":2.1849,
46 | "GMD":54.05,
47 | "GBP":0.8113592,
48 | "GEL":2.915,
49 | "GHS":7.981841,
50 | "GTQ":7.780376,
51 | "GNF":8915.954,
52 | "GYD":210.8291,
53 | "HTG":115.3214,
54 | "HNL":24.74615,
55 | "HKD":7.849185,
56 | "HUF":378.506,
57 | "ISK":131.86,
58 | "INR":78.1435,
59 | "IDR":14614.95,
60 | "IRR":42350,
61 | "IQD":1469.985,
62 | "ILS":3.39429,
63 | "JMD":154.4742,
64 | "JPY":134.282,
65 | "JOD":0.709,
66 | "KZT":439.3801,
67 | "KES":117.8891,
68 | "KWD":0.30675,
69 | "KGS":79.5096,
70 | "LAK":14497.15,
71 | "LBP":1522.818,
72 | "LSL":15.86,
73 | "LRD":152,
74 | "LYD":4.814223,
75 | "MOP":8.142898,
76 | "MKD":58.58053,
77 | "MGA":4083.067,
78 | "MWK":1028.919,
79 | "MYR":4.402,
80 | "MVR":15.86,
81 | "MUR":44.09584,
82 | "MXN":19.948,
83 | "MDL":19.19158,
84 | "MAD":9.982791,
85 | "MZN":63.83,
86 | "MMK":1864.773,
87 | "NAD":15.86,
88 | "NPR":125.3679,
89 | "ANG":1.815174,
90 | "NZD":1.57473,
91 | "NIO":36.10667,
92 | "NGN":415.13,
93 | "NOK":9.7054,
94 | "OMR":0.3849781,
95 | "PKR":203.6998,
96 | "PAB":1.007131,
97 | "PGK":3.594505,
98 | "PYG":6909.679,
99 | "PHP":53.06,
100 | "PLN":4.37749,
101 | "QAR":3.641,
102 | "RON":4.6935,
103 | "RUB":57.6249,
104 | "RWF":1035.976,
105 | "SVC":8.812512,
106 | "SAR":3.7518,
107 | "RSD":111.5497,
108 | "SCR":14.22324,
109 | "SLL":13170,
110 | "SGD":1.386875,
111 | "SBD":8.113698,
112 | "SOS":582,
113 | "ZAR":15.8775,
114 | "KRW":1279.28,
115 | "VES":5.24725,
116 | "LKR":361.07,
117 | "SDG":456.5,
118 | "SRD":21.771,
119 | "SZL":15.71059,
120 | "SEK":10.00588,
121 | "CHF":0.9871805,
122 | "TJS":11.07882,
123 | "TZS":2346.701,
124 | "THB":34.811,
125 | "TOP":2.32435,
126 | "TTD":6.845028,
127 | "TND":3.0695,
128 | "TRY":17.21549,
129 | "TMT":3.5,
130 | "UGX":3716.486,
131 | "UAH":29.75803,
132 | "AED":3.673015,
133 | "USD":1,
134 | "UYU":39.78798,
135 | "UZS":11083.92,
136 | "VND":23182,
137 | "XOF":623.6518,
138 | "YER":250.25,
139 | "ZMW":17.0463,
140 | "ETH":0.0006766998,
141 | "EUR":0.950765,
142 | "LTC":0.01990445,
143 | "TWD":29.662,
144 | "PEN":3.78437
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/renderer/functionsClasses/storageUnits/storageUnitsClass.tsx:
--------------------------------------------------------------------------------
1 | import combineInventory, {
2 | sortDataFunction,
3 | } from 'renderer/components/content/shared/filters/inventoryFunctions';
4 | import { ItemRow, ItemRowStorage } from 'renderer/interfaces/items';
5 | import { State } from 'renderer/interfaces/states';
6 | import { inventorySetFilteredStorage } from 'renderer/store/actions/filtersInventoryActions';
7 | import { addStorageInventoryData } from 'renderer/store/inventory/inventoryActions';
8 | import { moveFromAddCasketToStorages } from 'renderer/store/actions/moveFromActions';
9 | import { filterItemRows } from '../filters/custom';
10 | import { RequestPrices } from '../prices';
11 |
12 | export class HandleStorageData {
13 | dispatch: Function;
14 | state: State;
15 | constructor(dispatch: Function, state: State) {
16 | this.dispatch = dispatch;
17 | this.state = state;
18 | }
19 |
20 | async addStorage(storageRow: ItemRow, addArray: Array = []) {
21 | // Adding the casket ID
22 | this.dispatch(moveFromAddCasketToStorages(storageRow.item_id));
23 |
24 | // Fetch the storage unit data
25 | let storageResult = await this._getStorageUnitData(storageRow);
26 | const ClassRequest = new RequestPrices(
27 | this.dispatch,
28 | this.state.settingsReducer,
29 | this.state.pricingReducer
30 | );
31 | ClassRequest.handleRequestArray(storageResult.combinedStorages);
32 | if (addArray.length == 0) {
33 | addArray = this.state.inventoryReducer.storageInventory
34 | }
35 | let filteredStorage = await filterItemRows(
36 | [...addArray, ...storageResult.combinedStorages],
37 | this.state.inventoryFiltersReducer.storageFilter
38 | );
39 | filteredStorage = await sortDataFunction(
40 | this.state.moveFromReducer.sortValue,
41 | filteredStorage,
42 | this.state.pricingReducer.prices,
43 | this.state.settingsReducer?.source?.title
44 | );
45 |
46 | this.dispatch(inventorySetFilteredStorage(this.state.inventoryFiltersReducer.storageFilter, filteredStorage))
47 | this.dispatch(
48 | addStorageInventoryData(
49 | storageResult.rawStorages,
50 | storageResult.combinedStorages,
51 | storageRow.item_id,
52 | this.state.moveFromReducer.sortValue
53 | )
54 | );
55 | return storageResult.combinedStorages
56 | }
57 |
58 | // Get storage unit
59 | async _getStorageUnitData(storageRow: ItemRow) {
60 | console.log(storageRow.item_id, storageRow.item_customname);
61 | let storageResult = await window.electron.ipcRenderer.getStorageUnitData(
62 | storageRow.item_id,
63 | storageRow.item_customname
64 | );
65 | let returnData: Array = storageResult[1];
66 |
67 | let finalReturnData = (await combineInventory(
68 | returnData,
69 | this.state.settingsReducer,
70 | {
71 | storage_id: storageRow.item_id,
72 | storage_name: storageRow.item_customname,
73 | }
74 | )) as Array;
75 | finalReturnData = await sortDataFunction(
76 | this.state.moveFromReducer.sortValue,
77 | finalReturnData,
78 | this.state.pricingReducer.prices,
79 | this.state.settingsReducer?.source?.title
80 | );
81 |
82 | returnData.forEach((element) => {
83 | element.storage_id = storageRow.item_id;
84 | element.storage_name = storageRow.item_customname as string;
85 | });
86 |
87 | return {
88 | combinedStorages: finalReturnData,
89 | rawStorages: returnData,
90 | };
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/modals & notifcations/notification.tsx:
--------------------------------------------------------------------------------
1 | /* This example requires Tailwind CSS v2.0+ */
2 | import { Fragment } from 'react';
3 | import { Transition } from '@headlessui/react';
4 | import { CheckCircleIcon, XCircleIcon } from '@heroicons/react/outline';
5 | import { XIcon } from '@heroicons/react/solid';
6 | import { useSelector } from 'react-redux';
7 | import { classNames } from '../filters/inventoryFunctions';
8 |
9 | export default function NotificationElement({
10 | success,
11 | titleToDisplay,
12 | textToDisplay,
13 | doShow,
14 | setShow,
15 | }) {
16 | const settingsData = useSelector((state: any) => state.settingsReducer);
17 | return (
18 | <>
19 | {/* Global notification live region, render this permanently at the end of the document */}
20 |
24 |
25 | {/* Notification panel, dynamically insert this into the live region when it needs to be displayed */}
26 |
36 |
37 |
38 |
39 |
40 | {success ? (
41 |
45 | ) : (
46 |
50 | )}
51 |
52 |
53 |
54 | {titleToDisplay}
55 |
56 |
57 | {textToDisplay}
58 |
59 |
60 |
61 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | >
78 | );
79 | }
80 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/filter/optionsDropdown.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from 'react'
2 | import { Popover, Transition } from '@headlessui/react'
3 | import { useDispatch, useSelector } from 'react-redux';
4 | import { tradeUpOptionsAddRemove } from 'renderer/store/actions/tradeUpActions';
5 |
6 | let optionsAvailable = ['Hide equipped']
7 |
8 | export default function TradeUpOptionsDropDown() {
9 |
10 | const tradeUpData = useSelector((state: any) => state.tradeUpReducer);
11 | const dispatch = useDispatch();
12 |
13 |
14 | return (
15 |
16 |
17 |
18 | Options
19 |
20 | {tradeUpData.options.length}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
37 |
38 |
59 |
60 |
61 |
62 |
63 | )
64 | }
--------------------------------------------------------------------------------
/src/renderer/views/tradeUp/filter/optionsDropdown.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from 'react'
2 | import { Popover, Transition } from '@headlessui/react'
3 | import { useDispatch, useSelector } from 'react-redux';
4 | import { tradeUpOptionsAddRemove } from 'renderer/store/actions/tradeUpActions';
5 |
6 | let optionsAvailable = ['Hide equipped']
7 |
8 | export default function TradeUpOptionsDropDown() {
9 |
10 | const tradeUpData = useSelector((state: any) => state.tradeUpReducer);
11 | const dispatch = useDispatch();
12 |
13 |
14 | return (
15 |
16 |
17 |
18 | Options
19 |
20 | {tradeUpData.options.length}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
37 |
38 |
59 |
60 |
61 |
62 |
63 | )
64 | }
--------------------------------------------------------------------------------
/src/renderer/views/overview/charts/pieChart.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Chart as ChartJS,
3 | RadialLinearScale,
4 | PointElement,
5 | LineElement,
6 | Filler,
7 | Tooltip,
8 | Legend,
9 | LinearScale,
10 | } from 'chart.js';
11 | import { Pie } from 'react-chartjs-2';
12 | import ChartDataLabels from 'chartjs-plugin-datalabels';
13 | import { ConvertPricesFormatted } from 'renderer/functionsClasses/prices';
14 | import { ReducerManager } from 'renderer/functionsClasses/reducerManager';
15 | import { useSelector } from 'react-redux';
16 | import { Prices, Settings } from 'renderer/interfaces/states';
17 |
18 | ChartJS.register(
19 | RadialLinearScale,
20 | PointElement,
21 | LinearScale,
22 | LineElement,
23 | Filler,
24 | Tooltip,
25 | Legend
26 | );
27 |
28 | export default function PieChart({ data, headerName }) {
29 | const ReducerClass = new ReducerManager(useSelector);
30 | let settingsData: Settings = ReducerClass.getStorage(
31 | ReducerClass.names.settings
32 | );
33 | let pricingData: Prices = ReducerClass.getStorage(ReducerClass.names.pricing);
34 | const converter = new ConvertPricesFormatted(settingsData, pricingData);
35 |
36 | const title = (tooltipItems) => {
37 | let percentageData: Array = [];
38 | let sum = 0;
39 |
40 | tooltipItems.dataset.data.forEach((element) => {
41 | sum += element;
42 | });
43 | tooltipItems.dataset.data.forEach((element) => {
44 | let percentage = (element * 100) / sum;
45 | percentageData.push(percentage);
46 | });
47 | if (settingsData.overview.by == 'price') {
48 | return (
49 | tooltipItems.label + ': ' + converter.formatPrice(tooltipItems.raw) + ' - ' + percentageData[tooltipItems.dataIndex].toFixed(2) + '%'
50 | );
51 | }
52 | return tooltipItems.label + ': ' + tooltipItems.raw + ' - ' + percentageData[tooltipItems.dataIndex].toFixed(2) + '%'
53 | };
54 |
55 | // Radar options
56 | const options = {
57 | plugins: {
58 | legend: {
59 | labels: {
60 | position: 'right',
61 | color: '#d6d3cd',
62 | },
63 | },
64 | title: {
65 | display: true,
66 | text: headerName,
67 | color: '#d6d3cd',
68 | },
69 | tooltip: {
70 | callbacks: {
71 | label: title,
72 | },
73 | },
74 | datalabels: {
75 | formatter: (value, ctx) => {
76 | let sum = 0;
77 | let dataArr = ctx.chart.data.datasets[0].data;
78 | dataArr.map((data) => {
79 | sum += data;
80 | });
81 | let percentage = ((value * 100) / sum).toFixed(2) + '%';
82 | return percentage;
83 | },
84 | color: '#fff',
85 | display: function (context) {
86 | let percentageData: Array = [];
87 | let sum = 0;
88 |
89 | context.dataset.data.forEach((element) => {
90 | sum += element;
91 | });
92 | context.dataset.data.forEach((element) => {
93 | let percentage = (element * 100) / sum;
94 | percentageData.push(percentage);
95 | });
96 |
97 | if (percentageData[context.dataIndex] > 4) {
98 | return true;
99 | }
100 | if (percentageData[context.dataIndex] > 2) {
101 | return 'auto';
102 | }
103 | return false;
104 |
105 | },
106 | },
107 | },
108 | };
109 |
110 | return (
111 | <>
112 |
113 |
116 | >
117 | );
118 | }
119 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/radarChart copy.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Chart as ChartJS,
3 | RadialLinearScale,
4 | PointElement,
5 | LineElement,
6 | Filler,
7 | Tooltip,
8 | Legend,
9 | LinearScale,
10 | } from 'chart.js';
11 | import { Radar } from 'react-chartjs-2';
12 | import { useSelector } from 'react-redux';
13 | import {itemCategories} from 'renderer/components/content/shared/categories';
14 |
15 | ChartJS.register(
16 | RadialLinearScale,
17 | PointElement,
18 | LinearScale,
19 | LineElement,
20 | Filler,
21 | Tooltip,
22 | Legend
23 | );
24 |
25 |
26 | export default function RadarApp() {
27 | let categoriesFixed: Array = [];
28 |
29 | let resultingData = {} as any;
30 | itemCategories.forEach((element) => {
31 | categoriesFixed.push(element.name);
32 | resultingData[element.name] = {
33 | inventory: 0,
34 | storageUnits: 0
35 | }
36 | });
37 |
38 | // Radar options
39 | const options = {
40 | plugins: {
41 | legend: {
42 | labels: {
43 | color: '#d6d3cd',
44 | },
45 |
46 | },
47 | title: {
48 | display: true,
49 | text: 'Items',
50 | color: '#d6d3cd'
51 | }
52 | },
53 | parsing: {
54 | key: 'nested.value',
55 | },
56 | legend: {
57 | position: 'top',
58 | labels: {
59 | fontColor: 'white',
60 | },
61 | },
62 | title: {
63 | display: true,
64 | text: 'Chart.js Radar Chart',
65 | fontColor: 'white',
66 | },
67 | scales: {
68 | r: {
69 | angleLines: {
70 | color: 'rgba(255, 255, 255, 0.2)',
71 | },
72 |
73 | grid: {
74 | color: 'rgba(255, 255, 255, 0.2)',
75 | },
76 | ticks: {
77 | color: 'white',
78 | showLabelBackdrop: false,
79 | },
80 | },
81 | },
82 | };
83 |
84 | // Go through inventory and find matching categories
85 | const inventory = useSelector((state: any) => state.inventoryReducer);
86 | inventory.combinedInventory.forEach(element => {
87 | if (resultingData[element.category]) {
88 | resultingData[element.category].inventory = resultingData?.[element.category]?.inventory + element.combined_QTY
89 | }
90 | });
91 |
92 | // Go through Storage Units
93 | inventory.storageInventory.forEach(element => {
94 | console.log(element)
95 | if (resultingData[element.category]) {
96 | resultingData[element.category].storageUnits = resultingData?.[element.category]?.storageUnits + element.combined_QTY
97 | }
98 | });
99 |
100 | // Convert inventory to chart data
101 | let inventoryDataToUse: Array = [];
102 | let storageUnitDataToUse: Array = [];
103 |
104 | categoriesFixed.forEach(category => {
105 | inventoryDataToUse.push(resultingData[category].inventory)
106 | storageUnitDataToUse.push(resultingData[category].storageUnits)
107 | });
108 | console.log(storageUnitDataToUse)
109 |
110 |
111 | const data = {
112 | labels: categoriesFixed,
113 |
114 | datasets: [
115 | {
116 | label: 'Inventory',
117 | data: inventoryDataToUse,
118 | backgroundColor: 'rgba(255, 99, 132, 0.2)',
119 | borderColor: 'rgba(255, 99, 132, 1)',
120 | borderWidth: 1,
121 | },
122 | {
123 | label: 'Storage Units',
124 | data: storageUnitDataToUse,
125 | backgroundColor: 'rgb(50, 91, 136, 0.2)',
126 | borderColor: 'rgb(50, 91, 136, 1)',
127 | borderWidth: 1,
128 | },
129 |
130 | ],
131 | };
132 |
133 | return (
134 | <>
135 |
136 | >
137 | );
138 | }
139 |
--------------------------------------------------------------------------------
/src/renderer/store/reducer/moveFromReducers.tsx:
--------------------------------------------------------------------------------
1 | import { MoveFromReducer } from "renderer/interfaces/states";
2 |
3 | const initialState: MoveFromReducer = {
4 | hideFull: false,
5 | activeStorages: [],
6 | totalToMove: [],
7 | totalItemsToMove: 0,
8 | searchInput: '',
9 | searchInputStorage: '',
10 | sortValue: 'Default',
11 | doCancel: false,
12 | sortBack: false,
13 | };
14 |
15 | const moveFromReducer = (state = initialState, action) => {
16 | switch (action.type) {
17 | case 'MOVE_FROM_SET_FULL':
18 | return {
19 | ...state,
20 | hideFull: !state.hideFull
21 | }
22 | case 'MOVE_FROM_SET_SORT_BACK':
23 | return {
24 | ...state,
25 | sortBack: !state.sortBack
26 | }
27 | case 'MOVE_FROM_ADD_TO':
28 | // Add to or remove from active storages
29 | let casketAlreadyExists = state.activeStorages.indexOf(action.payload.casketID) > -1;
30 | let chosenActiveCopy = state.activeStorages.slice();
31 |
32 | if (casketAlreadyExists) {
33 | chosenActiveCopy = chosenActiveCopy.filter(id => id != action.payload.casketID)
34 | } else {
35 | chosenActiveCopy.push(action.payload.casketID)
36 | }
37 | return {
38 | ...state,
39 | activeStorages: chosenActiveCopy
40 | }
41 | case 'MOVE_FROM_CLEAR':
42 | return {
43 | ...initialState
44 | }
45 | case 'MOVE_FROM_TOTAL_TO_ADD':
46 | let toMoveAlreadyExists = state.totalToMove.filter(row => row[0] != action.payload.itemID)
47 |
48 | if (action.payload.toMove.length > 0) {
49 | toMoveAlreadyExists.push([action.payload.itemID, action.payload.casketID, action.payload.toMove, action.payload.itemName])
50 | }
51 | let newTotalItemsToMove = 0
52 | toMoveAlreadyExists.forEach(element => {
53 | newTotalItemsToMove += element[2].length
54 | });
55 | return {
56 | ...state,
57 | totalToMove: toMoveAlreadyExists,
58 | totalItemsToMove: newTotalItemsToMove
59 | }
60 | case 'MOVE_FROM_ALL_CASKET_RESULTS':
61 | let allCasketResults = state.totalToMove.filter(row => row[1] != action.payload.casketID)
62 |
63 | let allCasketToRemoveTotal = 0
64 | allCasketResults.forEach(element => {
65 | allCasketToRemoveTotal += element[2].length
66 | });
67 | return {
68 | ...state,
69 | totalToMove: allCasketResults,
70 | totalItemsToMove: allCasketToRemoveTotal
71 | }
72 |
73 | case 'MOVE_FROM_SET_SEARCH':
74 | return {
75 | ...state,
76 | searchInput: action.payload.searchField
77 | }
78 | case 'MOVE_FROM_SET_SEARCH_STORAGE':
79 | return {
80 | ...state,
81 | searchInputStorage: action.payload.searchField
82 | }
83 | case 'SET_SORT':
84 | if (state.sortValue == action.payload.sortValue) {
85 | return {
86 | ...state,
87 | sortBack: !state.sortBack
88 | }
89 | } else {
90 | return {
91 | ...state,
92 | sortValue: action.payload.sortValue,
93 | sortBack: initialState.sortBack
94 | }
95 | }
96 | case 'MOVE_FROM_CLEAR_ALL':
97 | return {
98 | ...state,
99 | totalToMove: [] as any,
100 | totalItemsToMove: 0,
101 | searchInput: '',
102 | sortValue: 'Default'
103 | }
104 |
105 | case 'DO_CANCEL':
106 | return {
107 | ...state,
108 | doCancel: action.payload.doCancel
109 | }
110 | case 'SIGN_OUT':
111 | return {
112 | ...initialState
113 | }
114 |
115 |
116 |
117 | default:
118 | return { ...state }
119 |
120 | }
121 | };
122 |
123 | export default moveFromReducer;
124 |
--------------------------------------------------------------------------------
/src/renderer/store/reducer/moveToReducers.tsx:
--------------------------------------------------------------------------------
1 | import { MoveToReducer } from "renderer/interfaces/states";
2 |
3 | const initialState: MoveToReducer = {
4 | doHide: false,
5 | hideFull: true,
6 | activeStorages: [],
7 | activeStoragesAmount: 0,
8 | totalToMove: [],
9 | totalItemsToMove: 0,
10 | searchInput: '',
11 | searchInputStorage: '',
12 | sortValue: 'Default',
13 | doCancel: false,
14 | sortBack: false,
15 | };
16 |
17 | const moveFromReducer = (state = initialState, action) => {
18 | switch (action.type) {
19 | case 'MOVE_TO_SET_HIDE':
20 | return {
21 | ...state,
22 | doHide: !state.doHide
23 | }
24 |
25 | case 'MOVE_TO_SET_FULL':
26 | return {
27 | ...state,
28 | hideFull: !state.hideFull
29 | }
30 | case 'MOVE_TO_ADD_TO':
31 | // Add to or remove from active storages
32 | console.log(action.payload.casketID)
33 | let casketAlreadyExists = state.activeStorages.indexOf(action.payload.casketID) > -1;
34 | let chosenActiveCopy = state.activeStorages.slice();
35 | let storageAmount = 0
36 | if (casketAlreadyExists) {
37 | chosenActiveCopy = []
38 | } else {
39 | chosenActiveCopy = [action.payload.casketID]
40 | storageAmount = action.payload.casketVolume
41 | }
42 | console.log(chosenActiveCopy)
43 | return {
44 | ...state,
45 | activeStorages: chosenActiveCopy,
46 | activeStoragesAmount: storageAmount
47 |
48 | }
49 | case 'MOVE_TO_TOTAL_TO_ADD':
50 | let toMoveAlreadyExists = state.totalToMove.filter(row => row[0] != action.payload.itemID)
51 |
52 | if (action.payload.toMove.length > 0) {
53 | toMoveAlreadyExists.push([action.payload.itemID, action.payload.casketID, action.payload.toMove, action.payload.itemName])
54 | }
55 | let newTotalItemsToMove = 0
56 | toMoveAlreadyExists.forEach(element => {
57 | newTotalItemsToMove += element[2].length
58 | });
59 | return {
60 | ...state,
61 | totalToMove: toMoveAlreadyExists,
62 | totalItemsToMove: newTotalItemsToMove
63 | }
64 |
65 | case 'SET_STORAGE_AMOUNT':
66 | return {
67 | ...state,
68 | activeStoragesAmount: action.payload.storageAmount
69 | }
70 |
71 | case 'MOVE_TO_SET_SEARCH':
72 | return {
73 | ...state,
74 | searchInput: action.payload.searchField
75 | }
76 |
77 | case 'MOVE_TO_SET_SEARCH_STORAGE':
78 | return {
79 | ...state,
80 | searchInputStorage: action.payload.searchField
81 | }
82 | case 'SET_SORT':
83 | if (state.sortValue == action.payload.sortValue) {
84 | return {
85 | ...state,
86 | sortBack: !state.sortBack
87 | }
88 | } else {
89 | return {
90 | ...state,
91 | sortValue: action.payload.sortValue,
92 | sortBack: initialState.sortBack
93 | }
94 | }
95 | case 'MOVE_TO_CLEAR_ALL':
96 | return {
97 | ...state,
98 | totalToMove: [] as any,
99 | totalItemsToMove: 0,
100 | searchInput: '',
101 | sortValue: 'Default'
102 | }
103 | case 'DO_CANCEL':
104 |
105 | return {
106 | ...state,
107 | doCancel: action.payload.doCancel
108 | }
109 | case 'SIGN_OUT':
110 | return {
111 | ...initialState
112 | }
113 |
114 |
115 |
116 | default:
117 | return {...state}
118 |
119 | }
120 | };
121 |
122 | export default moveFromReducer;
123 |
--------------------------------------------------------------------------------
/src/renderer/views/overview/overviewOptionsDropdown.tsx:
--------------------------------------------------------------------------------
1 | /* This example requires Tailwind CSS v2.0+ */
2 | import { Fragment } from 'react'
3 | import { Listbox, Transition } from '@headlessui/react'
4 | import { CheckIcon, SelectorIcon } from '@heroicons/react/solid'
5 | import { classNames } from 'renderer/components/content/shared/filters/inventoryFunctions'
6 | import { Overview, Settings } from 'renderer/interfaces/states'
7 | import { useDispatch, useSelector } from 'react-redux'
8 | import { ReducerManager } from 'renderer/functionsClasses/reducerManager'
9 | import { setOverview } from 'renderer/store/actions/settings'
10 |
11 | interface params {
12 | optionsObject: any
13 | keyToUse: keyof Overview
14 | }
15 |
16 | export default function ListBoxOptions({optionsObject, keyToUse}: params) {
17 |
18 | const dispatch = useDispatch();
19 | const ReducerClass = new ReducerManager(useSelector);
20 | const settingsData: Settings = ReducerClass.getStorage(ReducerClass.names.settings)
21 | let selected = settingsData.overview[keyToUse]
22 |
23 | async function updateOverview(valueToset: any) {
24 | let newOverviewValue: Overview = settingsData.overview
25 | // @ts-ignore
26 | newOverviewValue[keyToUse] = valueToset
27 |
28 | dispatch(setOverview(newOverviewValue));
29 | window.electron.store.set('overview', newOverviewValue);
30 | window.electron.ipcRenderer.refreshInventory();
31 | }
32 |
33 | return (
34 |
35 | {({ open }) => (
36 | <>
37 |
38 |
39 | {optionsObject[selected]}
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 | {Object.entries(optionsObject).map(([key, name]: any) => (
54 |
57 | classNames(
58 | active ? 'bg-dark-level-four' : '',
59 | 'cursor-default select-none text-dark-white relative py-2 pl-3 pr-9'
60 | )
61 | }
62 | value={key}
63 | >
64 | {({ selected, active }) => (
65 | <>
66 |
67 | {name}
68 |
69 |
70 | {selected ? (
71 |
77 |
78 |
79 | ) : null}
80 | >
81 | )}
82 |
83 | ))}
84 |
85 |
86 |
87 | >
88 | )}
89 |
90 | )
91 | }
92 |
--------------------------------------------------------------------------------
/src/renderer/store/actions/filtersInventoryActions.tsx:
--------------------------------------------------------------------------------
1 | import { sortDataFunction } from "renderer/components/content/shared/filters/inventoryFunctions"
2 | import { Filter } from "renderer/interfaces/filters"
3 | import { State } from "renderer/interfaces/states"
4 | import _ from 'lodash';
5 | import { filterItemRows } from "renderer/functionsClasses/filters/custom";
6 |
7 | export const allButClear = (filterString: any, sortValue, inventoryFiltered) => {
8 | return {
9 | type: 'ALL_BUT_CLEAR',
10 | payload: {
11 | inventoryFilter: filterString,
12 | sortValue: sortValue,
13 | inventoryFiltered: inventoryFiltered
14 |
15 | }
16 | }
17 | }
18 | export const inventorySetFilteredStorage = (storageFilter, storageFiltered) => {
19 | return {
20 | type: 'SET_FILTERED_STORAGE',
21 | payload: {
22 | storageFiltered,
23 | storageFilter
24 |
25 | }
26 | }
27 | }
28 | export const inventorySetFilter = (inventoryFilter: any, sortValue, inventoryFiltered) => {
29 | return {
30 | type: 'SET_FILTERED',
31 | payload: {
32 | inventoryFilter,
33 | sortValue,
34 | inventoryFiltered
35 | }
36 | }
37 | }
38 | export const filterInventoryClearAll = () => {
39 | return {
40 | type: 'CLEAR_ALL'
41 | }
42 | }
43 | export const inventoryFilterSetSearch = (searchField) => {
44 | return {
45 | type: 'INVENTORY_FILTERS_SET_SEARCH',
46 | payload: {
47 | searchField: searchField
48 | }
49 | }
50 | }
51 |
52 | export const inventoryAddCategoryFilter = (filterToAdd) => {
53 | return {
54 | type: 'INVENTORY_ADD_CATEGORY_FILTER',
55 | payload: filterToAdd
56 | }
57 | }
58 | export const inventoryAddRarityFilter = (filterToAdd) => {
59 | return {
60 | type: 'INVENTORY_ADD_RARITY_FILTER',
61 | payload: filterToAdd
62 | }
63 | }
64 |
65 | export async function storageInventoryAddOption(currentState: State, newFilter: Filter) {
66 | let newFilterState = [] as Array;
67 | let wasSeen: boolean = false;
68 | currentState.inventoryFiltersReducer.storageFilter.forEach(element => {
69 | if (!_.isEqual(element, newFilter)) {
70 | newFilterState.push(element)
71 |
72 | } else {
73 | wasSeen = true;
74 | }
75 | });
76 |
77 | if (!wasSeen) {
78 | newFilterState.push(newFilter)
79 | }
80 |
81 | let filteredStorage = await filterItemRows(currentState.inventoryReducer.storageInventory, newFilterState)
82 | filteredStorage = await sortDataFunction(currentState.moveFromReducer.sortValue, filteredStorage, currentState.pricingReducer.prices, currentState.settingsReducer?.source?.title)
83 | return inventorySetFilteredStorage(newFilterState, filteredStorage)
84 | }
85 |
86 | export async function filterInventoryAddOption(currentState: State, newFilter: Filter) {
87 | let newFilterState = [] as Array;
88 | let wasSeen: boolean = false;
89 | currentState.inventoryFiltersReducer.inventoryFilter.forEach(element => {
90 | if (!_.isEqual(element, newFilter)) {
91 | newFilterState.push(element)
92 |
93 | } else {
94 | wasSeen = true;
95 | }
96 | });
97 |
98 | if (!wasSeen) {
99 | newFilterState.push(newFilter)
100 | }
101 | let filteredInv = await filterItemRows(currentState.inventoryReducer.combinedInventory, newFilterState)
102 | filteredInv = await sortDataFunction(currentState.inventoryFiltersReducer.sortValue, filteredInv, currentState.pricingReducer.prices, currentState.settingsReducer?.source?.title)
103 | return inventorySetFilter(newFilterState, currentState.inventoryFiltersReducer.sortValue, filteredInv)
104 | }
105 |
106 | export async function filterInventorySetSort(currentState: State, newSort: string) {
107 | let inventoryData = sortDataFunction(newSort, currentState.inventoryReducer.inventory, currentState.pricingReducer.prices, currentState.settingsReducer?.source?.title)
108 | return allButClear(currentState.inventoryFiltersReducer.inventoryFilter, newSort, inventoryData)
109 | }
110 |
--------------------------------------------------------------------------------
/src/renderer/components/content/shared/modals & notifcations/modalTradeResult.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from 'react';
2 | import { Dialog, Transition } from '@headlessui/react';
3 | import { useDispatch, useSelector } from 'react-redux';
4 | import { setTradeMoveResult } from 'renderer/store/actions/modalTrade';
5 | import { tradeUpResetPossible } from 'renderer/store/actions/tradeUpActions';
6 | import { createCSGOImage } from '../../../../functionsClasses/createCSGOImage';
7 |
8 | export default function TradeResultModal() {
9 | const dispatch = useDispatch();
10 | const modalData = useSelector((state: any) => state.modalTradeReducer);
11 |
12 | let devMode = false;
13 |
14 | async function setDone() {
15 | dispatch(setTradeMoveResult())
16 | dispatch(tradeUpResetPossible())
17 | }
18 |
19 |
20 | return (
21 |
22 |
89 |
90 | );
91 | }
92 |
--------------------------------------------------------------------------------
/src/renderer/store/inventory/inventoryClass.tsx:
--------------------------------------------------------------------------------
1 | import { Inventory } from "renderer/interfaces/states";
2 | import { InventoryMatchingObject } from "./inventoryInterfaces";
3 |
4 | const initialState: Inventory = {
5 | inventory: [],
6 | combinedInventory: [],
7 | storageInventory: [],
8 | storageInventoryRaw: [],
9 | totalAccountItems: 0,
10 | itemsLookUp: {}
11 | };
12 |
13 |
14 | export class InventoryActionsReducer {
15 |
16 | matchingObject: InventoryMatchingObject = {
17 | 'INVENTORY_SET_INVENTORY': this.setInventory,
18 | 'INVENTORY_STORAGES_ADD_TO': this.addStorageUnitsItems,
19 | 'INVENTORY_STORAGES_CLEAR_CASKET': this.clearStorageUnitItems,
20 | 'INVENTORY_STORAGES_SET_SORT_STORAGES': this.setSortStorageUnits,
21 | 'INVENTORY_STORAGES_CLEAR_ALL': this.clearAllStorageUnits,
22 | 'MOVE_FROM_CLEAR': this.clearAllStorageUnits,
23 | 'SIGN_OUT': this.initialState
24 |
25 | }
26 | relevantFunction: Function
27 | state: Inventory
28 | action
29 |
30 | constructor(state = initialState, action: any) {
31 | this.relevantFunction = this.default
32 | if (action.type in this.matchingObject) {
33 | this.relevantFunction = this.matchingObject[action.type]
34 | }
35 | this.state = state
36 | this.action = action
37 | }
38 |
39 | // Default
40 | default() {
41 | return {
42 | ...this.state
43 | }
44 | }
45 |
46 | // Initial state
47 | initialState() {
48 | return {
49 | ...initialState
50 | }
51 | }
52 |
53 |
54 |
55 | // Set the inventory whenever it changes
56 | setInventory() {
57 | let storageTotal = 0
58 |
59 | this.action.payload.inventory.forEach(element => {
60 | storageTotal += 1
61 | if (element.item_url == "econ/tools/casket") {
62 | storageTotal += element.item_storage_total
63 | }
64 | });
65 |
66 |
67 |
68 | return {
69 | ...this.state,
70 | inventory: this.action.payload.inventory,
71 | combinedInventory: this.action.payload.combinedInventory,
72 | totalAccountItems: storageTotal
73 | }
74 | }
75 |
76 | // Add storage unit items
77 | addStorageUnitsItems() {
78 | const add_to_filtered = this.state.storageInventory?.filter(id => id.storage_id != this.action.payload.casketID) || []
79 | const add_to_filtered_raw = this.state.storageInventoryRaw?.filter(id => id.storage_id != this.action.pay) || []
80 | this.action.payload.storageData.forEach(storageRow => add_to_filtered.push(storageRow))
81 | this.action.payload.storageRowsRaw.forEach(storageRow => {
82 | add_to_filtered_raw.push(storageRow)
83 | })
84 |
85 | return {
86 | ...this.state,
87 | storageInventory: add_to_filtered,
88 | storageInventoryRaw: add_to_filtered_raw
89 | }
90 | }
91 |
92 | // Clear a caskets storage unit items
93 | clearStorageUnitItems() {
94 | const AddToFiltered = this.state.storageInventory.filter(id => id.storage_id != this.action.payload.casketID)
95 | const AddToFilteredRaw = this.state.storageInventoryRaw.filter(id => id.storage_id != this.action.payload.casketID)
96 | return {
97 | ...this.state,
98 | storageInventory: AddToFiltered,
99 | storageInventoryRaw: AddToFilteredRaw
100 | }
101 | }
102 |
103 | // Set storage unit sort
104 | setSortStorageUnits() {
105 | return {
106 | ...this.state,
107 | storageInventory: this.action.payload.storageData
108 | }
109 | }
110 |
111 | // Clear all storage units
112 | clearAllStorageUnits() {
113 | return {
114 | ...this.state,
115 | storageInventory: initialState.storageInventory,
116 | storageInventoryRaw: initialState.storageInventoryRaw
117 | }
118 | }
119 |
120 | }
121 |
122 | export function inventoryReducer(state = initialState, action) {
123 | return new InventoryActionsReducer(state, action).relevantFunction()
124 | }
125 |
126 |
--------------------------------------------------------------------------------