diff --git a/src/application/README.md b/src/application/README.md new file mode 100644 index 0000000..c4c63fc --- /dev/null +++ b/src/application/README.md @@ -0,0 +1,6 @@ +## Application + +* This layer contains application logic. +* It only knows of the Domain Layer and the Infrastructure Layer. +* The services are implemented with [Vue Composable Functions](https://vueschool.io/articles/vuejs-tutorials/what-is-a-vue-js-composable/) + diff --git a/src/composable-functions/useModal.ts b/src/application/services/useModal.ts similarity index 100% rename from src/composable-functions/useModal.ts rename to src/application/services/useModal.ts diff --git a/src/composable-functions/useShoppingInit.ts b/src/application/services/useShoppingInit.ts similarity index 66% rename from src/composable-functions/useShoppingInit.ts rename to src/application/services/useShoppingInit.ts index 87bb3f2..536b3df 100644 --- a/src/composable-functions/useShoppingInit.ts +++ b/src/application/services/useShoppingInit.ts @@ -1,7 +1,6 @@ import { onMounted } from "vue"; -import { useStore } from "@/store"; - -import { ACTIONS } from "@/enums/shopping"; +import { useStore } from "@/infrastructure/store"; +import { ACTIONS } from "@/infrastructure/store/shopping/shopping.types"; export default function useShoppingInit() { const store = useStore(); diff --git a/src/composable-functions/useShoppingProducts.ts b/src/application/services/useShoppingProducts.ts similarity index 69% rename from src/composable-functions/useShoppingProducts.ts rename to src/application/services/useShoppingProducts.ts index eea900f..3be34b0 100644 --- a/src/composable-functions/useShoppingProducts.ts +++ b/src/application/services/useShoppingProducts.ts @@ -1,10 +1,11 @@ import { computed } from "vue"; -import { useStore } from "@/store"; +import { useStore } from "@/infrastructure/store"; -import { Product } from "@/domain/checkout/checkout.types"; - -import PRODUCT_CODE from "@/enums/product"; -import { ACTIONS, GETTERS } from "@/enums/shopping"; +import { Product, PRODUCT_CODE } from "@/domain/checkout/checkout.types"; +import { + ACTIONS, + GETTERS +} from "@/infrastructure/store/shopping/shopping.types"; export default function useShopping() { const store = useStore(); diff --git a/src/composable-functions/useShoppingSummary.ts b/src/application/services/useShoppingSummary.ts similarity index 87% rename from src/composable-functions/useShoppingSummary.ts rename to src/application/services/useShoppingSummary.ts index 1ff96fe..fc40e6c 100644 --- a/src/composable-functions/useShoppingSummary.ts +++ b/src/application/services/useShoppingSummary.ts @@ -1,8 +1,8 @@ import { computed } from "vue"; -import { useStore } from "@/store"; +import { useStore } from "@/infrastructure/store"; -import { GETTERS } from "@/enums/shopping"; import { TotalDiscountItem } from "@/domain/checkout/checkout.types"; +import { GETTERS } from "@/infrastructure/store/shopping/shopping.types"; export default function useShopping() { const store = useStore(); diff --git a/src/domain/README.md b/src/domain/README.md new file mode 100644 index 0000000..a94e8d1 --- /dev/null +++ b/src/domain/README.md @@ -0,0 +1,5 @@ +## Domain + +* This layer is for domain/business logic. +* Only business logic lives in the Domain layer +* It is just pure TypeScript code with no frameworks/libraries whatsoever here. diff --git a/src/domain/checkout/checkout.service.ts b/src/domain/checkout/checkout.service.ts index 621a3d0..82bd5f1 100644 --- a/src/domain/checkout/checkout.service.ts +++ b/src/domain/checkout/checkout.service.ts @@ -1,5 +1,5 @@ -import PRODUCT_CODE from "@/enums/product"; -import DISCOUNT_CODE from "@/enums/discount"; +import { PRODUCT_CODE } from "@/domain/checkout/checkout.types"; +import { DISCOUNT_CODE } from "@/domain/discount-rules/discount.rules.types"; import { PricingRule, diff --git a/src/domain/checkout/checkout.types.ts b/src/domain/checkout/checkout.types.ts index 8e75831..cc1e7df 100644 --- a/src/domain/checkout/checkout.types.ts +++ b/src/domain/checkout/checkout.types.ts @@ -1,5 +1,11 @@ -import PRODUCT_CODE from "@/enums/product"; -import DISCOUNT_CODE from "@/enums/discount"; +import { DISCOUNT_CODE } from "@/domain/discount-rules/discount.rules.types"; + +export enum PRODUCT_CODE { + CAP = "CAP", + TSHIRT = "TSHIRT", + MUG = "MUG", + EMPTY = "EMPTY" +} export interface PricingRule { code: PRODUCT_CODE; diff --git a/src/domain/discount-rules/discount.rules.factory.ts b/src/domain/discount-rules/discount.rules.factory.ts index 4eb32e6..25cd9bd 100644 --- a/src/domain/discount-rules/discount.rules.factory.ts +++ b/src/domain/discount-rules/discount.rules.factory.ts @@ -1,5 +1,5 @@ -import PRODUCT_CODE from "@/enums/product"; -import DISCOUNT_CODE from "@/enums/discount"; +import { PRODUCT_CODE } from "@/domain/checkout/checkout.types"; +import { DISCOUNT_CODE } from "@/domain/discount-rules/discount.rules.types"; import { ScannerItem } from "@/domain/checkout/checkout.types"; import { DiscountRule } from "@/domain/discount-rules/discount.rules.types"; diff --git a/src/domain/discount-rules/discount.rules.service.ts b/src/domain/discount-rules/discount.rules.service.ts index ccf5076..5ed1d42 100644 --- a/src/domain/discount-rules/discount.rules.service.ts +++ b/src/domain/discount-rules/discount.rules.service.ts @@ -1,4 +1,4 @@ -import DISCOUNT_CODE from "@/enums/discount"; +import { DISCOUNT_CODE } from "@/domain/discount-rules/discount.rules.types"; import { DiscountRule } from "@/domain/discount-rules/discount.rules.types"; import { discountFactory } from "@/domain/discount-rules/discount.rules.factory"; diff --git a/src/domain/discount-rules/discount.rules.types.ts b/src/domain/discount-rules/discount.rules.types.ts index fea7998..739adf3 100644 --- a/src/domain/discount-rules/discount.rules.types.ts +++ b/src/domain/discount-rules/discount.rules.types.ts @@ -1,8 +1,12 @@ -import PRODUCT_CODE from "@/enums/product"; -import DISCOUNT_CODE from "@/enums/discount"; - +import { PRODUCT_CODE } from "@/domain/checkout/checkout.types"; import { ScannerItem } from "@/domain/checkout/checkout.types"; +export enum DISCOUNT_CODE { + TWO_X_ONE = "TWO_X_ONE", + BULK = "BULK", + PROMO_CODE = "PROMO_CODE" +} + export interface DiscountRule { code: DISCOUNT_CODE; literal: string; diff --git a/src/enums/discount.ts b/src/enums/discount.ts deleted file mode 100644 index 9833094..0000000 --- a/src/enums/discount.ts +++ /dev/null @@ -1,7 +0,0 @@ -enum CODE { - TWO_X_ONE = "TWO_X_ONE", - BULK = "BULK", - PROMO_CODE = "PROMO_CODE" -} - -export default CODE; diff --git a/src/enums/modal.ts b/src/enums/modal.ts deleted file mode 100644 index 2cc1da3..0000000 --- a/src/enums/modal.ts +++ /dev/null @@ -1,5 +0,0 @@ -enum MODAL_MUTATION { - DISPLAY = "DISPLAY" -} - -export default MODAL_MUTATION; diff --git a/src/enums/product.ts b/src/enums/product.ts deleted file mode 100644 index e515c7d..0000000 --- a/src/enums/product.ts +++ /dev/null @@ -1,8 +0,0 @@ -enum CODE { - CAP = "CAP", - TSHIRT = "TSHIRT", - MUG = "MUG", - EMPTY = "EMPTY" -} - -export default CODE; diff --git a/src/enums/shopping.ts b/src/enums/shopping.ts deleted file mode 100644 index e144a37..0000000 --- a/src/enums/shopping.ts +++ /dev/null @@ -1,23 +0,0 @@ -export enum MUTATION { - SAVE_PRODUCTS = "SAVE_PRODUCTS", - SAVE_TOTAL_COST = "SAVE_TOTAL_COST", - SAVE_TOTAL_ITEMS = "SAVE_TOTAL_ITEMS", - SAVE_DISCOUNTS_APPLIED = "SAVE_DISCOUNTS_APPLIED", - SAVE_TOTAL_COST_WITH_DISCOUNTS = "SAVE_TOTAL_COST_WITH_DISCOUNTS" -} - -export enum ACTIONS { - INIT_SHOPPING_CART = "INIT_SHOPPING_CART", - SCAN_PRODUCT = "SCAN_PRODUCT", - REMOVE_PRODUCT = "REMOVE_PRODUCT" -} - -export enum GETTERS { - PRODUCTS = "PRODUCTS", - TOTAL_COST = "TOTAL_COST", - TOTAL_ITEMS = "TOTAL_ITEMS", - DISCOUNTS_APPLIED = "DISCOUNTS_APPLIED", - TOTAL_COST_WITH_DISCOUNTS = "TOTAL_COST_WITH_DISCOUNTS", - HAS_TOTAL_COST = "HAS_TOTAL_COST", - HAS_DISCOUNTS_APPLIED = "HAS_DISCOUNTS_APPLIED" -} diff --git a/src/infrastructure/README.md b/src/infrastructure/README.md new file mode 100644 index 0000000..346e7a5 --- /dev/null +++ b/src/infrastructure/README.md @@ -0,0 +1,7 @@ +## Infrastructure + +* This layer is responsible for communications with the outside world (sending requests/receiving responses) and storing local data. +* HTTP: Fetch API +* State Management: Vuex + + diff --git a/src/api/index.ts b/src/infrastructure/http/index.ts similarity index 80% rename from src/api/index.ts rename to src/infrastructure/http/index.ts index 7bbfc71..75a7671 100644 --- a/src/api/index.ts +++ b/src/infrastructure/http/index.ts @@ -5,7 +5,7 @@ import { Product } from "@/domain/checkout/checkout.types"; */ function mockProducts() { return import( - /* webpackChunkName: "async-mock-products" */ "@/api/mocks/products.json" + /* webpackChunkName: "async-mock-products" */ "@/infrastructure/http/mocks/products.json" ); } diff --git a/src/api/mocks/products.json b/src/infrastructure/http/mocks/products.json similarity index 100% rename from src/api/mocks/products.json rename to src/infrastructure/http/mocks/products.json diff --git a/src/store/index.ts b/src/infrastructure/store/index.ts similarity index 73% rename from src/store/index.ts rename to src/infrastructure/store/index.ts index a8c3d35..6a2f19c 100644 --- a/src/store/index.ts +++ b/src/infrastructure/store/index.ts @@ -5,8 +5,8 @@ import { useStore as baseUseStore } from "vuex"; -import { StateRoot } from "@/store/types"; -import Shopping from "@/store/shopping"; +import { StateRoot } from "@/infrastructure/store/store.types"; +import Shopping from "@/infrastructure/store/shopping"; export const key: InjectionKey> = Symbol(); diff --git a/src/store/shopping/actions.ts b/src/infrastructure/store/shopping/actions.ts similarity index 88% rename from src/store/shopping/actions.ts rename to src/infrastructure/store/shopping/actions.ts index e2f7efa..ef6ce7d 100644 --- a/src/store/shopping/actions.ts +++ b/src/infrastructure/store/shopping/actions.ts @@ -1,16 +1,19 @@ import { ActionContext, ActionTree } from "vuex"; -import API from "@/api"; +import http from "@/infrastructure/http"; import CheckoutService from "@/domain/checkout/checkout.service"; import DiscountRulesService from "@/domain/discount-rules/discount.rules.service"; -import { StateRoot } from "@/store/types"; -import { ShoppingActions } from "@/store/shopping/types"; +import { StateRoot } from "@/infrastructure/store/store.types"; +import { ShoppingActions } from "@/infrastructure/store/shopping/shopping.types"; import { Product, PricingRule } from "@/domain/checkout/checkout.types"; import { DiscountRule } from "@/domain/discount-rules/discount.rules.types"; -import PRODUCT_CODE from "@/enums/product"; -import { ACTIONS, MUTATION } from "@/enums/shopping"; +import { PRODUCT_CODE } from "@/domain/checkout/checkout.types"; +import { + ACTIONS, + MUTATION +} from "@/infrastructure/store/shopping/shopping.types"; let checkoutService: CheckoutService; const discountRulesService = new DiscountRulesService(); @@ -27,7 +30,7 @@ const actions: ActionTree & ShoppingActions = { const { commit } = context; try { - const products: Product[] = await API.products(); + const products: Product[] = await http.products(); const pricingRules: PricingRule[] = products.map(product => ({ code: product.code, diff --git a/src/store/shopping/getters.ts b/src/infrastructure/store/shopping/getters.ts similarity index 88% rename from src/store/shopping/getters.ts rename to src/infrastructure/store/shopping/getters.ts index 9a354eb..ab4585c 100644 --- a/src/store/shopping/getters.ts +++ b/src/infrastructure/store/shopping/getters.ts @@ -1,9 +1,9 @@ import { GetterTree } from "vuex"; -import { GETTERS } from "@/enums/shopping"; +import { GETTERS } from "@/infrastructure/store/shopping/shopping.types"; -import { StateRoot } from "@/store/types"; -import { ShoppingGetters } from "@/store/shopping/types"; +import { StateRoot } from "@/infrastructure/store/store.types"; +import { ShoppingGetters } from "@/infrastructure/store/shopping/shopping.types"; import { Product, TotalDiscountItem } from "@/domain/checkout/checkout.types"; const getters: GetterTree & ShoppingGetters = { diff --git a/src/infrastructure/store/shopping/index.ts b/src/infrastructure/store/shopping/index.ts new file mode 100644 index 0000000..8a8a12d --- /dev/null +++ b/src/infrastructure/store/shopping/index.ts @@ -0,0 +1,18 @@ +import { StoreOptions } from "vuex"; + +import { StateRoot } from "@/infrastructure/store/store.types"; + +import initialState from "@/infrastructure/store/shopping/initialState"; +import actions from "@/infrastructure/store/shopping/actions"; +import getters from "@/infrastructure/store/shopping/getters"; +import mutations from "@/infrastructure/store/shopping/mutations"; + +const Shopping: StoreOptions = { + strict: true, + state: initialState, + actions, + mutations, + getters +}; + +export default Shopping; diff --git a/src/store/shopping/initialState.ts b/src/infrastructure/store/shopping/initialState.ts similarity index 82% rename from src/store/shopping/initialState.ts rename to src/infrastructure/store/shopping/initialState.ts index aa527fb..ff02cfa 100644 --- a/src/store/shopping/initialState.ts +++ b/src/infrastructure/store/shopping/initialState.ts @@ -1,4 +1,4 @@ -import { StateRoot } from "@/store/types"; +import { StateRoot } from "@/infrastructure/store/store.types"; import { Product, Summary } from "@/domain/checkout/checkout.types"; const products: Product[] = []; diff --git a/src/store/shopping/mutations.ts b/src/infrastructure/store/shopping/mutations.ts similarity index 78% rename from src/store/shopping/mutations.ts rename to src/infrastructure/store/shopping/mutations.ts index 4f9eb92..7dd2f90 100644 --- a/src/store/shopping/mutations.ts +++ b/src/infrastructure/store/shopping/mutations.ts @@ -1,10 +1,9 @@ import { MutationTree } from "vuex"; -import { MUTATION } from "@/enums/shopping"; - -import { StateRoot } from "@/store/types"; -import { ShoppingMutations } from "@/store/shopping/types"; +import { StateRoot } from "@/infrastructure/store/store.types"; +import { MUTATION } from "@/infrastructure/store/shopping/shopping.types"; import { Product, TotalDiscountItem } from "@/domain/checkout/checkout.types"; +import { ShoppingMutations } from "@/infrastructure/store/shopping/shopping.types"; const mutations: MutationTree & ShoppingMutations = { [MUTATION.SAVE_PRODUCTS](state: StateRoot, payload: Product[]) { diff --git a/src/store/shopping/types.ts b/src/infrastructure/store/shopping/shopping.types.ts similarity index 66% rename from src/store/shopping/types.ts rename to src/infrastructure/store/shopping/shopping.types.ts index 3a20976..dc8e76d 100644 --- a/src/store/shopping/types.ts +++ b/src/infrastructure/store/shopping/shopping.types.ts @@ -1,10 +1,33 @@ import { ActionContext } from "vuex"; -import { StateRoot } from "@/store/types"; +import { StateRoot } from "@/infrastructure/store/store.types"; import { Product, TotalDiscountItem } from "@/domain/checkout/checkout.types"; -import PRODUCT_CODE from "@/enums/product"; -import { ACTIONS, MUTATION, GETTERS } from "@/enums/shopping"; +import { PRODUCT_CODE } from "@/domain/checkout/checkout.types"; + +export enum MUTATION { + SAVE_PRODUCTS = "SAVE_PRODUCTS", + SAVE_TOTAL_COST = "SAVE_TOTAL_COST", + SAVE_TOTAL_ITEMS = "SAVE_TOTAL_ITEMS", + SAVE_DISCOUNTS_APPLIED = "SAVE_DISCOUNTS_APPLIED", + SAVE_TOTAL_COST_WITH_DISCOUNTS = "SAVE_TOTAL_COST_WITH_DISCOUNTS" +} + +export enum ACTIONS { + INIT_SHOPPING_CART = "INIT_SHOPPING_CART", + SCAN_PRODUCT = "SCAN_PRODUCT", + REMOVE_PRODUCT = "REMOVE_PRODUCT" +} + +export enum GETTERS { + PRODUCTS = "PRODUCTS", + TOTAL_COST = "TOTAL_COST", + TOTAL_ITEMS = "TOTAL_ITEMS", + DISCOUNTS_APPLIED = "DISCOUNTS_APPLIED", + TOTAL_COST_WITH_DISCOUNTS = "TOTAL_COST_WITH_DISCOUNTS", + HAS_TOTAL_COST = "HAS_TOTAL_COST", + HAS_DISCOUNTS_APPLIED = "HAS_DISCOUNTS_APPLIED" +} type AugmentedActionContext = { commit( diff --git a/src/store/types.ts b/src/infrastructure/store/store.types.ts similarity index 93% rename from src/store/types.ts rename to src/infrastructure/store/store.types.ts index 9eae1c4..b6aa22a 100644 --- a/src/store/types.ts +++ b/src/infrastructure/store/store.types.ts @@ -3,7 +3,7 @@ import { ShoppingMutations, ShoppingActions, ShoppingGetters -} from "@/store/shopping/types"; +} from "@/infrastructure/store/shopping/shopping.types"; import { Store as VuexStore, CommitOptions, DispatchOptions } from "vuex"; export interface StateRoot { diff --git a/src/main.ts b/src/main.ts index 81ef89c..cc8d5df 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,7 @@ import { createApp } from "vue"; -import App from "@/App.vue"; -import { store, key } from "@/store"; +import App from "@/ui/App.vue"; +import { store, key } from "@/infrastructure/store"; createApp(App) .use(store, key) diff --git a/src/store/shopping/index.ts b/src/store/shopping/index.ts deleted file mode 100644 index a50fcdb..0000000 --- a/src/store/shopping/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { StoreOptions } from "vuex"; - -import { StateRoot } from "@/store/types"; - -import initialState from "@/store/shopping/initialState"; -import actions from "@/store/shopping/actions"; -import getters from "@/store/shopping/getters"; -import mutations from "@/store/shopping/mutations"; - -const Shopping: StoreOptions = { - strict: true, - state: initialState, - actions, - mutations, - getters -}; - -export default Shopping; diff --git a/src/App.vue b/src/ui/App.vue similarity index 72% rename from src/App.vue rename to src/ui/App.vue index a96be05..a8b7f2d 100644 --- a/src/App.vue +++ b/src/ui/App.vue @@ -7,12 +7,12 @@