diff --git a/db/DML/content.json b/db/DML/content.json index b8f4bc9..8f5568b 100644 --- a/db/DML/content.json +++ b/db/DML/content.json @@ -139,23 +139,21 @@ } }, "titleSection": { - "title": "Hello, World! by Redux", + "title": "Hello, World! by C# and Mongo", "text": "

Welcome to your new single-page application, built with:

\n ", - - "primaryLink": { - "target": "#!", - "anchorText": "Get Started" - }, - "secondaryLink": { - "target": "#!", - "anchorText": "Learn more" - }, - - "image": { - "src": "https://dummyimage.com/600x400/343a40/6c757d", - "alt": "..." - } - }, + "primaryLink": { + "target": "#!", + "anchorText": "Get Started" + }, + "secondaryLink": { + "target": "#!", + "anchorText": "Learn more" + }, + "image": { + "src": "https://dummyimage.com/600x400/343a40/6c757d", + "alt": "..." + } + }, "featuresSection": { "title": "To help you get started, we have also set up:", "items": [ @@ -254,11 +252,9 @@ }, "titleSection": { "title": "Shopping Cart", - "text": "items in your cart" + "text": "{quantity} items in your cart" }, "productsSection": { - "title": "Shopping Cart", - "text": "{quantity} items in your cart", "product": "Product", "price": "Price", "quantity": "Quantity", @@ -267,8 +263,9 @@ "target": "/shop", "anchorText": "Continue shopping" }, - "submit": { - "title": "Checkout" + "checkout": { + "target": "checkout", + "anchorText": "Checkout" } } }, diff --git a/db/DML/shopcart.json b/db/DML/shopcart.json new file mode 100644 index 0000000..0947b41 --- /dev/null +++ b/db/DML/shopcart.json @@ -0,0 +1,47 @@ +[ + { + "_id": "bdc1aeac-2592-40c2-b9b3-a4988ce6173d", + "siteId": "404c8232-9048-4519-bfba-6e78dc7005ca", + "userId": "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "slug": "shop-catalog-item", + "sku": "SKU-01", + "image": { "src": "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", "alt": "..." }, + "title": "Shop item title", + "brandName": "Brand & Name", + "shortText": "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...", + "created": { "$date": "2022-01-01T00:00:00.000Z" }, + "price": 20, + "newPrice": 10, + "quantity": 1 + }, + { + "_id": "0aaa0244-4b4a-4b05-8135-463ba187d78b", + "siteId": "404c8232-9048-4519-bfba-6e78dc7005ca", + "userId": "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "slug": "shop-catalog-item", + "sku": "SKU-02", + "image": { "src": "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", "alt": "..." }, + "title": "Shop item title", + "brandName": "Brand & Name", + "shortText": "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...", + "created": { "$date": "2022-01-01T00:00:00.000Z" }, + "price": 20, + "newPrice": 10, + "quantity": 2 + }, + { + "_id": "7da86cc6-80a9-4828-b81f-421d26a8cb24", + "siteId": "404c8232-9048-4519-bfba-6e78dc7005ca", + "userId": "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "slug": "shop-catalog-item", + "sku": "SKU-03", + "image": { "src": "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", "alt": "..." }, + "title": "Shop item title", + "brandName": "Brand & Name", + "shortText": "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...", + "created": { "$date": "2022-01-01T00:00:00.000Z" }, + "price": 20, + "newPrice": 10, + "quantity": 2 + } +] \ No newline at end of file diff --git a/postman/reactredux.postman_collection.json b/postman/reactredux.postman_collection.json index 37e04a5..b1f7531 100644 --- a/postman/reactredux.postman_collection.json +++ b/postman/reactredux.postman_collection.json @@ -47,6 +47,44 @@ "response": [] } ] + }, + { + "name": "ShopCart", + "item": [ + { + "name": "GetShopCart", + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "default" + }, + { + "key": "Accept", + "value": "application/json", + "type": "default" + } + ], + "url": { + "raw": "https://localhost:7151/api/ShopCart/404c8232-9048-4519-bfba-6e78dc7005ca/fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "7151", + "path": [ + "api", + "ShopCart", + "404c8232-9048-4519-bfba-6e78dc7005ca", + "fdc5aa50-ee68-4bae-a8e6-b8ae2c258f60" + ] + } + }, + "response": [] + } + ] } ] } \ No newline at end of file diff --git a/webapi/ClientApp/src/models/abstractions.ts b/webapi/ClientApp/src/models/abstractions.ts index 7ba6e62..c75f3b9 100644 --- a/webapi/ClientApp/src/models/abstractions.ts +++ b/webapi/ClientApp/src/models/abstractions.ts @@ -1,4 +1,5 @@ import { AuthorModel, FormItemModel, HeaderModel, ImageModel } from "./" +import { TitleSectionModel } from "./pageSections" export interface RequestModel { @@ -20,6 +21,7 @@ export interface AddressPageSectionModel extends PageSectionModel { export interface PageModel { header: HeaderModel, + titleSection?: TitleSectionModel } export interface PageSectionModel { diff --git a/webapi/ClientApp/src/models/pageSections.ts b/webapi/ClientApp/src/models/pageSections.ts index e1c00ad..80bf1e1 100644 --- a/webapi/ClientApp/src/models/pageSections.ts +++ b/webapi/ClientApp/src/models/pageSections.ts @@ -1,63 +1,25 @@ import { FeatureModel, FormItemModel, ImageModel, LinkModel, MenuItemModel, TestimonialModel } from "./" import { AddressPageSectionModel, PageSectionModel } from "./abstractions" -export interface BlogTitleSectionModel extends PageSectionModel { - postedOnBy: string -} +export interface BillingAddressSectionModel extends AddressPageSectionModel { } + export interface CallToActionSectionModel extends PageSectionModel { privacyDisclaimer?: string email?: FormItemModel } -export interface CommentsSectionModel extends PageSectionModel { - leaveComment: string -} - -export interface FeaturesSectionModel extends PageSectionModel { - items: FeatureModel [] -} - -export interface FeaturedBlogSectionModel extends PageSectionModel { - readTime: string -} - -export interface FeaturedBlogsSectionModel extends PageSectionModel {} - -export interface ProductSectionModel extends PageSectionModel { - availableQuantity: string, - addToCart: string -} - -export interface RelatedProductsSectionModel extends PageSectionModel { - addToCart: string -} - -export interface TestimonialsSectionModel extends PageSectionModel { - items: TestimonialModel [] -} - -export interface TitleSectionModel extends PageSectionModel { - image?: ImageModel, - primaryLink?: MenuItemModel, - secondaryLink?: MenuItemModel -} - - export interface CartProductsSectionModel extends PageSectionModel { product: string, price: string, quantity: string, subtotal: string, continueShopping: LinkModel, - submit: FormItemModel + checkout: LinkModel } -export interface BillingAddressSectionModel extends AddressPageSectionModel { } - -export interface ShippingAddressSectionModel extends AddressPageSectionModel { } - -export interface ShopItemsSectionModel extends PageSectionModel { - addToCart: string +export interface CheckoutSettingsSectionModel extends PageSectionModel { + shippingAddressSameAsBillingAddress: string, + saveThisInformation: string } export interface CheckoutSummarySectionModel extends PageSectionModel { @@ -68,28 +30,49 @@ export interface CheckoutSummarySectionModel extends PageSectionModel { submit: FormItemModel } -export interface CheckoutSettingsSectionModel extends PageSectionModel { - shippingAddressSameAsBillingAddress: string, - saveThisInformation: string +export interface CommentsSectionModel extends PageSectionModel { + leaveComment: string +} + +export interface FeaturedBlogSectionModel extends PageSectionModel { + readTime: string +} + +export interface FeaturedBlogsSectionModel extends PageSectionModel {} + +export interface FeaturesSectionModel extends PageSectionModel { + items: FeatureModel [] } export interface PaymentSectionModel extends PageSectionModel { - title: string, nameOnCard: FormItemModel, cardNumber: FormItemModel, expiration: FormItemModel, cvv: FormItemModel } +export interface ProductSectionModel extends PageSectionModel { + availableQuantity: string, + addToCart: string +} +export interface RelatedProductsSectionModel extends PageSectionModel { + addToCart: string +} +export interface ShippingAddressSectionModel extends AddressPageSectionModel { } +export interface TestimonialsSectionModel extends PageSectionModel { + items: TestimonialModel [] +} +export interface TitleSectionModel extends PageSectionModel { + image?: ImageModel, + primaryLink?: MenuItemModel, + secondaryLink?: MenuItemModel, + postedOnBy?: string +} - - - - - - - +export interface ShopItemsSectionModel extends PageSectionModel { + addToCart: string +} diff --git a/webapi/ClientApp/src/models/pages.ts b/webapi/ClientApp/src/models/pages.ts index 58d104f..4389c63 100644 --- a/webapi/ClientApp/src/models/pages.ts +++ b/webapi/ClientApp/src/models/pages.ts @@ -3,28 +3,42 @@ import { PageModel } from "./abstractions" import * as PageSection from "./pageSections" export interface BlogCatalogPageModel extends PageModel { - titleSection: PageSection.TitleSectionModel, featuredBlogSection: PageSection.FeaturedBlogSectionModel } export interface BlogItemPageModel extends PageModel { - titleSection: PageSection.BlogTitleSectionModel, commentsSection: PageSection.CommentsSectionModel } export interface HomePageModel extends PageModel { - titleSection: PageSection.TitleSectionModel, featuresSection: PageSection.FeaturesSectionModel, testimonialsSection: PageSection.TestimonialsSectionModel, featuredBlogsSection: PageSection.FeaturedBlogsSectionModel, callToActionSection: PageSection.CallToActionSectionModel } +export interface ShopCartPageModel extends PageModel { + productsSection: PageSection.CartProductsSectionModel +} + export interface ShopCatalogPageModel extends PageModel { - titleSection: PageSection.TitleSectionModel, shopItemsSection: PageSection.ShopItemsSectionModel } +export interface ShopCheckoutPageModel extends PageModel { + billingAddressSection: PageSection.BillingAddressSectionModel, + shippingAddressSection: PageSection.ShippingAddressSectionModel, + settingsSection: PageSection.CheckoutSettingsSectionModel, + summarySection: PageSection.CheckoutSummarySectionModel, + paymentSection: PageSection.PaymentSectionModel, + submit: FormItemModel +} + +export interface ShopItemPageModel extends PageModel { + productSection: PageSection.ProductSectionModel + relatedProductsSection: PageSection.RelatedProductsSectionModel +} + export interface SignInPageModel extends PageModel { title: string, email: FormItemModel, @@ -43,24 +57,4 @@ export interface SignUpPageModel extends PageModel { rePassword: FormItemModel, acceptTermsAndConditions: string, submit: FormItemModel -} - -export interface ShopItemPageModel extends PageModel { - productSection: PageSection.ProductSectionModel - relatedProductsSection: PageSection.RelatedProductsSectionModel -} - -export interface ShopCartPageModel extends PageModel { - titleSection: PageSection.TitleSectionModel - productsSection: PageSection.CartProductsSectionModel -} - -export interface ShopCheckoutPageModel extends PageModel { - titleSection: PageSection.TitleSectionModel, - billingAddressSection: PageSection.BillingAddressSectionModel, - shippingAddressSection: PageSection.ShippingAddressSectionModel, - settingsSection: PageSection.CheckoutSettingsSectionModel, - summarySection: PageSection.CheckoutSummarySectionModel, - paymentSection: PageSection.PaymentSectionModel, - submit: FormItemModel } \ No newline at end of file diff --git a/webapi/ClientApp/src/pages/Home/index.tsx b/webapi/ClientApp/src/pages/Home/index.tsx index 87b1d4c..437f9ad 100644 --- a/webapi/ClientApp/src/pages/Home/index.tsx +++ b/webapi/ClientApp/src/pages/Home/index.tsx @@ -196,7 +196,7 @@ const Home = () => { }, []) useEffect(() => { - content?.isLoading || content?.isLoading + content?.isLoading || blogFeatured?.isLoading ? dispatch(loaderActionCreators.show()) : setTimeout(() => { dispatch(loaderActionCreators.hide()) diff --git a/webapi/ClientApp/src/pages/Shop/Cart/index.tsx b/webapi/ClientApp/src/pages/Shop/Cart/index.tsx index eee3082..139579d 100644 --- a/webapi/ClientApp/src/pages/Shop/Cart/index.tsx +++ b/webapi/ClientApp/src/pages/Shop/Cart/index.tsx @@ -3,19 +3,29 @@ import React, { useEffect, useState } from 'react' // Redux import { useDispatch, useSelector } from 'react-redux' +import { actionCreators as loaderActionCreators } from '../../../store/reducers/Loader' // import { actionCreator as shopCartActionCreator } from '../../../store/reducers/ShopCart' import { ApplicationState } from '../../../store' -import { Container } from 'reactstrap' +import { Button, Col, Container, Input, InputGroup, Row } from 'reactstrap' +import { Link } from 'react-router-dom' import { FeatherIcon } from '../../../components/FeatherIcons' import style from './scss/style.module.scss' - +import { ReservedWords } from '../../../enumerations' const Cart = () => { const dispatch = useDispatch() const { content, shopCart } = useSelector((state: ApplicationState) => state) + useEffect(() => { + content?.isLoading || shopCart?.isLoading + ? dispatch(loaderActionCreators.show()) + : setTimeout(() => { + dispatch(loaderActionCreators.hide()) + }, 1000) + }, [content?.isLoading, shopCart?.isLoading]) + const { currencySymbol = "" } = content?.localization ? content.localization : {} @@ -31,11 +41,12 @@ const Cart = () => { quantity: "", subtotal: "", continueShopping: { - target: "#", + target: "!#", anchorText: "" }, - submit: { - title: "" + checkout: { + target: "!#", + anchorText: "" } } @@ -55,23 +66,35 @@ const Cart = () => { }, [shopCart?.items]) + + const onPlus = () => { + + } + + const onMinus = () => { + + } + + const onDelete = () => { + + } + return

{titleSection.title}

-

{shopCart?.items ? shopCart.items.length : 0} {titleSection.text}

+

- - + + - + - {(shopCart?.items ? shopCart.items : []).map((item, index) => )} - -
{productsSection.product}{productsSection.price}{productsSection.product}{productsSection.price} {productsSection.quantity}
@@ -88,18 +111,20 @@ const Cart = () => { ? <>{currencySymbol}{item.price.toFixed(2)} {currencySymbol}{item.newPrice.toFixed(2)} : {currencySymbol}{item.price.toFixed(2)}}
- + + + + +
-
@@ -108,18 +133,16 @@ const Cart = () => {
-
-
- {productsSection.submit.title} -
-
- - {productsSection.continueShopping.anchorText} -
-
+ + + {productsSection.checkout.anchorText} + + + {productsSection.continueShopping.anchorText} + +
- } export { diff --git a/webapi/ClientApp/src/store/reducers/Content.ts b/webapi/ClientApp/src/store/reducers/Content.ts index adadccd..9efdfe6 100644 --- a/webapi/ClientApp/src/store/reducers/Content.ts +++ b/webapi/ClientApp/src/store/reducers/Content.ts @@ -23,7 +23,7 @@ type KnownAction = RequestAction | ReceiveAction; export const actionCreators = { requestContent: (props?: GetContentRequestModel): AppThunkAction => (dispatch, getState) => { - Get>('https://localhost:7151/api/Content', props) + Get>('https://localhost:7151/api/Content/404c8232-9048-4519-bfba-6e78dc7005ca?locale=en-US', props) .then(response => response) .then((data) => { if(data) { @@ -214,11 +214,9 @@ const unloadedState: ContentState = { }, titleSection: { title: "Shopping Cart", - text: "items in your cart" + text: "{quantity} items in your cart" }, productsSection: { - title: "Shopping Cart", - text: `${ReservedWords.quantity} items in your cart`, product: "Product", price: "Price", quantity: "Quantity", @@ -227,8 +225,9 @@ const unloadedState: ContentState = { target: "/shop", anchorText: "Continue shopping" }, - submit: { - title: "Checkout" + checkout: { + target: "checkout", + anchorText: "Checkout" } } }, diff --git a/webapi/ClientApp/src/store/reducers/ShopCart.ts b/webapi/ClientApp/src/store/reducers/ShopCart.ts index 0b62d13..fb8882a 100644 --- a/webapi/ClientApp/src/store/reducers/ShopCart.ts +++ b/webapi/ClientApp/src/store/reducers/ShopCart.ts @@ -1,5 +1,6 @@ import { Action, Reducer } from 'redux' import { AppThunkAction } from '..' +import { ShopItemModel } from '../../models' import { GetShopCartRequestModel } from '../../models/requests' import { GetShopCartResponseModel } from '../../models/responses' @@ -15,7 +16,15 @@ export interface ReceiveAction extends GetShopCartResponseModel { type: 'RECEIVE_CART' } -export type KnownAction = RequestAction | ReceiveAction +export interface IncrementItemQuantityAction extends GetShopCartResponseModel { + type: 'INCREMENT_ITEM_QUANTITY' +} + +export interface DecrementItmeQuantityAction extends GetShopCartResponseModel { + type: 'DECREMENT_ITEM_QUANTITY' +} + +export type KnownAction = RequestAction | ReceiveAction | IncrementItemQuantityAction | DecrementItmeQuantityAction export const actionCreators = { requestCart: (): AppThunkAction => (dispatch, getState) => { @@ -34,6 +43,19 @@ export const actionCreators = { // dispatch({ type: 'REQUEST_BLOG_ITEM', slug: props.slug }) }, + increment: (): AppThunkAction => (dispatch, getState) => { + + const items: ShopItemModel [] = [] + dispatch({ type: 'INCREMENT_ITEM_QUANTITY', items }) + + + }, + decrement: (): AppThunkAction => (dispatch, getState) => { + + const items: ShopItemModel [] = [] + dispatch({ type: 'DECREMENT_ITEM_QUANTITY', items }) + }, + remFromCart: (): AppThunkAction => (dispatch, getState) => { } @@ -142,6 +164,18 @@ export const reducer: Reducer = (state: ShopCartState | undefined ...action, isLoading: false } + + case 'INCREMENT_ITEM_QUANTITY': + return { + ...action, + isLoading: false + } + + case 'DECREMENT_ITEM_QUANTITY': + return { + ...action, + isLoading: false + } } return state diff --git a/webapi/Core/Abstractions/DomainObjects/PageBase.cs b/webapi/Core/Abstractions/DomainObjects/PageBase.cs index ec2dee6..4b9822d 100644 --- a/webapi/Core/Abstractions/DomainObjects/PageBase.cs +++ b/webapi/Core/Abstractions/DomainObjects/PageBase.cs @@ -1,5 +1,12 @@  +using Core.DomainObjects; +using Core.DomainObjects.PageSections; + namespace Core.Abstractions.DomainObjects { - public abstract class PageBase : DomainObjectBase { } + public abstract class PageBase : DomainObjectBase { + + public Header Header { get; set; } + public TitleSection? TitleSection { get; set; } + } } diff --git a/webapi/Core/Abstractions/Models/ModelBase.cs b/webapi/Core/Abstractions/Models/ModelBase.cs index 4c665d2..5bf0a12 100644 --- a/webapi/Core/Abstractions/Models/ModelBase.cs +++ b/webapi/Core/Abstractions/Models/ModelBase.cs @@ -5,5 +5,8 @@ using System.Text; using System.Threading.Tasks; namespace Core.Abstractions.Models { - public abstract class ModelBase { } + public abstract class ModelBase { + + + } } diff --git a/webapi/Core/Abstractions/Models/RequestModel.cs b/webapi/Core/Abstractions/Models/RequestModelBase.cs similarity index 62% rename from webapi/Core/Abstractions/Models/RequestModel.cs rename to webapi/Core/Abstractions/Models/RequestModelBase.cs index bf8ba36..6259ec4 100644 --- a/webapi/Core/Abstractions/Models/RequestModel.cs +++ b/webapi/Core/Abstractions/Models/RequestModelBase.cs @@ -5,9 +5,9 @@ using System.Text; using System.Threading.Tasks; namespace Core.Abstractions.Models { - public abstract class RequestModel : ModelBase { + public abstract class RequestModelBase : ModelBase { - + public abstract T ToDomainObject(); } } diff --git a/webapi/Core/Abstractions/Models/ResponseModel.cs b/webapi/Core/Abstractions/Models/ResponseModelBase.cs similarity index 74% rename from webapi/Core/Abstractions/Models/ResponseModel.cs rename to webapi/Core/Abstractions/Models/ResponseModelBase.cs index 55fa695..3e3733f 100644 --- a/webapi/Core/Abstractions/Models/ResponseModel.cs +++ b/webapi/Core/Abstractions/Models/ResponseModelBase.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; namespace Core.Abstractions.Models { - public abstract class ResponseModel : ModelBase { + public abstract class ResponseModelBase : ModelBase { } } diff --git a/webapi/Core/DomainObjects/Documents/ShopCart.cs b/webapi/Core/DomainObjects/Documents/ShopCart.cs new file mode 100644 index 0000000..4a968d9 --- /dev/null +++ b/webapi/Core/DomainObjects/Documents/ShopCart.cs @@ -0,0 +1,27 @@ +using Core.Abstractions.DomainObjects; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.DomainObjects.Documents { + public class ShopCart : DomainObjectDocumentBase { + public Guid SiteId { get; set; } + public Guid UserId { get; set; } + public string Slug { get; set; } + public string Sku { get; set; } + public Image Image { get; set; } + public string Title { get; set; } + public string BrandName { get; set; } + public string ShortText { get; set; } + public DateTime Created { get; set; } + public double Price { get; set; } + public double NewPrice { get; set; } + public uint Quantity { get; set; } + + public override int GetHashCode() { + throw new NotImplementedException(); + } + } +} diff --git a/webapi/Core/DomainObjects/PageSections/ProductsSection.cs b/webapi/Core/DomainObjects/PageSections/ProductsSection.cs index a8fbfe7..e8f664c 100644 --- a/webapi/Core/DomainObjects/PageSections/ProductsSection.cs +++ b/webapi/Core/DomainObjects/PageSections/ProductsSection.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; namespace Core.DomainObjects.PageSections { public class ProductsSection : PageSectionBase { public string Product { get; set; } + public string Price { get; set; } public string Quantity { get; set; } @@ -16,7 +17,7 @@ namespace Core.DomainObjects.PageSections { public Link ContinueShopping { get; set; } - public FormItem Submit { get; set; } + public Link Checkout { get; set; } public override int GetHashCode() { throw new NotImplementedException(); diff --git a/webapi/Core/DomainObjects/Pages/BlogCatalogPage.cs b/webapi/Core/DomainObjects/Pages/BlogCatalogPage.cs index 5641378..2dedea6 100644 --- a/webapi/Core/DomainObjects/Pages/BlogCatalogPage.cs +++ b/webapi/Core/DomainObjects/Pages/BlogCatalogPage.cs @@ -4,9 +4,6 @@ using Core.DomainObjects.PageSections; namespace Core.DomainObjects.Pages { public class BlogCatalogPage : PageBase { - public Header Header { get; set; } - - public TitleSection TitleSection { get; set; } public FeaturedBlogSection FeaturedBlogSection { get; set; } public override int GetHashCode() { diff --git a/webapi/Core/DomainObjects/Pages/BlogItemPage.cs b/webapi/Core/DomainObjects/Pages/BlogItemPage.cs index 2f1c11a..be1124b 100644 --- a/webapi/Core/DomainObjects/Pages/BlogItemPage.cs +++ b/webapi/Core/DomainObjects/Pages/BlogItemPage.cs @@ -4,8 +4,7 @@ using Core.DomainObjects.PageSections; namespace Core.DomainObjects.Pages { public class BlogItemPage : PageBase { - public Header Header { get; set; } - public TitleSection TitleSection { get; set; } + public CommentsSection CommentsSection { get; set; } public override int GetHashCode() { diff --git a/webapi/Core/DomainObjects/Pages/HomePage.cs b/webapi/Core/DomainObjects/Pages/HomePage.cs index d89ca8b..14dd649 100644 --- a/webapi/Core/DomainObjects/Pages/HomePage.cs +++ b/webapi/Core/DomainObjects/Pages/HomePage.cs @@ -4,8 +4,7 @@ using Core.DomainObjects.PageSections; namespace Core.DomainObjects.Pages { public class HomePage : PageBase { - public Header Header { get; set; } - public TitleSection TitleSection { get; set; } + public FeaturesSection FeaturesSection { get; set; } public TestimonialsSection TestimonialsSection { get; set; } public FeaturedBlogsSection FeaturedBlogsSection { get; set; } diff --git a/webapi/Core/DomainObjects/Pages/ShopCartPage.cs b/webapi/Core/DomainObjects/Pages/ShopCartPage.cs index 4441fa8..7d6486e 100644 --- a/webapi/Core/DomainObjects/Pages/ShopCartPage.cs +++ b/webapi/Core/DomainObjects/Pages/ShopCartPage.cs @@ -3,9 +3,7 @@ using Core.DomainObjects.PageSections; namespace Core.DomainObjects.Pages { public class ShopCartPage : PageBase { - public Header Header { get; set; } - - public TitleSection TitleSection { get; set; } + public ProductsSection ProductsSection { get; set; } diff --git a/webapi/Core/DomainObjects/Pages/ShopCatalogPage.cs b/webapi/Core/DomainObjects/Pages/ShopCatalogPage.cs index f142aec..21569d2 100644 --- a/webapi/Core/DomainObjects/Pages/ShopCatalogPage.cs +++ b/webapi/Core/DomainObjects/Pages/ShopCatalogPage.cs @@ -4,9 +4,7 @@ using Core.DomainObjects.PageSections; namespace Core.DomainObjects.Pages { public class ShopCatalogPage : PageBase { - public Header Header { get; set; } - public TitleSection TitleSection { get; set; } public ShopItemsSection ShopItemsSection { get; set; } diff --git a/webapi/Core/DomainObjects/Pages/ShopCheckoutPage.cs b/webapi/Core/DomainObjects/Pages/ShopCheckoutPage.cs index 3bceb11..600f931 100644 --- a/webapi/Core/DomainObjects/Pages/ShopCheckoutPage.cs +++ b/webapi/Core/DomainObjects/Pages/ShopCheckoutPage.cs @@ -9,8 +9,6 @@ using System.Threading.Tasks; namespace Core.DomainObjects.Pages { public class ShopCheckoutPage : PageBase { - public Header Header { get; set; } - public TitleSection TitleSection { get; set; } public BillingAddressSection BillingAddressSection { get; set; } diff --git a/webapi/Core/DomainObjects/Pages/ShopItemPage.cs b/webapi/Core/DomainObjects/Pages/ShopItemPage.cs index d9cc3ed..36da1b7 100644 --- a/webapi/Core/DomainObjects/Pages/ShopItemPage.cs +++ b/webapi/Core/DomainObjects/Pages/ShopItemPage.cs @@ -4,7 +4,6 @@ using Core.DomainObjects.PageSections; namespace Core.DomainObjects.Pages { public class ShopItemPage : PageBase { - public Header Header { get; set; } public ProductSection ProductSection { get; set; } public RelatedProductsSection RelatedProductsSection { get; set; } diff --git a/webapi/Core/DomainObjects/Pages/SignUpPage.cs b/webapi/Core/DomainObjects/Pages/SignUpPage.cs index d205fe4..15d33df 100644 --- a/webapi/Core/DomainObjects/Pages/SignUpPage.cs +++ b/webapi/Core/DomainObjects/Pages/SignUpPage.cs @@ -6,9 +6,7 @@ using System.Text; using System.Threading.Tasks; namespace Core.DomainObjects.Pages { - public class SignUpPage : PageBase { - - public Header Header { get; set; } + public class SignUpPage : PageBase { public string Title { get; set; } diff --git a/webapi/Core/DomainObjects/Pages/SingInPage.cs b/webapi/Core/DomainObjects/Pages/SingInPage.cs index 860b863..d6ff555 100644 --- a/webapi/Core/DomainObjects/Pages/SingInPage.cs +++ b/webapi/Core/DomainObjects/Pages/SingInPage.cs @@ -8,8 +8,6 @@ using System.Threading.Tasks; namespace Core.DomainObjects.Pages { public class SignInPage : PageBase { - public Header Header { get; set; } - public string Title { get; set; } public FormItem Email { get; set; } diff --git a/webapi/Core/Models/PaginationModel.cs b/webapi/Core/Models/PaginationModel.cs index 3151fa5..9aab35e 100644 --- a/webapi/Core/Models/PaginationModel.cs +++ b/webapi/Core/Models/PaginationModel.cs @@ -7,7 +7,7 @@ using System.Text; using System.Threading.Tasks; namespace Core.Models { - public class PaginationModel : ResponseModel { + public class PaginationModel : ResponseModelBase { public int TotalPages { get; set; } public int CurrentPage { get; set; } public List Items { get; set; } diff --git a/webapi/DataProviders/ContentDataProvider.cs b/webapi/DataProviders/ContentDataProvider.cs index 05fda00..871c90f 100644 --- a/webapi/DataProviders/ContentDataProvider.cs +++ b/webapi/DataProviders/ContentDataProvider.cs @@ -4,19 +4,13 @@ using DomainResults.Common; using Microsoft.Extensions.Logging; using MongoDB.Bson.Serialization; using MongoDB.Driver; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace DataProviders { public interface IContentDataProvider { - (Content?, IDomainResult) Get(Guid id); + (Content?, IDomainResult) Get(Guid siteId, string locale); } - public class ContentDataProvider : DataProviderBase, IContentDataProvider { private const string _collectionName = "content"; @@ -27,8 +21,9 @@ namespace DataProviders { ISessionService sessionService) : base(logger, client, idGenerator, sessionService) { } - public (Content?, IDomainResult) Get(Guid id) { - var (list, result) = GetWithPredicate(x => x.Id == id, _collectionName); + public (Content?, IDomainResult) Get(Guid siteId, string locale) { + var (list, result) = GetWithPredicate(x => x.SiteId == siteId + && (x.Localization.Locale == null || x.Localization.Locale.ToLower() == locale.ToLower()), _collectionName); if (!result.IsSuccess || list == null || list.Count == 0) return (null, result); diff --git a/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs b/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs index b02c6c3..0695d54 100644 --- a/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs +++ b/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs @@ -16,6 +16,7 @@ namespace DataProviders.Extensions services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); Mappings.RegisterClassMap(); } diff --git a/webapi/DataProviders/ShopCartDataProvider.cs b/webapi/DataProviders/ShopCartDataProvider.cs new file mode 100644 index 0000000..6fb76a6 --- /dev/null +++ b/webapi/DataProviders/ShopCartDataProvider.cs @@ -0,0 +1,29 @@ +using Microsoft.Extensions.Logging; + +using DomainResults.Common; + +using MongoDB.Bson.Serialization; +using MongoDB.Driver; + +using DataProviders.Abstractions; +using Core.DomainObjects.Documents; + +namespace DataProviders { + + public interface IShopCartDataProvider { + (List?, IDomainResult) Get(Guid siteId, Guid userId); + } + + public class ShopCartDataProvider : DataProviderBase, IShopCartDataProvider { + private const string _collectionName = "shopcart"; + public ShopCartDataProvider( + ILogger> logger, + IMongoClient client, + IIdGenerator idGenerator, + ISessionService sessionService) : base(logger, client, idGenerator, sessionService) { + } + + public (List?, IDomainResult) Get(Guid siteId, Guid userId) => + GetWithPredicate(x => x.SiteId == siteId && x.UserId == userId, _collectionName); + } +} diff --git a/webapi/DataProviders/ShopDataProvider.cs b/webapi/DataProviders/ShopDataProvider.cs deleted file mode 100644 index 861ca34..0000000 --- a/webapi/DataProviders/ShopDataProvider.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace DataProviders { - - public interface IShopDataProvider { - - } - - public class ShopDataProvider : IShopDataProvider { - - } -} diff --git a/webapi/WeatherForecast/Controllers/ContentController.cs b/webapi/WeatherForecast/Controllers/ContentController.cs index 57b18ce..beb64a2 100644 --- a/webapi/WeatherForecast/Controllers/ContentController.cs +++ b/webapi/WeatherForecast/Controllers/ContentController.cs @@ -38,198 +38,8 @@ public class ContentController : ControllerBase { /// /// [HttpGet("{siteId}")] - public IActionResult Get([FromRoute] Guid siteId, [FromQuery] string? locale = "en-US") { - - var result = _contentService.GetContent(siteId, locale); + public IActionResult Get([FromRoute] Guid siteId, [FromQuery] string? locale) { + var result = _contentService.GetContent(siteId, locale ?? "en-Us") ; return result.ToActionResult(); - - //var routes = new List { - // new RouteModel ("/", "Home"), - // new RouteModel ("/home", "Home") - //}; - - //var shopRoute = new RouteModel("/shop", - // new List { - // new RouteModel ("", "ShopCatalog"), - // new RouteModel (":page", "ShopCatalog"), - // new RouteModel (":page", new List { - // new RouteModel (":slug", "ShopItem") - // }) - //}); - - //var blogRoute = new RouteModel("/blog", - // new List { - // new RouteModel ("", "BlogCatalog"), - // new RouteModel (":page", "BlogCatalog"), - // new RouteModel (":page", new List { - // new RouteModel (":slug", "BlogItem") - // }) - //}); - - //routes.Add(shopRoute); - //routes.Add(blogRoute); - - //var demoRoutes = new List { - // new RouteModel ("/counter", "Counter"), - // new RouteModel ("/fetch-data", new List { - // new RouteModel ("", "FetchData"), - // new RouteModel (":startDateIndex", "FetchData") - // }) - // }; - - //routes = routes.Concat(demoRoutes).ToList(); - - //var adminRoutes = new List { - // new RouteModel ("/admin", "AdminHome") - //}; - - //var serviceRoutes = new List { - // new RouteModel ("/signin", "Signin"), - // new RouteModel ("/signup", "Signup"), - // new RouteModel ("*", "Error") - //}; - - //var topMenu = new List { - // new MenuItemModel ("Home", "/"), - // new MenuItemModel ("Shop", "/shop"), - // new MenuItemModel ("Blog", "/blog"), - // new MenuItemModel ("Signin", "/signin"), - // new MenuItemModel ("Signout", "/signout") - //}; - - //var sideMenu = new List { - // new MenuItemModel ("alert-triangle", "Home", "/admin"), - // new MenuItemModel ("activity", "Page", new List { - // new MenuItemModel ("activity", "Page-1", "Page-1"), - // new MenuItemModel ("activity", "Page-2", "Page-2"), - // new MenuItemModel ("activity", "Page-3", "Page-3") - // }), - // new MenuItemModel ("Counter", "/counter"), - // new MenuItemModel ("Fetch data", "/fetch-data") - //}; - - - - - - - - //var homePage = new HomePageModel { - // TitleSection = new TitleSectionModel { - // Title = "Hello, World! by C#", - // Text = @" - //

Welcome to your new single-page application, built with:

- // ", - // Image = new ImageModel { Src = "https://dummyimage.com/600x400/343a40/6c757d", Alt = "..." }, - // PrimaryLink = new MenuItemModel("Get Started", "#features"), - // SecondaryLink = new MenuItemModel("Learn More", "#!") - // }, - - // FeaturesSection = new FeaturesSectionModel { - // Title = "To help you get started, we have also set up:", - // Items = new List { - // new FeatureModel { - // Icon = "navigation", - // Title = "Client-side navigation", - // Text = "For example, click Counter then Back to return here." - // }, - // new FeatureModel { - // Icon = "server", - // Title = "Development server integration", - // Text = "In development mode, the development server from create-react-app runs in the background automatically, so your client-side resources are dynamically built on demand and the page refreshes when you modify any file." - // }, - // new FeatureModel { - // Icon = "terminal", - // Title = "Efficient production builds", - // Text = "In production mode, development-time features are disabled, and your dotnet publish configuration produces minified, efficiently bundled JavaScript files." - // } - // } - // }, - // TestimonialsSection = new TestimonialsSectionModel { - // Items = new List { - // new TestimonialModel { - // Text = "The ClientApp subdirectory is a standard React application based on the create-react-app template. If you open a command prompt in that directory, you can run yarn commands such as yarn test or yarn install.", - // Reviewer = new ReviewerModel { - // Id = Guid.NewGuid(), - // Image = new ImageModel { Src = "https://dummyimage.com/40x40/ced4da/6c757d", Alt = "..." }, - // FullName = "Admin", - // Position = "CEO, MAKS-IT" - // } - // } - // } - // }, - // FeaturedBlogsSection = new FeaturedBologsSectionModel { - // Title = "From our blog" - // }, - - // CallToActionSection = new CallToActionSectionModel { - // Title = "New products, delivered to you.", - // Text = "Sign up for our newsletter for the latest updates.", - // PrivacyDisclaimer = "We care about privacy, and will never share your data.", - // Email = new FormItemModel { - // PlaceHolder = "Email address...", - // Title = "Sign up" - // } - // } - //}; - - //var shopCatalogPage = new ShopCatalogPageModel { - // TitleSection = new TitleSectionModel { - // Title = "Shop in style", - // Text = "With this shop hompeage template" - // } - //}; - - //var shopItem = new ShopItemPageModel { - // ProductSection = new ProductSectionModel { - // AvailableQuantity = "Available Qty.", - // AddToCart = "Add to cart" - // }, - // RelatedProductsSection = new RelatedProductsSectionModel { - // Title = "Related products" - // } - //}; - - //var blogCatalogPage = new BlogCatalogPageModel { - // TitleSection = new TitleSectionModel { - // Title = "Welcome to Blog Home!", - // Text = "A Bootstrap 5 starter layout for your next blog homepage" - // }, - // FeaturedBlogSection = new FeaturedBlogSectionModel { - // ReadTime = "{date} Time to read: {readTime} min" - // } - //}; - - //var blogItem = new BlogItemPageModel { - // TitleSection = new BlogTitleSectionModel { - // PostedOnBy = "Posted on {date} by {nickName}" - // }, - // CommentsSection = new CommentsSectionModel { - // LeaveComment = "Join the discussion and leave a comment!" - // } - //}; - - //return Ok(new GetContentResponseModel { - // SiteName = "MAKS-IT", - - // Routes = routes, - // AdminRoutes = adminRoutes, - // ServiceRoutes = serviceRoutes, - - // TopMenu = topMenu, - // SideMenu = sideMenu, - - // HomePage = homePage, - - // ShopCatalog = shopCatalogPage, - // ShopItem = shopItem, - - // BlogCatalog = blogCatalogPage, - // Blogitem = blogItem - //}); } } diff --git a/webapi/WeatherForecast/Controllers/LoginController.cs b/webapi/WeatherForecast/Controllers/LoginController.cs index 12d5d46..2bd3df5 100644 --- a/webapi/WeatherForecast/Controllers/LoginController.cs +++ b/webapi/WeatherForecast/Controllers/LoginController.cs @@ -5,7 +5,7 @@ using WeatherForecast.Models; namespace WeatherForecast.Controllers; -public class PostLoginRequest : RequestModel { +public class PostLoginRequest : RequestModelBase { public string Username { get; set; } public string Password { get; set; } diff --git a/webapi/WeatherForecast/Controllers/ShopCartController.cs b/webapi/WeatherForecast/Controllers/ShopCartController.cs new file mode 100644 index 0000000..9f9131b --- /dev/null +++ b/webapi/WeatherForecast/Controllers/ShopCartController.cs @@ -0,0 +1,49 @@ +using DomainResults.Mvc; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using WeatherForecast.Models.Requests; +using WeatherForecast.Services; + +namespace WeatherForecast.Controllers { + + + /// + /// + /// + [ApiController] + [AllowAnonymous] + [Route("api/[controller]")] + public class ShopCartController : ControllerBase { + + private readonly ILogger _logger; + private readonly IShopCartService _shopCartService; + + /// + /// + /// + /// + public ShopCartController( + ILogger logger, + IShopCartService shopCartService + ) { + _logger = logger; + _shopCartService = shopCartService; + } + + /// + /// + /// + /// + [HttpGet("{siteId}/{userId}")] + public IActionResult Get([FromRoute] Guid siteId, [FromRoute] Guid userId) { + var result = _shopCartService.GetShopCart(siteId, userId); + return result.ToActionResult(); + } + + [HttpPut("{siteId}/{userId}/{shopCartId}")] + public IActionResult Update([FromRoute] Guid siteId, [FromRoute] Guid userId, [FromRoute] Guid shopCartId, [FromBody] PutShopCatalogRequestModel requestData) { + var result = _shopCartService.UpdateShopCart(siteId, userId, shopCartId, requestData); + return result.ToActionResult(); + } + } +} diff --git a/webapi/WeatherForecast/Models/Abstractions/PageModelBase.cs b/webapi/WeatherForecast/Models/Abstractions/PageModelBase.cs index 2a12422..a9868f9 100644 --- a/webapi/WeatherForecast/Models/Abstractions/PageModelBase.cs +++ b/webapi/WeatherForecast/Models/Abstractions/PageModelBase.cs @@ -1,11 +1,12 @@  +using Core.Abstractions.DomainObjects; using Core.Abstractions.Models; using Core.DomainObjects; using Core.DomainObjects.PageSections; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Abstractions { - public abstract class PageModelBase : ModelBase { + public abstract class PageModelBase : ModelBase { public HeaderModel Header { get; set; } @@ -13,9 +14,11 @@ namespace WeatherForecast.Models.Abstractions { public PageModelBase() { } - public PageModelBase(Header header, TitleSection titleSection) { - TitleSection = new TitleSectionModel(titleSection); - Header = new HeaderModel(header); + public PageModelBase(PageBase pageBase) { + if(pageBase.TitleSection !=null) + TitleSection = new TitleSectionModel(pageBase.TitleSection); + + Header = new HeaderModel(pageBase.Header); } } } diff --git a/webapi/WeatherForecast/Models/PageSections/ProductsSectionModel.cs b/webapi/WeatherForecast/Models/PageSections/CartProductsSectionModel.cs similarity index 68% rename from webapi/WeatherForecast/Models/PageSections/ProductsSectionModel.cs rename to webapi/WeatherForecast/Models/PageSections/CartProductsSectionModel.cs index 2ce4e01..31f6c05 100644 --- a/webapi/WeatherForecast/Models/PageSections/ProductsSectionModel.cs +++ b/webapi/WeatherForecast/Models/PageSections/CartProductsSectionModel.cs @@ -4,22 +4,22 @@ using Core.DomainObjects.PageSections; using WeatherForecast.Models.Abstractions; namespace WeatherForecast.Models.PageSections { - public class ProductsSectionModel : PageSectionModelBase { + public class CartProductsSectionModel : PageSectionModelBase { public string Product { get; set; } public string Price { get; set; } public string Quantity { get; set; } public string Subtotal { get; set; } public LinkModel ContinueShopping { get; set; } - public FormItemModel Submit { get; set; } + public LinkModel Checkout { get; set; } - public ProductsSectionModel(ProductsSection productsSection) : base(productsSection) { + public CartProductsSectionModel(ProductsSection productsSection) : base(productsSection) { Product = productsSection.Product; Price = productsSection.Price; Quantity = productsSection.Quantity; Subtotal = productsSection.Subtotal; ContinueShopping = new LinkModel(productsSection.ContinueShopping); - Submit = new FormItemModel(productsSection.Submit); + Checkout = new LinkModel(productsSection.Checkout); } } } diff --git a/webapi/WeatherForecast/Models/PageSections/SettingsSectionModel.cs b/webapi/WeatherForecast/Models/PageSections/CheckoutSettingsSectionModel.cs similarity index 69% rename from webapi/WeatherForecast/Models/PageSections/SettingsSectionModel.cs rename to webapi/WeatherForecast/Models/PageSections/CheckoutSettingsSectionModel.cs index 2edbd21..c0a6aa0 100644 --- a/webapi/WeatherForecast/Models/PageSections/SettingsSectionModel.cs +++ b/webapi/WeatherForecast/Models/PageSections/CheckoutSettingsSectionModel.cs @@ -2,12 +2,12 @@ using WeatherForecast.Models.Abstractions; namespace WeatherForecast.Models.PageSections { - public class SettingsSectionModel : PageSectionModelBase { + public class CheckoutSettingsSectionModel : PageSectionModelBase { public string ShippingAddressSameAsBillingAddress { get; set; } public string SaveThisInformation { get; set; } - public SettingsSectionModel(SettingsSection settingsSection) : base(settingsSection) { + public CheckoutSettingsSectionModel(SettingsSection settingsSection) : base(settingsSection) { ShippingAddressSameAsBillingAddress = settingsSection.ShippingAddressSameAsBillingAddress; SaveThisInformation = settingsSection.SaveThisInformation; } diff --git a/webapi/WeatherForecast/Models/PageSections/SummarySectionModel.cs b/webapi/WeatherForecast/Models/PageSections/CheckoutSummarySectionModel.cs similarity index 71% rename from webapi/WeatherForecast/Models/PageSections/SummarySectionModel.cs rename to webapi/WeatherForecast/Models/PageSections/CheckoutSummarySectionModel.cs index 29cfeb3..dc03460 100644 --- a/webapi/WeatherForecast/Models/PageSections/SummarySectionModel.cs +++ b/webapi/WeatherForecast/Models/PageSections/CheckoutSummarySectionModel.cs @@ -2,7 +2,7 @@ using WeatherForecast.Models.Abstractions; namespace WeatherForecast.Models.PageSections { - public class SummarySectionModel : PageSectionModelBase { + public class CheckoutSummarySectionModel : PageSectionModelBase { public string Total { get; set; } @@ -10,7 +10,7 @@ namespace WeatherForecast.Models.PageSections { public FormItemModel Submit { get; set; } - public SummarySectionModel(SummarySection summarySection) : base(summarySection) { + public CheckoutSummarySectionModel(SummarySection summarySection) : base(summarySection) { Total = summarySection.Total; PromoCode = new FormItemModel(summarySection.PromoCode); Submit = new FormItemModel(summarySection.Submit); diff --git a/webapi/WeatherForecast/Models/PageSections/ShopItemsSectionModel.cs b/webapi/WeatherForecast/Models/PageSections/ShopItemsSectionModel.cs new file mode 100644 index 0000000..fb1f534 --- /dev/null +++ b/webapi/WeatherForecast/Models/PageSections/ShopItemsSectionModel.cs @@ -0,0 +1,13 @@ +using Core.DomainObjects.PageSections; +using WeatherForecast.Models.Abstractions; + +namespace WeatherForecast.Models.PageSections { + public class ShopItemsSectionModel : PageSectionModelBase { + + public string AddToCart { get; set; } + + public ShopItemsSectionModel(ShopItemsSection shopItemSection) : base(shopItemSection) { + AddToCart = shopItemSection.AddToCart; + } + } +} diff --git a/webapi/WeatherForecast/Models/Pages/BlogCatalogPageModel.cs b/webapi/WeatherForecast/Models/Pages/BlogCatalogPageModel.cs index 7309346..81d8654 100644 --- a/webapi/WeatherForecast/Models/Pages/BlogCatalogPageModel.cs +++ b/webapi/WeatherForecast/Models/Pages/BlogCatalogPageModel.cs @@ -3,11 +3,11 @@ using WeatherForecast.Models.Abstractions; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Pages { - public class BlogCatalogPageModel : PageModelBase { + public class BlogCatalogPageModel : PageModelBase { public FeaturedBlogSectionModel FeaturedBlogSection { get; set; } - public BlogCatalogPageModel(BlogCatalogPage blogCatalogPage) : base(blogCatalogPage.Header, blogCatalogPage.TitleSection) { + public BlogCatalogPageModel(BlogCatalogPage blogCatalogPage) : base(blogCatalogPage) { FeaturedBlogSection = new FeaturedBlogSectionModel(blogCatalogPage.FeaturedBlogSection); } } diff --git a/webapi/WeatherForecast/Models/Pages/BlogItemPageModel.cs b/webapi/WeatherForecast/Models/Pages/BlogItemPageModel.cs index 1100a6d..65f3612 100644 --- a/webapi/WeatherForecast/Models/Pages/BlogItemPageModel.cs +++ b/webapi/WeatherForecast/Models/Pages/BlogItemPageModel.cs @@ -3,10 +3,10 @@ using WeatherForecast.Models.Abstractions; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Pages { - public class BlogItemPageModel : PageModelBase { + public class BlogItemPageModel : PageModelBase { public CommentsSectionModel CommentsSection { get; set; } - public BlogItemPageModel(BlogItemPage blogItemPage) : base(blogItemPage.Header, blogItemPage.TitleSection) { + public BlogItemPageModel(BlogItemPage blogItemPage) : base(blogItemPage) { CommentsSection = new CommentsSectionModel(blogItemPage.CommentsSection); } } diff --git a/webapi/WeatherForecast/Models/Pages/HomePageModel.cs b/webapi/WeatherForecast/Models/Pages/HomePageModel.cs index de3caa2..1aea4fe 100644 --- a/webapi/WeatherForecast/Models/Pages/HomePageModel.cs +++ b/webapi/WeatherForecast/Models/Pages/HomePageModel.cs @@ -3,16 +3,13 @@ using WeatherForecast.Models.Abstractions; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Pages { - public class HomePageModel : PageModelBase{ - public TitleSectionModel TitleSection { get; set; } - public FeaturesSectionModel FeaturesSection { get; set; } + public class HomePageModel : PageModelBase { + public TestimonialsSectionModel TestimonialsSection { get; set; } public FeaturedBlogsSectionModel FeaturedBlogsSection { get; set; } public CallToActionSectionModel CallToActionSection { get; set; } - public HomePageModel(HomePage homePage) { - TitleSection = new TitleSectionModel(homePage.TitleSection); - FeaturesSection = new FeaturesSectionModel(homePage.FeaturesSection); + public HomePageModel(HomePage homePage) : base(homePage) { TestimonialsSection = new TestimonialsSectionModel(homePage.TestimonialsSection); FeaturedBlogsSection = new FeaturedBlogsSectionModel(homePage.FeaturedBlogsSection); CallToActionSection = new CallToActionSectionModel(homePage.CallToActionSection); diff --git a/webapi/WeatherForecast/Models/Pages/ShopCartPageModel.cs b/webapi/WeatherForecast/Models/Pages/ShopCartPageModel.cs index 4be2f5e..06f4728 100644 --- a/webapi/WeatherForecast/Models/Pages/ShopCartPageModel.cs +++ b/webapi/WeatherForecast/Models/Pages/ShopCartPageModel.cs @@ -4,13 +4,13 @@ using WeatherForecast.Models.Abstractions; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Pages { - public class ShopCartPageModel : PageModelBase { + public class ShopCartPageModel : PageModelBase { - public ProductsSectionModel ProductsSectionModel { get; set; } + public CartProductsSectionModel ProductsSection { get; set; } - public ShopCartPageModel(ShopCartPage shopCartPage) : base(shopCartPage.Header, shopCartPage.TitleSection) { + public ShopCartPageModel(ShopCartPage shopCartPage) : base(shopCartPage) { - ProductsSectionModel = new ProductsSectionModel(shopCartPage.ProductsSection); + ProductsSection = new CartProductsSectionModel(shopCartPage.ProductsSection); } } } diff --git a/webapi/WeatherForecast/Models/Pages/ShopCatalogPageModel.cs b/webapi/WeatherForecast/Models/Pages/ShopCatalogPageModel.cs index b887bb7..d6f1761 100644 --- a/webapi/WeatherForecast/Models/Pages/ShopCatalogPageModel.cs +++ b/webapi/WeatherForecast/Models/Pages/ShopCatalogPageModel.cs @@ -3,7 +3,13 @@ using WeatherForecast.Models.Abstractions; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Pages { - public class ShopCatalogPageModel : PageModelBase { - public ShopCatalogPageModel(ShopCatalogPage shopCatalogPage) : base(shopCatalogPage.Header, shopCatalogPage.TitleSection) { } + public class ShopCatalogPageModel : PageModelBase { + + public ShopItemsSectionModel ShopItemsSection { get; set; } + + public ShopCatalogPageModel(ShopCatalogPage shopCatalogPage) : base(shopCatalogPage) { + + ShopItemsSection = new ShopItemsSectionModel(shopCatalogPage.ShopItemsSection); + } } } diff --git a/webapi/WeatherForecast/Models/Pages/ShopCheckoutPageModel.cs b/webapi/WeatherForecast/Models/Pages/ShopCheckoutPageModel.cs index da18514..aa32c30 100644 --- a/webapi/WeatherForecast/Models/Pages/ShopCheckoutPageModel.cs +++ b/webapi/WeatherForecast/Models/Pages/ShopCheckoutPageModel.cs @@ -3,21 +3,21 @@ using WeatherForecast.Models.Abstractions; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Pages { - public class ShopCheckoutPageModel : PageModelBase { + public class ShopCheckoutPageModel : PageModelBase { public BillingAddressSectionModel BillingAddressSection { get; set; } public ShippingAddressSectionModel ShippingAddressSection { get; set; } - public SettingsSectionModel SettingsSection { get; set; } - public SummarySectionModel SummarySection { get; set; } + public CheckoutSettingsSectionModel SettingsSection { get; set; } + public CheckoutSummarySectionModel SummarySection { get; set; } public PaymentSectionModel PaymentSection { get; set; } public FormItemModel Submit { get; set; } - public ShopCheckoutPageModel(ShopCheckoutPage shopCheckoutPage) : base(shopCheckoutPage.Header, shopCheckoutPage.TitleSection) { + public ShopCheckoutPageModel(ShopCheckoutPage shopCheckoutPage) : base(shopCheckoutPage) { BillingAddressSection = new BillingAddressSectionModel(shopCheckoutPage.BillingAddressSection); ShippingAddressSection = new ShippingAddressSectionModel(shopCheckoutPage.ShippingAddressSection); - SettingsSection = new SettingsSectionModel(shopCheckoutPage.SettingsSection); - SummarySection = new SummarySectionModel(shopCheckoutPage.SummarySection); + SettingsSection = new CheckoutSettingsSectionModel(shopCheckoutPage.SettingsSection); + SummarySection = new CheckoutSummarySectionModel(shopCheckoutPage.SummarySection); PaymentSection = new PaymentSectionModel(shopCheckoutPage.PaymentSection); Submit = new FormItemModel(shopCheckoutPage.Submit); diff --git a/webapi/WeatherForecast/Models/Pages/ShopItemPageModel.cs b/webapi/WeatherForecast/Models/Pages/ShopItemPageModel.cs index 9230ce5..c984c74 100644 --- a/webapi/WeatherForecast/Models/Pages/ShopItemPageModel.cs +++ b/webapi/WeatherForecast/Models/Pages/ShopItemPageModel.cs @@ -3,11 +3,11 @@ using WeatherForecast.Models.Abstractions; using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Pages { - public class ShopItemPageModel : PageModelBase { + public class ShopItemPageModel : PageModelBase { public ProductSectionModel ProductSection { get; set; } public RelatedProductsSectionModel RelatedProductsSection { get; set; } - public ShopItemPageModel(ShopItemPage shopItemPage) : base() { + public ShopItemPageModel(ShopItemPage shopItemPage) : base(shopItemPage) { ProductSection = new ProductSectionModel(shopItemPage.ProductSection); RelatedProductsSection = new RelatedProductsSectionModel(shopItemPage.RelatedProductsSection); diff --git a/webapi/WeatherForecast/Models/Pages/SignInPageModel.cs b/webapi/WeatherForecast/Models/Pages/SignInPageModel.cs new file mode 100644 index 0000000..780f614 --- /dev/null +++ b/webapi/WeatherForecast/Models/Pages/SignInPageModel.cs @@ -0,0 +1,28 @@ +using Core.DomainObjects.Pages; +using WeatherForecast.Models.Abstractions; + +namespace WeatherForecast.Models.Pages { + public class SignInPageModel : PageModelBase { + + public string Title { get; set; } + + public FormItemModel Email { get; set; } + public FormItemModel Password { get; set; } + + public string DontHaveAnAccount { get; set; } + + public LinkModel SignUpLink { get; set; } + + public FormItemModel Submit { get; set; } + + public SignInPageModel(SignInPage signInPage) : base(signInPage) { + + Title = signInPage.Title; + Email = new FormItemModel(signInPage.Email); + Password = new FormItemModel(signInPage.Password); + DontHaveAnAccount = signInPage.DontHaveAnAccount; + SignUpLink = new LinkModel(signInPage.SignUpLink); + Submit = new FormItemModel(signInPage.Submit); + } + } +} diff --git a/webapi/WeatherForecast/Models/Pages/SignUpPageModel.cs b/webapi/WeatherForecast/Models/Pages/SignUpPageModel.cs new file mode 100644 index 0000000..29e138d --- /dev/null +++ b/webapi/WeatherForecast/Models/Pages/SignUpPageModel.cs @@ -0,0 +1,27 @@ +using Core.DomainObjects.Pages; +using WeatherForecast.Models.Abstractions; + +namespace WeatherForecast.Models.Pages { + public class SignUpPageModel : PageModelBase { + + public string Title { get; set; } + public FormItemModel Username { get; set; } + public FormItemModel Email { get; set; } + public FormItemModel ReEmail { get; set; } + public FormItemModel Password { get; set; } + public FormItemModel RePassword { get; set; } + public string AcceptTermsAndConditions { get; set; } + public FormItemModel Submit { get; set; } + + public SignUpPageModel(SignUpPage signUpPage) : base(signUpPage) { + Title = signUpPage.Title; + Username = new FormItemModel(signUpPage.Username); + Email = new FormItemModel(signUpPage.Email); + ReEmail = new FormItemModel(signUpPage.ReEmail); + Password = new FormItemModel(signUpPage.Password); + RePassword = new FormItemModel(signUpPage.RePassword); + AcceptTermsAndConditions = signUpPage.AcceptTermsAndConditions; + Submit = new FormItemModel(signUpPage.Submit); + } + } +} diff --git a/webapi/WeatherForecast/Models/Requests/PutShopCatalogRequestModel.cs b/webapi/WeatherForecast/Models/Requests/PutShopCatalogRequestModel.cs new file mode 100644 index 0000000..917eefb --- /dev/null +++ b/webapi/WeatherForecast/Models/Requests/PutShopCatalogRequestModel.cs @@ -0,0 +1,37 @@ +using Core.Abstractions.Models; +using Core.DomainObjects; +using Core.DomainObjects.Documents; + +namespace WeatherForecast.Models.Requests { + public class PutShopCatalogRequestModel : RequestModelBase { + + public string Slug { get; set; } + public string Sku { get; set; } + public ImageModel Image { get; set; } + public string Title { get; set; } + public string BrandName { get; set; } + public string ShortText { get; set; } + public DateTime Created { get; set; } + public double Price { get; set; } + public double NewPrice { get; set; } + public uint Quantity { get; set; } + + public override ShopCart ToDomainObject() { + return new ShopCart { + Slug = Slug, + Sku = Sku, + Image = new Image { + Src = Image.Src, + Alt = Image.Alt + }, + Title = Title, + BrandName = BrandName, + ShortText = ShortText, + Created = Created, + Price = Price, + NewPrice = NewPrice, + Quantity = Quantity + }; + } + } +} diff --git a/webapi/WeatherForecast/Models/Responses/GetBlogCatalogResponseModel.cs b/webapi/WeatherForecast/Models/Responses/GetBlogCatalogResponseModel.cs index 351184f..21ae32b 100644 --- a/webapi/WeatherForecast/Models/Responses/GetBlogCatalogResponseModel.cs +++ b/webapi/WeatherForecast/Models/Responses/GetBlogCatalogResponseModel.cs @@ -2,7 +2,7 @@ using Core.Models; namespace WeatherForecast.Models.Responses { - public class GetBlogCatalogResponseModel : ResponseModel { + public class GetBlogCatalogResponseModel : ResponseModelBase { public BlogItemModel FeaturedBlog { get; set; } diff --git a/webapi/WeatherForecast/Models/Responses/GetBlogCategoriesResponseModel.cs b/webapi/WeatherForecast/Models/Responses/GetBlogCategoriesResponseModel.cs index 04005cc..a21576a 100644 --- a/webapi/WeatherForecast/Models/Responses/GetBlogCategoriesResponseModel.cs +++ b/webapi/WeatherForecast/Models/Responses/GetBlogCategoriesResponseModel.cs @@ -1,7 +1,7 @@ using Core.Abstractions.Models; namespace WeatherForecast.Models.Responses { - public class GetBlogCategoriesResponseModel : ResponseModel { + public class GetBlogCategoriesResponseModel : ResponseModelBase { public List Items { get; set; } } } diff --git a/webapi/WeatherForecast/Models/Responses/GetBlogFeaturedResponseModel.cs b/webapi/WeatherForecast/Models/Responses/GetBlogFeaturedResponseModel.cs index e3fa736..5ae1632 100644 --- a/webapi/WeatherForecast/Models/Responses/GetBlogFeaturedResponseModel.cs +++ b/webapi/WeatherForecast/Models/Responses/GetBlogFeaturedResponseModel.cs @@ -5,7 +5,7 @@ namespace WeatherForecast.Models.Responses { /// /// /// - public class GetBlogFeaturedResponseModel : ResponseModel { + public class GetBlogFeaturedResponseModel : ResponseModelBase { /// /// diff --git a/webapi/WeatherForecast/Models/Responses/GetContentResponseModel.cs b/webapi/WeatherForecast/Models/Responses/GetContentResponseModel.cs index 9d6a65f..c93e5e4 100644 --- a/webapi/WeatherForecast/Models/Responses/GetContentResponseModel.cs +++ b/webapi/WeatherForecast/Models/Responses/GetContentResponseModel.cs @@ -6,7 +6,7 @@ using WeatherForecast.Models.PageSections; namespace WeatherForecast.Models.Responses { - public class GetContentResponseModel : ResponseModel { + public class GetContentResponseModel : ResponseModelBase { public string SiteName { get; set; } public string SiteUrl { get; set; } @@ -43,6 +43,9 @@ namespace WeatherForecast.Models.Responses { public BlogCatalogPageModel BlogCatalog { get; set; } public BlogItemPageModel BlogItem { get; set; } + public SignInPageModel SignIn { get; set; } + public SignUpPageModel SignUp { get; set; } + public GetContentResponseModel(Content domainObject) { SiteName = domainObject.SiteName; @@ -59,6 +62,7 @@ namespace WeatherForecast.Models.Responses { SideMenu = domainObject.SideMenu.Select(x => new MenuItemModel(x)).ToList(); HomePage = new HomePageModel(domainObject.HomePage); + ShopCatalog = new ShopCatalogPageModel(domainObject.ShopCatalog); ShopItem = new ShopItemPageModel(domainObject.ShopItem); ShopCart = new ShopCartPageModel(domainObject.ShopCart); @@ -66,6 +70,9 @@ namespace WeatherForecast.Models.Responses { BlogCatalog = new BlogCatalogPageModel(domainObject.BlogCatalog); BlogItem = new BlogItemPageModel(domainObject.BlogItem); + + SignIn = new SignInPageModel(domainObject.SignIn); + SignUp = new SignUpPageModel(domainObject.SignUp); } } } diff --git a/webapi/WeatherForecast/Models/Responses/GetShopCartResponseModel.cs b/webapi/WeatherForecast/Models/Responses/GetShopCartResponseModel.cs new file mode 100644 index 0000000..246b03a --- /dev/null +++ b/webapi/WeatherForecast/Models/Responses/GetShopCartResponseModel.cs @@ -0,0 +1,14 @@ +using Core.Abstractions.Models; +using Core.DomainObjects.Documents; + +namespace WeatherForecast.Models.Responses { + public class GetShopCartResponseModel : ResponseModelBase { + + public List Items { get; set; } + + public GetShopCartResponseModel(List items) { + Items = items.Select(x => new ShopCartModel(x)).ToList(); + + } + } +} diff --git a/webapi/WeatherForecast/Models/Responses/GetShopCatalogResponseModel.cs b/webapi/WeatherForecast/Models/Responses/GetShopCatalogResponseModel.cs index da55dbe..f2e3146 100644 --- a/webapi/WeatherForecast/Models/Responses/GetShopCatalogResponseModel.cs +++ b/webapi/WeatherForecast/Models/Responses/GetShopCatalogResponseModel.cs @@ -2,7 +2,7 @@ using Core.Models; namespace WeatherForecast.Models.Responses { - public class GetShopCatalogResponseModel : ResponseModel { + public class GetShopCatalogResponseModel : ResponseModelBase { public PaginationModel ShopItemsPagination { get; set; } } } diff --git a/webapi/WeatherForecast/Models/Responses/GetWeatherForecastResponseModel.cs b/webapi/WeatherForecast/Models/Responses/GetWeatherForecastResponseModel.cs index 237cc89..bd5b082 100644 --- a/webapi/WeatherForecast/Models/Responses/GetWeatherForecastResponseModel.cs +++ b/webapi/WeatherForecast/Models/Responses/GetWeatherForecastResponseModel.cs @@ -1,7 +1,7 @@ using Core.Abstractions.Models; namespace WeatherForecast.Models.Responses { - public class GetWeatherForecastResponseModel : ResponseModel { + public class GetWeatherForecastResponseModel : ResponseModelBase { public DateTime Date { get; set; } public int TemperatureC { get; set; } diff --git a/webapi/WeatherForecast/Models/ShopCartModel.cs b/webapi/WeatherForecast/Models/ShopCartModel.cs new file mode 100644 index 0000000..a3dc710 --- /dev/null +++ b/webapi/WeatherForecast/Models/ShopCartModel.cs @@ -0,0 +1,33 @@ +using Core.Abstractions.Models; +using Core.DomainObjects.Documents; + +namespace WeatherForecast.Models { + public class ShopCartModel : ModelBase { + + public string Slug { get; set; } + public string Sku { get; set; } + public ImageModel Image { get; set; } + public string Title { get; set; } + public string BrandName { get; set; } + public string ShortText { get; set; } + public DateTime Created { get; set; } + public double Price { get; set; } + public double NewPrice { get; set; } + public uint Quantity { get; set; } + + public ShopCartModel() { } + + public ShopCartModel(ShopCart shopCart) { + Slug = shopCart.Slug; + Sku = shopCart.Sku; + Image = new ImageModel(shopCart.Image); + Title = shopCart.Title; + BrandName = shopCart.BrandName; + ShortText = shopCart.ShortText; + Created = shopCart.Created; + Price = shopCart.Price; + NewPrice = shopCart.NewPrice; + Quantity = shopCart.Quantity; + } + } +} diff --git a/webapi/WeatherForecast/Services/ContentService.cs b/webapi/WeatherForecast/Services/ContentService.cs index dfe4339..1387770 100644 --- a/webapi/WeatherForecast/Services/ContentService.cs +++ b/webapi/WeatherForecast/Services/ContentService.cs @@ -1,12 +1,12 @@ using DataProviders; using DomainResults.Common; -using ExtensionMethods; + using WeatherForecast.Models.Responses; namespace WeatherForecast.Services { public interface IContentService { - (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string? locale); + (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale); } public class ContentService : IContentService { @@ -22,8 +22,8 @@ namespace WeatherForecast.Services { _contentDataProvider = contentDataprovider; } - public (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string? locale) { - var (content, result) = _contentDataProvider.Get("b3f39a82-6a1b-46a4-85cc-04c3b4315511".ToGuid()); + public (GetContentResponseModel?, IDomainResult) GetContent(Guid siteId, string locale) { + var (content, result) = _contentDataProvider.Get(siteId, locale); if (!result.IsSuccess || content == null) return (null, result); diff --git a/webapi/WeatherForecast/Services/ShopCartService.cs b/webapi/WeatherForecast/Services/ShopCartService.cs new file mode 100644 index 0000000..53fe7ce --- /dev/null +++ b/webapi/WeatherForecast/Services/ShopCartService.cs @@ -0,0 +1,46 @@ +using DataProviders; +using DomainResults.Common; + +using WeatherForecast.Models.Requests; +using WeatherForecast.Models.Responses; + +namespace WeatherForecast.Services { + + public interface IShopCartService { + (GetShopCartResponseModel?, IDomainResult) GetShopCart(Guid siteId, Guid userId); + (Guid?, IDomainResult) UpdateShopCart(Guid siteId, Guid userId, Guid shopCartId, PutShopCatalogRequestModel requestData); + } + + public class ShopCartService : IShopCartService { + + ILogger _logger; + IShopCartDataProvider _shopCartDataProvider; + + public ShopCartService( + ILogger logger, + IShopCartDataProvider shopCartDataprovider + ) { + _logger = logger; + _shopCartDataProvider = shopCartDataprovider; + } + + public (GetShopCartResponseModel?, IDomainResult) GetShopCart(Guid siteId, Guid userId) { + var (items, result) = _shopCartDataProvider.Get(siteId, userId); + + if (!result.IsSuccess || items == null) + return (null, result); + + return IDomainResult.Success(new GetShopCartResponseModel(items)); + } + + public (Guid?, IDomainResult) UpdateShopCart(Guid siteId, Guid userId, Guid shopCartId, PutShopCatalogRequestModel requestData) { + var shopCart = requestData.ToDomainObject(); + + shopCart.Id = shopCartId; + shopCart.SiteId = siteId; + shopCart.UserId = userId; + + return IDomainResult.Failed(); + } + } +} diff --git a/webapi/WeatherForecast/Startup.cs b/webapi/WeatherForecast/Startup.cs index 99ca36c..3f72035 100644 --- a/webapi/WeatherForecast/Startup.cs +++ b/webapi/WeatherForecast/Startup.cs @@ -58,6 +58,7 @@ namespace WeatherForecast { services.AddHttpContextAccessor(); services.AddScoped(); + services.AddScoped(); services.RegisterDataproviders(appSettings); diff --git a/webapi/WeatherForecast/WeatherForecast.csproj b/webapi/WeatherForecast/WeatherForecast.csproj index fab6f9c..fd99840 100644 --- a/webapi/WeatherForecast/WeatherForecast.csproj +++ b/webapi/WeatherForecast/WeatherForecast.csproj @@ -25,8 +25,4 @@ - - - -