├── api ├── shared │ ├── models.js │ ├── discount-data.js │ └── product-data.js ├── discounts-get │ ├── sample.dat │ ├── index.js │ └── function.json ├── .funcignore ├── .vscode │ └── extensions.json ├── host.json ├── package.json ├── products-get │ ├── index.js │ └── function.json ├── products-delete │ ├── index.js │ └── function.json ├── products-post │ ├── function.json │ └── index.js ├── products-put │ ├── function.json │ └── index.js ├── .gitignore └── README.md ├── react-app ├── src │ ├── App.css │ ├── globe.png │ ├── store │ │ ├── config.js │ │ ├── discount.api.js │ │ ├── discount.actions.js │ │ ├── action-utils.js │ │ ├── index.js │ │ ├── discount.reducer.js │ │ ├── discount.saga.js │ │ ├── product.api.js │ │ ├── product.actions.js │ │ ├── product.saga.js │ │ └── product.reducer.js │ ├── components │ │ ├── CardContent.js │ │ ├── HeaderBar.js │ │ ├── NotFound.js │ │ ├── AuthLogout.js │ │ ├── index.js │ │ ├── AuthLogin.js │ │ ├── Modal.js │ │ ├── InputDetail.js │ │ ├── ButtonFooter.js │ │ ├── HeaderBarBrand.js │ │ ├── ModalYesNo.js │ │ ├── ListHeader.js │ │ └── NavBar.js │ ├── index.css │ ├── useDiscounts.js │ ├── products │ │ ├── useProducts.js │ │ ├── ProductList.js │ │ └── ProductDetail.js │ ├── index.js │ ├── Home.js │ ├── App.js │ ├── Discounts.js │ └── logo.svg ├── public │ ├── favicon.ico │ ├── manifest.json │ ├── some-legacy-discounts-page.html │ ├── 404.html │ ├── staticwebapp.config.json │ └── index.html ├── .prettierrc ├── .gitignore ├── .eslintrc.json ├── package.json └── README.md ├── angular-app ├── src │ ├── assets │ │ ├── .gitkeep │ │ └── staticwebapp.config.json │ ├── app │ │ ├── build-specific │ │ │ ├── index.prod.ts │ │ │ └── index.ts │ │ ├── core │ │ │ ├── model │ │ │ │ ├── index.ts │ │ │ │ ├── discount.ts │ │ │ │ ├── product.ts │ │ │ │ └── user-info.ts │ │ │ ├── index.ts │ │ │ └── components │ │ │ │ ├── header-bar.component.ts │ │ │ │ ├── auth-logout.component.ts │ │ │ │ ├── not-found.component.ts │ │ │ │ ├── auth-login.component.ts │ │ │ │ ├── header-bar-brand.component.ts │ │ │ │ ├── index.ts │ │ │ │ └── nav.component.ts │ │ ├── app.component.ts │ │ ├── discount.service.ts │ │ ├── shared │ │ │ ├── card-content.component.ts │ │ │ ├── shared.module.ts │ │ │ ├── button-footer.component.ts │ │ │ ├── list-header.component.ts │ │ │ └── modal.component.ts │ │ ├── router.ts │ │ ├── products │ │ │ ├── products.module.ts │ │ │ ├── product.service.ts │ │ │ └── product-list.component.ts │ │ ├── app.module.ts │ │ ├── home.component.ts │ │ └── discounts.component.ts │ ├── favicon.ico │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ ├── tslint.json │ ├── main.ts │ ├── test.ts │ ├── index.html │ ├── public │ │ ├── some-legacy-discounts-page.html │ │ └── 404.html │ ├── karma.conf.js │ └── polyfills.ts ├── proxy.conf.json ├── .prettierrc ├── .browserslistrc ├── tsconfig.json ├── .gitignore ├── package.json ├── tslint.json └── README.md ├── vue-app ├── .env ├── .browserslistrc ├── postcss.config.js ├── public │ ├── favicon.ico │ ├── some-legacy-discounts-page.html │ ├── 404.html │ ├── index.html │ └── staticwebapp.config.json ├── src │ ├── assets │ │ └── logo.png │ ├── store │ │ ├── config.js │ │ ├── modules │ │ │ ├── mutation-types.js │ │ │ ├── action-utils.js │ │ │ ├── discounts.js │ │ │ └── products.js │ │ └── index.js │ ├── main.js │ ├── components │ │ ├── page-not-found.vue │ │ ├── header-bar.vue │ │ ├── card-content.vue │ │ ├── auth-logout.vue │ │ ├── auth-login.vue │ │ ├── header-bar-brand.vue │ │ ├── button-footer.vue │ │ ├── modal.vue │ │ ├── list-header.vue │ │ └── nav-bar.vue │ ├── app.vue │ ├── router.js │ └── views │ │ ├── home.vue │ │ ├── discounts.vue │ │ └── products │ │ └── product-list.vue ├── .babelrc ├── .prettierrc ├── vue.config.js ├── .gitignore ├── .eslintrc.js ├── package.json └── README.md ├── svelte-app ├── .env ├── src │ ├── models │ │ ├── index.ts │ │ ├── discount.ts │ │ └── product.ts │ ├── vite-env.d.ts │ ├── global.d.ts │ ├── store │ │ ├── index.ts │ │ ├── discount-data.ts │ │ ├── http-utils.ts │ │ ├── store.ts │ │ └── product-data.ts │ ├── main.ts │ ├── components │ │ ├── Redirect.svelte │ │ ├── PageNotFound.svelte │ │ ├── HeaderBar.svelte │ │ ├── CardContent.svelte │ │ ├── AuthLogout.svelte │ │ ├── HeaderBarBrand.svelte │ │ ├── AuthLogin.svelte │ │ ├── index.ts │ │ ├── ButtonFooter.svelte │ │ ├── ListHeader.svelte │ │ ├── Modal.svelte │ │ └── NavBar.svelte │ ├── config.ts │ ├── App.svelte │ ├── Home.svelte │ ├── global.css │ ├── Discounts.svelte │ ├── products │ │ ├── ProductList.svelte │ │ └── ProductDetail.svelte │ └── assets │ │ └── svelte.svg ├── public │ ├── favicon.png │ ├── svelte-icon.png │ ├── some-legacy-discounts-page.html │ ├── 404.html │ └── staticwebapp.config.json ├── .gitignore ├── .prettierrc ├── tsconfig.node.json ├── svelte.config.js ├── index.html ├── tsconfig.json ├── vite.config.ts ├── package.json └── README.md ├── .vscode ├── extensions.json ├── launch.json ├── tasks.json └── settings.json ├── fastify-api-server ├── src │ ├── routes │ │ ├── discounts.js │ │ ├── index.js │ │ └── products.js │ ├── shared │ │ ├── discount-data.js │ │ └── product-data.js │ └── server.js ├── package.json └── README.md ├── .devcontainer ├── Dockerfile └── devcontainer.json ├── LICENSE └── .github └── workflows ├── azure-static-web-apps-zealous-ground-07634b41e.yml ├── azure-static-web-apps-thankful-ground-025b83e1e.yml ├── azure-static-web-apps-purple-cliff-0e5d9b80f.yml ├── azure-static-web-apps-purple-pond-08f780f0f.yml ├── azure-static-web-apps-gentle-cliff-0bc570010.yml └── azure-static-web-apps-brave-mushroom-0741e3c1e.yml /api/shared/models.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /react-app/src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /angular-app/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-app/.env: -------------------------------------------------------------------------------- 1 | VITE_API='/api' 2 | DEV=false 3 | -------------------------------------------------------------------------------- /svelte-app/.env: -------------------------------------------------------------------------------- 1 | VITE_API='/api' 2 | DEV=false 3 | -------------------------------------------------------------------------------- /api/discounts-get/sample.dat: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Azure" 3 | } -------------------------------------------------------------------------------- /vue-app/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | -------------------------------------------------------------------------------- /angular-app/src/app/build-specific/index.prod.ts: -------------------------------------------------------------------------------- 1 | export const externalModules = []; 2 | -------------------------------------------------------------------------------- /svelte-app/src/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './discount'; 2 | export * from './product'; 3 | -------------------------------------------------------------------------------- /react-app/src/globe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/shopathome/HEAD/react-app/src/globe.png -------------------------------------------------------------------------------- /api/.funcignore: -------------------------------------------------------------------------------- 1 | *.js.map 2 | *.ts 3 | .git* 4 | .vscode 5 | local.settings.json 6 | test 7 | tsconfig.json -------------------------------------------------------------------------------- /svelte-app/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /vue-app/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /vue-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/shopathome/HEAD/vue-app/public/favicon.ico -------------------------------------------------------------------------------- /angular-app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/shopathome/HEAD/angular-app/src/favicon.ico -------------------------------------------------------------------------------- /react-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/shopathome/HEAD/react-app/public/favicon.ico -------------------------------------------------------------------------------- /svelte-app/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/shopathome/HEAD/svelte-app/public/favicon.png -------------------------------------------------------------------------------- /vue-app/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/shopathome/HEAD/vue-app/src/assets/logo.png -------------------------------------------------------------------------------- /vue-app/src/store/config.js: -------------------------------------------------------------------------------- 1 | const API = process.env.VUE_APP_API || 'api'; 2 | 3 | export { API as default }; 4 | -------------------------------------------------------------------------------- /react-app/src/store/config.js: -------------------------------------------------------------------------------- 1 | const API = process.env.REACT_APP_API || '/api'; 2 | 3 | export { API as default }; 4 | -------------------------------------------------------------------------------- /svelte-app/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /public/build/ 3 | 4 | .DS_Store 5 | 6 | dist 7 | dist-ssr 8 | *.local 9 | -------------------------------------------------------------------------------- /api/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-azuretools.vscode-azurefunctions" 4 | ] 5 | } -------------------------------------------------------------------------------- /svelte-app/public/svelte-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/shopathome/HEAD/svelte-app/public/svelte-icon.png -------------------------------------------------------------------------------- /vue-app/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@vue/babel-preset-app", 4 | "@babel/preset-env" 5 | ] 6 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["ms-azuretools.vscode-azurefunctions", "svelte.svelte-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /angular-app/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api": { 3 | "target": "http://localhost:7071", 4 | "secure": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /angular-app/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | API: 'api', 4 | }; 5 | -------------------------------------------------------------------------------- /angular-app/src/app/core/model/index.ts: -------------------------------------------------------------------------------- 1 | export * from './discount'; 2 | export * from './product'; 3 | export * from './user-info'; 4 | -------------------------------------------------------------------------------- /svelte-app/src/global.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module 'svelte-routing'; 4 | declare const process: { env: any }; 5 | -------------------------------------------------------------------------------- /svelte-app/src/models/discount.ts: -------------------------------------------------------------------------------- 1 | export class Discount { 2 | id: number; 3 | store: string; 4 | percentage: number; 5 | code: string; 6 | } 7 | -------------------------------------------------------------------------------- /svelte-app/src/models/product.ts: -------------------------------------------------------------------------------- 1 | export class Product { 2 | id: number; 3 | name: string; 4 | description: string; 5 | quantity?: number; 6 | } 7 | -------------------------------------------------------------------------------- /angular-app/src/app/core/model/discount.ts: -------------------------------------------------------------------------------- 1 | export class Discount { 2 | id: number; 3 | store: string; 4 | percentage: number; 5 | code: string; 6 | } 7 | -------------------------------------------------------------------------------- /angular-app/src/app/core/model/product.ts: -------------------------------------------------------------------------------- 1 | export class Product { 2 | id: number; 3 | name: string; 4 | description: string; 5 | quantity: number; 6 | } 7 | -------------------------------------------------------------------------------- /react-app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "printWidth": 80, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "all", 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /vue-app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "printWidth": 80, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "all", 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /angular-app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "printWidth": 80, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "all", 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /angular-app/src/app/core/model/user-info.ts: -------------------------------------------------------------------------------- 1 | export interface UserInfo { 2 | identityProvider: string; 3 | userId: string; 4 | userDetails: string; 5 | userRoles: string[]; 6 | } 7 | -------------------------------------------------------------------------------- /svelte-app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "printWidth": 80, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "all", 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /svelte-app/src/store/index.ts: -------------------------------------------------------------------------------- 1 | export * from '../config'; 2 | export * from './http-utils'; 3 | export * from './store'; 4 | export * from './discount-data'; 5 | export * from './product-data'; 6 | -------------------------------------------------------------------------------- /svelte-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import './styles.scss'; 2 | import App from './App.svelte'; 3 | 4 | const app = new App({ 5 | target: document.getElementById('app'), 6 | }); 7 | 8 | export default app; 9 | -------------------------------------------------------------------------------- /svelte-app/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /angular-app/src/app/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components'; 2 | export * from './model'; 3 | import { environment } from './../../environments/environment'; 4 | 5 | export const API = environment.API || 'api'; 6 | -------------------------------------------------------------------------------- /svelte-app/src/components/Redirect.svelte: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /api/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingSettings": { 6 | "isEnabled": true, 7 | "excludedTypes": "Request" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /angular-app/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "main.ts", 9 | "polyfills.ts" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functions", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "start": "func start", 7 | "test": "echo \"No tests yet...\"" 8 | }, 9 | "dependencies": {}, 10 | "devDependencies": {} 11 | } 12 | -------------------------------------------------------------------------------- /vue-app/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './app.vue'; 3 | import router from './router'; 4 | import store from './store'; 5 | 6 | const app = createApp(App); 7 | 8 | app.use(router); 9 | app.use(store); 10 | 11 | app.mount('#app'); 12 | -------------------------------------------------------------------------------- /vue-app/src/store/modules/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const GET_DISCOUNTS = 'GET_DISCOUNTS'; 2 | export const GET_PRODUCTS = 'GET_PRODUCTS'; 3 | export const ADD_PRODUCT = 'ADD_PRODUCT'; 4 | export const UPDATE_PRODUCT = 'UPDATE_PRODUCT'; 5 | export const DELETE_PRODUCT = 'DELETE_PRODUCT'; 6 | -------------------------------------------------------------------------------- /react-app/src/store/discount.api.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { parseList } from './action-utils'; 3 | import API from './config'; 4 | 5 | export const loadDiscountsApi = async () => { 6 | const response = await axios.get(`${API}/discounts`); 7 | return parseList(response, 200); 8 | }; 9 | -------------------------------------------------------------------------------- /svelte-app/src/components/PageNotFound.svelte: -------------------------------------------------------------------------------- 1 |
2 |
3 |