├── .gitattributes ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── Deploy ├── copy-images.sh └── deployment.json ├── Documents └── Images │ ├── Coupon.png │ ├── Coupon_1.png │ ├── Coupon_2.png │ ├── Coupon_3.png │ ├── Coupon_4.png │ ├── Desktop.png │ └── deploy-to-azure.png ├── LICENSE ├── README.md ├── SECURITY.md └── Source ├── .editorconfig ├── CouponReader.Common ├── Controls │ ├── CouponDetailsControl.xaml │ ├── CouponDetailsControl.xaml.cs │ ├── CouponsHistoryControl.xaml │ └── CouponsHistoryControl.xaml.cs ├── Converters │ ├── BoolToVisibilityConverter.cs │ └── InverseBoolToVisibilityConverter.cs ├── CouponReader.Common.csproj ├── Helpers │ └── MapControlHelper.cs ├── Models │ ├── Coupon.cs │ └── CouponHistory.cs ├── Properties │ └── AssemblyInfo.cs ├── Services │ └── CouponsService.cs ├── Settings.cs ├── ViewModels │ └── CouponViewModel.cs ├── app.config └── packages.config ├── CouponReader.Core.Common ├── Controls │ ├── CouponDetailsControl.xaml │ ├── CouponDetailsControl.xaml.cs │ ├── CouponsHistoryControl.xaml │ └── CouponsHistoryControl.xaml.cs ├── Converters │ ├── BoolToVisibilityConverter.cs │ └── InverseBoolToVisibilityConverter.cs ├── CouponReader.Core.Common.csproj ├── Helpers │ └── MapControlHelper.cs ├── Models │ ├── Coupon.cs │ └── CouponHistory.cs ├── Services │ └── CouponsService.cs ├── Settings.cs └── ViewModels │ └── CouponViewModel.cs ├── CouponReader.Core.Forms ├── App.config ├── CouponReader.Core.WindowsForms.csproj ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Resources │ └── Images │ │ ├── Coupon.png │ │ ├── ic_clear.png │ │ ├── ic_error.png │ │ ├── ic_history.png │ │ ├── ic_no.png │ │ ├── ic_scan.png │ │ ├── ic_valid.png │ │ ├── logo_horizontal-b.png │ │ └── logo_vertical-b.png └── tail.ico ├── CouponReader.Core.Wpf ├── App.config ├── App.xaml ├── App.xaml.cs ├── CouponReader.Core.Wpf.csproj ├── Properties │ └── launchSettings.json ├── Resources │ ├── Fonts │ │ ├── BrandonGrotesque-Light.otf │ │ └── BrandonGrotesque-Medium.otf │ └── Images │ │ ├── Coupon.png │ │ ├── ic_clear.png │ │ ├── ic_error.png │ │ ├── ic_history.png │ │ ├── ic_no.png │ │ ├── ic_scan.png │ │ ├── ic_valid.png │ │ ├── logo_horizontal-b.png │ │ └── logo_vertical-b.png ├── Shell.xaml ├── Shell.xaml.cs ├── app1.manifest └── tail.ico ├── CouponReader.Forms ├── App.config ├── CouponReader.WindowsForms.csproj ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── packages.config └── tail.ico ├── CouponReader.NETCore.sln ├── CouponReader.NETFramework.sln ├── CouponReader.Tests ├── CouponReader.Tests.csproj ├── CouponsServiceTests.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── CouponReader.UnitTests ├── CouponReader.UnitTests.csproj └── CouponsServiceTests.cs ├── CouponReader.WPF.sln ├── CouponReader.WinForms.sln ├── CouponReader.Wpf.Core.Module ├── CouponReader.Wpf.Core.Module.csproj ├── CouponReaderModule.cs ├── RegionNames.cs ├── Services │ └── LoginService.cs ├── ViewModels │ ├── LoginViewModel.cs │ └── MainViewModel.cs └── Views │ ├── LoginView.xaml │ ├── LoginView.xaml.cs │ ├── MainView.xaml │ └── MainView.xaml.cs ├── CouponReader.Wpf.Module ├── CouponReader.Wpf.Module.csproj ├── CouponReaderModule.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── RegionNames.cs ├── Services │ └── LoginService.cs ├── ViewModels │ ├── LoginViewModel.cs │ └── MainViewModel.cs └── Views │ ├── LoginView.xaml │ ├── LoginView.xaml.cs │ ├── MainView.xaml │ └── MainView.xaml.cs ├── CouponReader.Wpf ├── App.config ├── App.xaml ├── App.xaml.cs ├── CouponReader.Wpf.csproj ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── Fonts │ │ ├── BrandonGrotesque-Light.otf │ │ └── BrandonGrotesque-Medium.otf │ └── Images │ │ ├── Coupon.png │ │ ├── Thumbs.db │ │ ├── ic_clear.png │ │ ├── ic_error.png │ │ ├── ic_history.png │ │ ├── ic_no.png │ │ ├── ic_scan.png │ │ ├── ic_valid.png │ │ ├── logo_horizontal-b.png │ │ └── logo_vertical-b.png ├── Shell.xaml ├── Shell.xaml.cs └── tail.ico ├── CouponReader.sln ├── Directory.Build.props ├── NuGet.config ├── WPFNetFX ├── App.config ├── App.xaml ├── App.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs └── WPFNetFX.csproj ├── db ├── azure.txt ├── deploy.json └── deploy.ps1 ├── global.json └── localNugets ├── Microsoft.Toolkit.Forms.UI.XamlHost.5.1.0-build.4.nupkg ├── Microsoft.Toolkit.Wpf.UI.XamlHost.5.1.0-build.4.nupkg ├── Microsoft.Win10.Contracts.10.0.17763.nupkg ├── System.Runtime.WindowsRuntime.4.6.0-dev.18570.1.nupkg ├── System.Runtime.WindowsRuntime.UI.Xaml.4.6.0-dev.18570.1.nupkg ├── microsoft.toolkit.wpf.ui.controls.5.0.0.nupkg └── microsoft.toolkit.wpf.ui.xamlhost.5.0.0.nupkg /.gitattributes: -------------------------------------------------------------------------------- 1 | # Sell script for Linux 2 | *.sh text eol=lf -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [main, ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [main] 9 | schedule: 10 | - cron: '0 2 * * 2' 11 | 12 | jobs: 13 | analyse: 14 | name: Analyse 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v2 20 | with: 21 | # We must fetch at least the immediate parents so that if this is 22 | # a pull request then we can checkout the head. 23 | fetch-depth: 2 24 | 25 | # If this run was triggered by a pull request event, then checkout 26 | # the head of the pull request instead of the merge commit. 27 | - run: git checkout HEAD^2 28 | if: ${{ github.event_name == 'pull_request' }} 29 | 30 | # Initializes the CodeQL tools for scanning. 31 | - name: Initialize CodeQL 32 | uses: github/codeql-action/init@v1 33 | # Override language selection by uncommenting this and choosing your languages 34 | # with: 35 | # languages: go, javascript, csharp, python, cpp, java 36 | 37 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 38 | # If this step fails, then you should remove it and run the build manually (see below) 39 | - name: Autobuild 40 | uses: github/codeql-action/autobuild@v1 41 | 42 | # ℹ️ Command-line programs to run using the OS shell. 43 | # 📚 https://git.io/JvXDl 44 | 45 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 46 | # and modify them (or add more) to build your code if your project 47 | # uses a compiled language 48 | 49 | #- run: | 50 | # make bootstrap 51 | # make release 52 | 53 | - name: Perform CodeQL Analysis 54 | uses: github/codeql-action/analyze@v1 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | bin/ 3 | obj/ 4 | 5 | *.user 6 | **/packages/ -------------------------------------------------------------------------------- /Deploy/copy-images.sh: -------------------------------------------------------------------------------- 1 | couponsRg=${TT_COUPONS_RG} 2 | couponsRegion=${TT_COUPONS_REGION} 3 | name=${TT_STORAGE_NAME} 4 | sourcepath="../Documents/Images" 5 | 6 | function validate { 7 | valid=1 8 | 9 | if [[ "$couponsRg" == "" ]] 10 | then 11 | echo "No resource group. Use -g to specify resource group." 12 | valid=0 13 | fi 14 | 15 | if [[ "$name" == "" ]] 16 | then 17 | echo "No storage name specified: Please, set a storage name using -n" 18 | valid=0 19 | fi 20 | 21 | if (( valid == 0)) 22 | then 23 | exit 1 24 | fi 25 | } 26 | 27 | while [ "$1" != "" ]; do 28 | case $1 in 29 | -g | --resource-group) shift 30 | couponsRg=$1 31 | ;; 32 | -n | --name) shift 33 | name=$1 34 | ;; 35 | -f | --source-path) shift 36 | sourcepath=$1 37 | ;; 38 | * ) echo "Invalid param: $1" 39 | exit 1 40 | esac 41 | shift 42 | done 43 | 44 | validate 45 | 46 | constr=$(az storage account show-connection-string -g $couponsRg -n $name | jq ".connectionString" | tr -d '"') 47 | 48 | echo "------------------------------------------------------------" 49 | echo "Copying files from $sourcepath to storage $name" 50 | echo "------------------------------------------------------------" 51 | az storage blob upload-batch --source $sourcepath --connection-string "$constr" -d coupons-images 52 | -------------------------------------------------------------------------------- /Deploy/deployment.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { }, 5 | "variables": { 6 | "storage_name": "[concat('ttstorage',uniqueString(resourceGroup().id))]" 7 | }, 8 | "resources": [ 9 | { 10 | "name": "[variables('storage_name')]", 11 | "type": "Microsoft.Storage/storageAccounts", 12 | "apiVersion": "2018-07-01", 13 | "location": "[resourceGroup().location]", 14 | "properties": { 15 | "accessTier": "Hot", 16 | "supportsHttpsTrafficOnly": false 17 | }, 18 | "dependsOn": [], 19 | "sku": { 20 | "name": "Standard_LRS" 21 | }, 22 | "kind": "StorageV2" 23 | } 24 | ], 25 | "outputs": { 26 | "storage": { 27 | "type": "string", 28 | "value": "[variables('storage_name')]" 29 | 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Documents/Images/Coupon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Documents/Images/Coupon.png -------------------------------------------------------------------------------- /Documents/Images/Coupon_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Documents/Images/Coupon_1.png -------------------------------------------------------------------------------- /Documents/Images/Coupon_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Documents/Images/Coupon_2.png -------------------------------------------------------------------------------- /Documents/Images/Coupon_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Documents/Images/Coupon_3.png -------------------------------------------------------------------------------- /Documents/Images/Coupon_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Documents/Images/Coupon_4.png -------------------------------------------------------------------------------- /Documents/Images/Desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Documents/Images/Desktop.png -------------------------------------------------------------------------------- /Documents/Images/deploy-to-azure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Documents/Images/deploy-to-azure.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tailwind Traders Desktop Reference App 2 | 3 | ![Tailwind Traders Desktop](Documents/Images/Desktop.png) 4 | 5 | | DevOps | master | 6 | | ----------------- | ------------------------------------------------------------ | 7 | | Windows | [![Build status](https://dev.azure.com/tailwindtraders/Desktop/_apis/build/status/Desktop-.NET%20Desktop-CI)](https://dev.azure.com/tailwindtraders/Desktop/_build/latest?definitionId=4) | 8 | 9 | Download the latest release [here](https://tailwindtradersdesktop.blob.core.windows.net/release/tailwindtradersdesktop/TailwindTradersDesktop.zip ). 10 | 11 | # DemoScript 12 | 13 | Check out the [Productivity Improvements in Visual Studio 2019](https://github.com/Microsoft/TailwindTraders/tree/master/Documents/DemoScripts/Productivity%20Improvements%20in%20Visual%20Studio%202019) demo script. 14 | 15 | # Feedback 16 | [Help us improving this reference application by providing us your valuable opinion](https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR8SMkUX-TIVBhIdeQCM_fI1UQzI4SDRIWFRGUU1aRkpDT1hDSUxKUFNRTyQlQCN0PWcu). 17 | 18 | # Repositories 19 | 20 | For this demo reference, we built several consumer and line-of-business applications and a set of backend services. You can find all repositories in the following locations: 21 | 22 | * [Tailwind Traders](https://github.com/Microsoft/TailwindTraders) 23 | * [Backend (AKS)](https://github.com/Microsoft/TailwindTraders-Backend) 24 | * [Website (ASP.NET & React)](https://github.com/Microsoft/TailwindTraders-Website) 25 | * [Desktop (WinForms & WPF -.NET Core)](https://github.com/Microsoft/TailwindTraders-Desktop) 26 | * [Rewards (ASP.NET Framework)](https://github.com/Microsoft/TailwindTraders-Rewards) 27 | * [Mobile (Xamarin Forms 4.0)](https://github.com/Microsoft/TailwindTraders-Mobile) 28 | 29 | ## PRISM 30 | Prism is a framework for building loosely coupled, maintainable, and testable XAML applications in WPF, Windows 10 UWP, and Xamarin Forms. 31 | 32 | Official Prism releases are available on NuGet. Simply add https://www.myget.org/F/prism/api/v3/index.json as a package source to either Visual Studio or Visual Studio for Mac. 33 | 34 | These are the base packages for each platform, together with the Prism's Core assembly as a cross-platform PCL. 35 | 36 | | Platform | Assembly | Package | NuGet | 37 | | ----------- | ----------- | ---------- | ---------- | 38 | | PCL | Prism.dll | [Prism.Core][CoreNuGet] | [![CoreNuGetShield]][CoreNuGet] | [![CoreMyGetShield]][CoreMyGet] | 39 | | WPF | Prism.Wpf.dll | [Prism.Wpf][WpfNuGet] | [![WpfNuGetShield]][WpfNuGet] | 40 | | DryIoc | Prism.DryIoc.dll | [Prism.DryIoc][DryIocWpfNuGet] | [![DryIocWpfNuGetShield]][DryIocWpfNuGet] | 41 | 42 | ## Xaml Islands 43 | There are two new system APIs called [WindowsXamlManager](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.hosting.windowsxamlmanager) and [DesktopWindowXamlSource](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.hosting.desktopwindowxamlsource). 44 | 45 | The WindowsXamlManager handles the UWP XAML Framework itself, which initializes the UWP XAML Framework inside the current thread of this non-UWP Win32 Desktop app, allowing it to create UWP UI in it. 46 | 47 | The DesktopWindowXamlSource is the actual instance of your Island content. This class also enables the developer to get and set the focus of that element. 48 | 49 | | NuGet | Description | 50 | | ------------------------------------- | ------------------------------------------------------------------------- | 51 | | [Microsoft.Toolkit.Wpf.UI.XamlHost](https://www.nuget.org/packages/Microsoft.Toolkit.Wpf.UI.XamlHost/) | This library provides XAML islands helpers for WPF. It is part of the Windows Community Toolkit. 52 | |[Microsoft.Toolkit.Wpf.UI.Controls](https://www.nuget.org/packages/Microsoft.Toolkit.Wpf.UI.Controls/) | Wrapper classes for 1st party controls, InkCanvas, InkToolbar, MapControl, MediaPlayerElement, all for WPF. | 53 | 54 | # Contributing 55 | 56 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 57 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 58 | the rights to use your contribution. For details, visit https://cla.microsoft.com. 59 | 60 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide 61 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions 62 | provided by the bot. You will only need to do this once across all repos using our CLA. 63 | 64 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 65 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 66 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 67 | 68 | 69 | [CoreNuGet]: https://www.nuget.org/packages/Prism.Core/ 70 | [WpfNuGet]: https://www.nuget.org/packages/Prism.Wpf/ 71 | [CoreNuGetShield]: https://img.shields.io/nuget/vpre/Prism.Core.svg 72 | [WpfNuGetShield]: https://img.shields.io/nuget/vpre/Prism.Wpf.svg 73 | [DryIocWpfNuGetShield]: https://img.shields.io/nuget/vpre/Prism.DryIoc.svg 74 | [CoreMyGetShield]: https://img.shields.io/myget/prism/vpre/Prism.Core.svg 75 | [DryIocWpfMyGetShield]: https://img.shields.io/myget/prism/vpre/Prism.DryIoc.svg 76 | [DryIocWpfNuGet]: https://www.nuget.org/packages/Prism.DryIoc/ 77 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /Source/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome:http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Don't use tabs for indentation. 7 | [*] 8 | indent_style = space 9 | # (Please don't specify an indent_size here; that has too many unintended consequences.) 10 | 11 | # Code files 12 | [*.{cs,csx,vb,vbx}] 13 | indent_size = 4 14 | 15 | # Xml project files 16 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] 17 | indent_size = 2 18 | 19 | # Xml config files 20 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] 21 | indent_size = 2 22 | 23 | # JSON files 24 | [*.json] 25 | indent_size = 2 26 | 27 | # Dotnet code style settings: 28 | [*.{cs,vb}] 29 | # Sort using and Import directives with System.* appearing first 30 | dotnet_sort_system_directives_first = true 31 | # Avoid "this." and "Me." if not necessary 32 | dotnet_style_qualification_for_field = false:suggestion 33 | dotnet_style_qualification_for_property = false:suggestion 34 | dotnet_style_qualification_for_method = false:suggestion 35 | dotnet_style_qualification_for_event = false:suggestion 36 | 37 | # Use language keywords instead of framework type names for type references 38 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 39 | dotnet_style_predefined_type_for_member_access = true:suggestion 40 | 41 | # Suggest more modern language features when available 42 | dotnet_style_object_initializer = true:suggestion 43 | dotnet_style_collection_initializer = true:suggestion 44 | dotnet_style_coalesce_expression = true:suggestion 45 | dotnet_style_null_propagation = true:suggestion 46 | dotnet_style_explicit_tuple_names = true:suggestion 47 | 48 | # CSharp code style settings: 49 | [*.cs] 50 | # Prefer "var" everywhere 51 | csharp_style_var_for_built_in_types = true:suggestion 52 | csharp_style_var_when_type_is_apparent = true:suggestion 53 | csharp_style_var_elsewhere = true:suggestion 54 | 55 | # Prefer method-like constructs to have a block body 56 | csharp_style_expression_bodied_methods = false:none 57 | csharp_style_expression_bodied_constructors = false:none 58 | csharp_style_expression_bodied_operators = false:none 59 | 60 | # Prefer property-like constructs to have an expression-body 61 | csharp_style_expression_bodied_properties = true:none 62 | csharp_style_expression_bodied_indexers = true:none 63 | csharp_style_expression_bodied_accessors = true:none 64 | 65 | # Suggest more modern language features when available 66 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 67 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 68 | csharp_style_inlined_variable_declaration = true:suggestion 69 | csharp_style_throw_expression = true:suggestion 70 | csharp_style_conditional_delegate_call = true:suggestion 71 | 72 | # Newline settings 73 | csharp_new_line_before_open_brace = all 74 | csharp_new_line_before_else = true 75 | csharp_new_line_before_catch = true 76 | csharp_new_line_before_finally = true 77 | csharp_new_line_before_members_in_object_initializers = true 78 | csharp_new_line_before_members_in_anonymous_types = true 79 | -------------------------------------------------------------------------------- /Source/CouponReader.Common/Controls/CouponDetailsControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using CouponReader.Common.Helpers; 6 | using CouponReader.Common.Services; 7 | using CouponReader.Common.ViewModels; 8 | using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; 9 | using Microsoft.Toolkit.Wpf.UI.Controls; 10 | 11 | namespace CouponReader.Common.Controls 12 | { 13 | public partial class CouponDetailsControl : UserControl 14 | { 15 | public CouponDetailsControl() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | public void Init() 21 | { 22 | ShowSignBoard(false); 23 | 24 | var toolbar = new InkToolbar(); 25 | InkToolbarContainer.Content = toolbar; 26 | 27 | var canvas = new Microsoft.Toolkit.Wpf.UI.Controls.InkCanvas(); 28 | canvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch | CoreInputDeviceTypes.Pen; 29 | InkCanvasContainer.Content = canvas; 30 | 31 | MapControlContainer.Content = MapControlHelper.Initialize(); 32 | } 33 | 34 | private void OnShowSignatureBoardClick(object sender, RoutedEventArgs e) 35 | { 36 | ShowSignBoard(true); 37 | } 38 | 39 | private void OnRedeemClick(object sender, RoutedEventArgs e) 40 | { 41 | try 42 | { 43 | var coupon = (CouponViewModel)DataContext; 44 | 45 | CouponsService.Instance.RedeemedCoupon(coupon.Coupon.Code); 46 | 47 | MessageBox.Show("Coupon redeemed"); 48 | } 49 | catch(Exception ex) 50 | { 51 | Debug.WriteLine(ex.Message); 52 | } 53 | } 54 | 55 | private void ShowSignBoard(bool show) 56 | { 57 | SignControl.Visibility = show ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/Controls/CouponsHistoryControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Media; 4 | 5 | namespace CouponReader.Common.Controls 6 | { 7 | public partial class CouponsHistoryControl : UserControl 8 | { 9 | public CouponsHistoryControl() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | private void OnRowHeaderToggleButtonClick(object sender, RoutedEventArgs e) 15 | { 16 | var obj = (DependencyObject)e.OriginalSource; 17 | 18 | while (!(obj is DataGridRow) && obj != null) 19 | obj = VisualTreeHelper.GetParent(obj); 20 | 21 | if (obj is DataGridRow) 22 | { 23 | if ((obj as DataGridRow).DetailsVisibility == Visibility.Visible) 24 | { 25 | (obj as DataGridRow).IsSelected = false; 26 | } 27 | else 28 | { 29 | (obj as DataGridRow).IsSelected = true; 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/Converters/BoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace CouponReader.Common.Converters 7 | { 8 | public class BoolToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (value is bool boolVal) 13 | { 14 | if (boolVal) 15 | { 16 | return Visibility.Visible; 17 | } 18 | } 19 | 20 | return Visibility.Collapsed; 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | return null; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/Converters/InverseBoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace CouponReader.Common.Converters 7 | { 8 | public class InverseBoolToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (value is bool boolVal) 13 | { 14 | if (boolVal) 15 | { 16 | return Visibility.Collapsed; 17 | } 18 | } 19 | 20 | return Visibility.Visible; 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | return null; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/CouponReader.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {612C0CBE-0BAA-4662-859C-DD6CC9A59498} 8 | Library 9 | Properties 10 | CouponReader.Common 11 | CouponReader.Common 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | CouponDetailsControl.xaml 56 | 57 | 58 | CouponsHistoryControl.xaml 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | MSBuild:Compile 73 | 74 | 75 | MSBuild:Compile 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 5.1.0-build.14.g97c3f5c88d 84 | 85 | 86 | 5.1.0-build.14.g97c3f5c88d 87 | 88 | 89 | 7.2.0.904-ci 90 | 91 | 92 | 7.2.0.904-ci 93 | 94 | 95 | 4.6.0-preview.19073.11 96 | 97 | 98 | 4.6.0-preview.19073.11 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Source/CouponReader.Common/Helpers/MapControlHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; 4 | using Microsoft.Toolkit.Wpf.UI.Controls; 5 | 6 | namespace CouponReader.Common.Helpers 7 | { 8 | internal static class MapControlHelper 9 | { 10 | private static readonly TimeSpan timeSimulatingGeolocation = TimeSpan.FromSeconds(1); 11 | 12 | public static MapControl Initialize() 13 | { 14 | var mapControl = new MapControl 15 | { 16 | BusinessLandmarksVisible = true, 17 | TransitFeaturesVisible = true, 18 | TrafficFlowVisible = true, 19 | PedestrianFeaturesVisible = true, 20 | MapServiceToken = Settings.BingMapsKey, 21 | LandmarksVisible = true 22 | }; 23 | 24 | var geoposition = new BasicGeoposition 25 | { 26 | Latitude = Settings.DeviceLatitude, 27 | Longitude = Settings.DeviceLongitude 28 | }; 29 | 30 | var point = new Geopoint(geoposition); 31 | 32 | Task.Delay(timeSimulatingGeolocation) 33 | .ContinueWith(_ => mapControl.TrySetViewAsync(point, 16)); 34 | 35 | return mapControl; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/Models/Coupon.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CouponReader.Common.Models 4 | { 5 | public class Coupon 6 | { 7 | public int Id { get; set; } 8 | 9 | public string Code { get; set; } 10 | 11 | public Guid ExternalId { get; set; } 12 | 13 | public string User { get; set; } 14 | 15 | public string UserName { get; set; } 16 | 17 | public DateTime Expiration { get; set; } 18 | 19 | public string ImageUrl { get; set; } 20 | 21 | public string CouponText { get; set; } 22 | 23 | public bool Redeemed { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/Models/CouponHistory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CouponReader.Common.Models 4 | { 5 | public class CouponHistory 6 | { 7 | public DateTime Date { get; set; } 8 | public Coupon Coupon { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CouponReader.Common")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CouponReader.Common")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("612c0cbe-0baa-4662-859c-dd6cc9a59498")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Source/CouponReader.Common/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace CouponReader.Common 2 | { 3 | internal static class Settings 4 | { 5 | // https://docs.microsoft.com/windows/uwp/maps-and-location/authentication-key 6 | public static string BingMapsKey { get; } = "tVLwXNfKxnth4f6zPBfq~mdsO86fJ-DuaAuw28FlUYA~ArBvDRqid9B6D8ELALBRgpRWHTE0HmTLms2nQ4pg6Hk-KB31vWlKonEfFY5XRvQP"; 7 | 8 | public static double DeviceLatitude { get; } = 47.640f; 9 | 10 | public static double DeviceLongitude { get; } = -122.132f; 11 | } 12 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/ViewModels/CouponViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using CouponReader.Common.Models; 4 | using CouponReader.Common.Services; 5 | using Prism.Mvvm; 6 | 7 | namespace CouponReader.Common.ViewModels 8 | { 9 | public class CouponViewModel : BindableBase 10 | { 11 | bool expired; 12 | 13 | public string Title { get; set; } 14 | public string Username { get; set; } 15 | public string User { get; set; } 16 | public string CouponImage { get; set; } 17 | public string CouponText { get; set; } 18 | public string Expiration { get; set; } 19 | public bool ReadyToRedeem { get; set; } 20 | 21 | public bool Expired 22 | { 23 | get { return expired; } 24 | set { SetProperty(ref expired, value); } 25 | } 26 | 27 | public Coupon Coupon { get; set; } 28 | 29 | public List CouponHistory 30 | { 31 | get { return CouponsService.Instance.CouponHistory; } 32 | } 33 | 34 | public CouponViewModel(Coupon coupon) 35 | { 36 | this.Coupon = coupon; 37 | 38 | if (coupon != null) 39 | { 40 | Title = coupon.CouponText; 41 | Username = coupon.UserName; 42 | User = coupon.User; 43 | CouponImage = coupon.ImageUrl; 44 | CouponText = coupon.CouponText; 45 | ReadyToRedeem = !coupon.Redeemed; 46 | Expiration = coupon.Expiration.ToLongDateString(); 47 | 48 | Expired = coupon.Expiration < DateTime.Now; 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Source/CouponReader.Common/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Source/CouponReader.Common/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Controls/CouponDetailsControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using CouponReader.Common.Helpers; 6 | using CouponReader.Common.Services; 7 | using CouponReader.Common.ViewModels; 8 | using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; 9 | using Microsoft.Toolkit.Wpf.UI.Controls; 10 | 11 | namespace CouponReader.Common.Controls 12 | { 13 | public partial class CouponDetailsControl : UserControl 14 | { 15 | public CouponDetailsControl() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | public void Init() 21 | { 22 | ShowSignBoard(false); 23 | 24 | var toolbar = new InkToolbar(); 25 | InkToolbarContainer.Content = toolbar; 26 | 27 | var canvas = new Microsoft.Toolkit.Wpf.UI.Controls.InkCanvas(); 28 | canvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch | CoreInputDeviceTypes.Pen; 29 | InkCanvasContainer.Content = canvas; 30 | 31 | MapControlContainer.Content = MapControlHelper.Initialize(); 32 | } 33 | 34 | private void OnShowSignatureBoardClick(object sender, RoutedEventArgs e) 35 | { 36 | ShowSignBoard(true); 37 | } 38 | 39 | private void OnRedeemClick(object sender, RoutedEventArgs e) 40 | { 41 | try 42 | { 43 | var coupon = (CouponViewModel)DataContext; 44 | 45 | CouponsService.Instance.RedeemedCoupon(coupon.Coupon.Code); 46 | 47 | MessageBox.Show("Coupon redeemed"); 48 | } 49 | catch(Exception ex) 50 | { 51 | Debug.WriteLine(ex.Message); 52 | } 53 | } 54 | 55 | private void ShowSignBoard(bool show) 56 | { 57 | SignControl.Visibility = show ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Controls/CouponsHistoryControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Media; 4 | 5 | namespace CouponReader.Common.Controls 6 | { 7 | public partial class CouponsHistoryControl : UserControl 8 | { 9 | public CouponsHistoryControl() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | private void OnRowHeaderToggleButtonClick(object sender, RoutedEventArgs e) 15 | { 16 | var obj = (DependencyObject)e.OriginalSource; 17 | 18 | while (!(obj is DataGridRow) && obj != null) 19 | obj = VisualTreeHelper.GetParent(obj); 20 | 21 | if (obj is DataGridRow) 22 | { 23 | if ((obj as DataGridRow).DetailsVisibility == Visibility.Visible) 24 | { 25 | (obj as DataGridRow).IsSelected = false; 26 | } 27 | else 28 | { 29 | (obj as DataGridRow).IsSelected = true; 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Converters/BoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace CouponReader.Common.Converters 7 | { 8 | public class BoolToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (value is bool boolVal) 13 | { 14 | if (boolVal) 15 | { 16 | return Visibility.Visible; 17 | } 18 | } 19 | 20 | return Visibility.Collapsed; 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | return null; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Converters/InverseBoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace CouponReader.Common.Converters 7 | { 8 | public class InverseBoolToVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (value is bool boolVal) 13 | { 14 | if (boolVal) 15 | { 16 | return Visibility.Collapsed; 17 | } 18 | } 19 | 20 | return Visibility.Visible; 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | return null; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/CouponReader.Core.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | CouponReader.Common 6 | CouponReader.Common 7 | true 8 | 9 | 10 | 11 | TRACE;DEBUG 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | MSBuild:Compile 22 | 23 | 24 | MSBuild:Compile 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Helpers/MapControlHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT; 4 | using Microsoft.Toolkit.Wpf.UI.Controls; 5 | 6 | namespace CouponReader.Common.Helpers 7 | { 8 | internal static class MapControlHelper 9 | { 10 | private static readonly TimeSpan timeSimulatingGeolocation = TimeSpan.FromSeconds(1); 11 | 12 | public static MapControl Initialize() 13 | { 14 | var mapControl = new MapControl 15 | { 16 | BusinessLandmarksVisible = true, 17 | TransitFeaturesVisible = true, 18 | TrafficFlowVisible = true, 19 | PedestrianFeaturesVisible = true, 20 | MapServiceToken = Settings.BingMapsKey, 21 | LandmarksVisible = true 22 | }; 23 | 24 | var geoposition = new BasicGeoposition 25 | { 26 | Latitude = Settings.DeviceLatitude, 27 | Longitude = Settings.DeviceLongitude 28 | }; 29 | 30 | var point = new Geopoint(geoposition); 31 | 32 | Task.Delay(timeSimulatingGeolocation) 33 | .ContinueWith(_ => mapControl.TrySetViewAsync(point, 16)); 34 | 35 | return mapControl; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Models/Coupon.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CouponReader.Common.Models 4 | { 5 | public class Coupon 6 | { 7 | public int Id { get; set; } 8 | 9 | public string Code { get; set; } 10 | 11 | public Guid ExternalId { get; set; } 12 | 13 | public string User { get; set; } 14 | 15 | public string UserName { get; set; } 16 | 17 | public DateTime Expiration { get; set; } 18 | 19 | public string ImageUrl { get; set; } 20 | 21 | public string CouponText { get; set; } 22 | 23 | public bool Redeemed { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Models/CouponHistory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CouponReader.Common.Models 4 | { 5 | public class CouponHistory 6 | { 7 | public DateTime Date { get; set; } 8 | public Coupon Coupon { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace CouponReader.Common 2 | { 3 | internal static class Settings 4 | { 5 | // https://docs.microsoft.com/windows/uwp/maps-and-location/authentication-key 6 | public static string BingMapsKey { get; } = "USE_YOUR_BING_MAPS_KEY"; 7 | 8 | public static double DeviceLatitude { get; } = 47.640f; 9 | 10 | public static double DeviceLongitude { get; } = -122.132f; 11 | } 12 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Common/ViewModels/CouponViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using CouponReader.Common.Models; 4 | using CouponReader.Common.Services; 5 | using Prism.Mvvm; 6 | 7 | namespace CouponReader.Common.ViewModels 8 | { 9 | public class CouponViewModel : BindableBase 10 | { 11 | bool expired; 12 | 13 | public string Title { get; set; } 14 | public string Username { get; set; } 15 | public string User { get; set; } 16 | public string CouponImage { get; set; } 17 | public string CouponText { get; set; } 18 | public string Expiration { get; set; } 19 | public bool ReadyToRedeem { get; set; } 20 | 21 | public bool Expired 22 | { 23 | get { return expired; } 24 | set { SetProperty(ref expired, value); } 25 | } 26 | 27 | public Coupon Coupon { get; set; } 28 | 29 | public List CouponHistory 30 | { 31 | get { return CouponsService.Instance.CouponHistory; } 32 | } 33 | 34 | public CouponViewModel(Coupon coupon) 35 | { 36 | this.Coupon = coupon; 37 | 38 | if (coupon != null) 39 | { 40 | Title = coupon.CouponText; 41 | Username = coupon.UserName; 42 | User = coupon.User; 43 | CouponImage = coupon.ImageUrl; 44 | CouponText = coupon.CouponText; 45 | ReadyToRedeem = !coupon.Redeemed; 46 | Expiration = coupon.Expiration.ToLongDateString(); 47 | 48 | Expired = coupon.Expiration < DateTime.Now; 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/CouponReader.Core.WindowsForms.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | netcoreapp3.0 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | MainForm.cs 26 | 27 | 28 | 29 | 30 | 31 | MainForm.cs 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Forms; 4 | using CouponReader.Common.Services; 5 | using CouponReader.Common.ViewModels; 6 | 7 | namespace CouponReader 8 | { 9 | public partial class MainForm : Form 10 | { 11 | public MainForm() 12 | { 13 | InitializeComponent(); 14 | 15 | InitButtons(); 16 | 17 | ShowCouponDetails(false); 18 | } 19 | 20 | private void InitButtons() 21 | { 22 | scanButton.Click += new EventHandler(OnScanButtonClick); 23 | clearButton.Click += new EventHandler(OnClearButtonClick); 24 | } 25 | 26 | private void OnScanButtonClick(object sender, EventArgs e) 27 | { 28 | if (string.IsNullOrEmpty(txtInputCode.Text)) 29 | { 30 | return; 31 | } 32 | 33 | var coupon = CouponsService.Instance.FindCouponByCode(txtInputCode.Text); 34 | 35 | if (coupon == null) 36 | { 37 | return; 38 | } 39 | 40 | couponDetails.Init(); 41 | couponDetails.DataContext = new CouponViewModel(coupon); 42 | 43 | ShowCouponDetails(true); 44 | } 45 | 46 | private void OnClearButtonClick(object sender, EventArgs e) 47 | { 48 | txtInputCode.Text = string.Empty; 49 | 50 | ShowCouponDetails(false); 51 | } 52 | 53 | private void OnHistoryButtonClick(object sender, EventArgs e) 54 | { 55 | couponsHistory.Visible = true; 56 | couponsHistoryControl.Visibility = Visibility.Visible; 57 | } 58 | 59 | private void ShowCouponDetails(bool show) 60 | { 61 | couponsHistoryControl.DataContext = new CouponViewModel(null); 62 | couponsHistoryControl.Visibility = Visibility.Collapsed; 63 | couponsHistory.Visible = false; 64 | 65 | couponDetails.Visibility = show ? Visibility.Visible : Visibility.Collapsed; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace CouponReader 5 | { 6 | static class Program 7 | { 8 | [STAThread] 9 | static void Main() 10 | { 11 | Application.EnableVisualStyles(); 12 | Application.SetCompatibleTextRenderingDefault(false); 13 | Application.Run(new MainForm()); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/Coupon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/Coupon.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/ic_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/ic_clear.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/ic_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/ic_error.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/ic_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/ic_history.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/ic_no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/ic_no.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/ic_scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/ic_scan.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/ic_valid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/ic_valid.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/logo_horizontal-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/logo_horizontal-b.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/Resources/Images/logo_vertical-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/Resources/Images/logo_vertical-b.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Forms/tail.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Forms/tail.ico -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | #2F4B66 12 | #F4F6F7 13 | #FFFFFF 14 | #000000 15 | #f4f6f7 16 | #f4f6f7 17 | #f4f6f7 18 | #FF666666 19 | #772F4B66 20 | #992F4B66 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | pack://application:,,,/Resources/Fonts/#Brandon Grotesque Light 43 | pack://application:,,,/Resources/Fonts/#Brandon Grotesque Medium 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using CouponReader.Wpf.CoreModule; 3 | using Prism.Ioc; 4 | using Prism.Modularity; 5 | 6 | namespace CouponReader.Wpf 7 | { 8 | public partial class App 9 | { 10 | protected override Window CreateShell() 11 | { 12 | return Container.Resolve(); 13 | } 14 | 15 | protected override void RegisterTypes(IContainerRegistry containerRegistry) 16 | { 17 | 18 | } 19 | 20 | protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) 21 | { 22 | moduleCatalog.AddModule(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/CouponReader.Core.Wpf.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | netcoreapp3.0 6 | true 7 | tail.ico 8 | app1.manifest 9 | 10 | 11 | 12 | TRACE;EFCORE 13 | 14 | 15 | 16 | TRACE;DEBUG 17 | bin\Debug\ 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | PreserveNewest 35 | 36 | 37 | 38 | 39 | 40 | App.xaml 41 | 42 | 43 | Shell.xaml 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "CouponReader.Core.Wpf": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Fonts/BrandonGrotesque-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Fonts/BrandonGrotesque-Light.otf -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Fonts/BrandonGrotesque-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Fonts/BrandonGrotesque-Medium.otf -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/Coupon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/Coupon.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/ic_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/ic_clear.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/ic_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/ic_error.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/ic_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/ic_history.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/ic_no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/ic_no.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/ic_scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/ic_scan.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/ic_valid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/ic_valid.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/logo_horizontal-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/logo_horizontal-b.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Resources/Images/logo_vertical-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/Resources/Images/logo_vertical-b.png -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Shell.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 16 | 17 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/Shell.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace CouponReader.Wpf 2 | { 3 | public partial class Shell 4 | { 5 | public Shell() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/app1.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Source/CouponReader.Core.Wpf/tail.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Core.Wpf/tail.ico -------------------------------------------------------------------------------- /Source/CouponReader.Forms/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/CouponReader.WindowsForms.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7FAE4C6D-AE2F-4593-8C7B-9329E617EA2C} 8 | WinExe 9 | CouponReader 10 | CouponReader 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | TRACE;DEBUG 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE;DB 33 | prompt 34 | 4 35 | 36 | 37 | tail.ico 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Form 61 | 62 | 63 | MainForm.cs 64 | 65 | 66 | 67 | 68 | MainForm.cs 69 | 70 | 71 | ResXFileCodeGenerator 72 | Resources.Designer.cs 73 | Designer 74 | 75 | 76 | True 77 | Resources.resx 78 | True 79 | 80 | 81 | SettingsSingleFileGenerator 82 | Settings.Designer.cs 83 | 84 | 85 | True 86 | Settings.settings 87 | True 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | {612c0cbe-0baa-4662-859c-dd6cc9a59498} 99 | CouponReader.Common 100 | 101 | 102 | 103 | 104 | 7.2.0.904-ci 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Forms; 4 | using CouponReader.Common.Services; 5 | using CouponReader.Common.ViewModels; 6 | 7 | namespace CouponReader 8 | { 9 | public partial class MainForm : Form 10 | { 11 | public MainForm() 12 | { 13 | InitializeComponent(); 14 | 15 | InitButtons(); 16 | 17 | ShowCouponDetails(false); 18 | } 19 | 20 | private void InitButtons() 21 | { 22 | scanButton.Click += new EventHandler(OnScanButtonClick); 23 | clearButton.Click += new EventHandler(OnClearButtonClick); 24 | } 25 | 26 | private void OnScanButtonClick(object sender, EventArgs e) 27 | { 28 | if (string.IsNullOrEmpty(txtInputCode.Text)) 29 | { 30 | return; 31 | } 32 | 33 | var coupon = CouponsService.Instance.FindCouponByCode(txtInputCode.Text); 34 | 35 | if (coupon == null) 36 | { 37 | return; 38 | } 39 | 40 | couponDetails.Init(); 41 | couponDetails.DataContext = new CouponViewModel(coupon); 42 | 43 | ShowCouponDetails(true); 44 | } 45 | 46 | private void OnClearButtonClick(object sender, EventArgs e) 47 | { 48 | txtInputCode.Text = string.Empty; 49 | 50 | ShowCouponDetails(false); 51 | } 52 | 53 | private void OnHistoryButtonClick(object sender, EventArgs e) 54 | { 55 | couponsHistory.Visible = true; 56 | couponsHistoryControl.Visibility = Visibility.Visible; 57 | } 58 | 59 | private void ShowCouponDetails(bool show) 60 | { 61 | couponsHistoryControl.DataContext = new CouponViewModel(null); 62 | couponsHistoryControl.Visibility = Visibility.Collapsed; 63 | couponsHistory.Visible = false; 64 | 65 | couponDetails.Visibility = show ? Visibility.Visible : Visibility.Collapsed; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Source/CouponReader.Forms/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace CouponReader 5 | { 6 | static class Program 7 | { 8 | [STAThread] 9 | static void Main() 10 | { 11 | Application.EnableVisualStyles(); 12 | Application.SetCompatibleTextRenderingDefault(false); 13 | Application.Run(new MainForm()); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Source/CouponReader.Forms/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CouponReader")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CouponReader")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("7fae4c6d-ae2f-4593-8c7b-9329e617ea2c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CouponReader.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CouponReader.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CouponReader.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Source/CouponReader.Forms/tail.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/TailwindTraders-Desktop/41e4d4f27f5001ce6ae461789d61e68668c345e3/Source/CouponReader.Forms/tail.ico -------------------------------------------------------------------------------- /Source/CouponReader.NETCore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28218.60 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Core.Common", "CouponReader.Core.Common\CouponReader.Core.Common.csproj", "{9F3D84C1-E358-438F-819C-C2A3AFD41030}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Launcher", "Launcher", "{DD125513-DF42-4DD4-9C07-036876AE7B24}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Core.Wpf", "CouponReader.Core.Wpf\CouponReader.Core.Wpf.csproj", "{D2E413E8-2EFB-40A2-A511-46935407CDB3}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Core.WindowsForms", "CouponReader.Core.Forms\CouponReader.Core.WindowsForms.csproj", "{3262A04F-5890-426D-93BE-28AEF9C097CA}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Wpf.Core.Module", "CouponReader.Wpf.Core.Module\CouponReader.Wpf.Core.Module.csproj", "{4C23E5D4-2249-4962-BF27-50370147BB65}" 15 | EndProject 16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{5CF01A23-DBCD-47EF-B6AC-F40205850600}" 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DB738021-55D5-4008-96D7-0A0ADA0D557F}" 19 | ProjectSection(SolutionItems) = preProject 20 | Directory.Build.props = Directory.Build.props 21 | NuGet.config = NuGet.config 22 | EndProjectSection 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{761D5854-6F19-4097-B0A9-B66F2CB26F45}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouponReader.Tests", "CouponReader.Tests\CouponReader.Tests.csproj", "{F0088704-5DB1-493C-A50C-0E180C4718D0}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {3262A04F-5890-426D-93BE-28AEF9C097CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {3262A04F-5890-426D-93BE-28AEF9C097CA}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {3262A04F-5890-426D-93BE-28AEF9C097CA}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {3262A04F-5890-426D-93BE-28AEF9C097CA}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(NestedProjects) = preSolution 59 | {9F3D84C1-E358-438F-819C-C2A3AFD41030} = {5CF01A23-DBCD-47EF-B6AC-F40205850600} 60 | {D2E413E8-2EFB-40A2-A511-46935407CDB3} = {DD125513-DF42-4DD4-9C07-036876AE7B24} 61 | {3262A04F-5890-426D-93BE-28AEF9C097CA} = {DD125513-DF42-4DD4-9C07-036876AE7B24} 62 | {4C23E5D4-2249-4962-BF27-50370147BB65} = {DD125513-DF42-4DD4-9C07-036876AE7B24} 63 | {F0088704-5DB1-493C-A50C-0E180C4718D0} = {761D5854-6F19-4097-B0A9-B66F2CB26F45} 64 | EndGlobalSection 65 | GlobalSection(ExtensibilityGlobals) = postSolution 66 | SolutionGuid = {264B945D-0967-4D4D-B7F5-C5A8650582D0} 67 | EndGlobalSection 68 | EndGlobal 69 | -------------------------------------------------------------------------------- /Source/CouponReader.NETFramework.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28218.60 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Launcher", "Launcher", "{DD125513-DF42-4DD4-9C07-036876AE7B24}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouponReader.Wpf", "CouponReader.Wpf\CouponReader.Wpf.csproj", "{E74C03F0-E840-4C64-A46A-07B0AF9B3B7F}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouponReader.Wpf.Module", "CouponReader.Wpf.Module\CouponReader.Wpf.Module.csproj", "{222C532F-7DDA-406E-A209-CB18AA5FF8A2}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouponReader.WindowsForms", "CouponReader.Forms\CouponReader.WindowsForms.csproj", "{7FAE4C6D-AE2F-4593-8C7B-9329E617EA2C}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{5CF01A23-DBCD-47EF-B6AC-F40205850600}" 15 | EndProject 16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DB738021-55D5-4008-96D7-0A0ADA0D557F}" 17 | ProjectSection(SolutionItems) = preProject 18 | Directory.Build.props = Directory.Build.props 19 | NuGet.config = NuGet.config 20 | EndProjectSection 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouponReader.Common", "CouponReader.Common\CouponReader.Common.csproj", "{612C0CBE-0BAA-4662-859C-DD6CC9A59498}" 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{359AA11D-2D09-4E7F-B658-DB22D599D8D2}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouponReader.Tests", "CouponReader.Tests\CouponReader.Tests.csproj", "{F0088704-5DB1-493C-A50C-0E180C4718D0}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {E74C03F0-E840-4C64-A46A-07B0AF9B3B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {E74C03F0-E840-4C64-A46A-07B0AF9B3B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {E74C03F0-E840-4C64-A46A-07B0AF9B3B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {E74C03F0-E840-4C64-A46A-07B0AF9B3B7F}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {222C532F-7DDA-406E-A209-CB18AA5FF8A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {222C532F-7DDA-406E-A209-CB18AA5FF8A2}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {222C532F-7DDA-406E-A209-CB18AA5FF8A2}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {222C532F-7DDA-406E-A209-CB18AA5FF8A2}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {7FAE4C6D-AE2F-4593-8C7B-9329E617EA2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {7FAE4C6D-AE2F-4593-8C7B-9329E617EA2C}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {7FAE4C6D-AE2F-4593-8C7B-9329E617EA2C}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {7FAE4C6D-AE2F-4593-8C7B-9329E617EA2C}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {612C0CBE-0BAA-4662-859C-DD6CC9A59498}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {612C0CBE-0BAA-4662-859C-DD6CC9A59498}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {612C0CBE-0BAA-4662-859C-DD6CC9A59498}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {612C0CBE-0BAA-4662-859C-DD6CC9A59498}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {F0088704-5DB1-493C-A50C-0E180C4718D0}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(NestedProjects) = preSolution 59 | {E74C03F0-E840-4C64-A46A-07B0AF9B3B7F} = {DD125513-DF42-4DD4-9C07-036876AE7B24} 60 | {222C532F-7DDA-406E-A209-CB18AA5FF8A2} = {DD125513-DF42-4DD4-9C07-036876AE7B24} 61 | {7FAE4C6D-AE2F-4593-8C7B-9329E617EA2C} = {DD125513-DF42-4DD4-9C07-036876AE7B24} 62 | {612C0CBE-0BAA-4662-859C-DD6CC9A59498} = {5CF01A23-DBCD-47EF-B6AC-F40205850600} 63 | {F0088704-5DB1-493C-A50C-0E180C4718D0} = {359AA11D-2D09-4E7F-B658-DB22D599D8D2} 64 | EndGlobalSection 65 | GlobalSection(ExtensibilityGlobals) = postSolution 66 | SolutionGuid = {264B945D-0967-4D4D-B7F5-C5A8650582D0} 67 | EndGlobalSection 68 | EndGlobal 69 | -------------------------------------------------------------------------------- /Source/CouponReader.Tests/CouponReader.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {F0088704-5DB1-493C-A50C-0E180C4718D0} 9 | Library 10 | Properties 11 | CouponReader.Tests 12 | CouponReader.Tests 13 | v4.7.2 14 | 512 15 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 16 | 15.0 17 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 18 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 19 | False 20 | UnitTest 21 | 22 | 23 | 24 | 25 | true 26 | full 27 | false 28 | bin\Debug\ 29 | DEBUG;TRACE 30 | prompt 31 | 4 32 | 33 | 34 | pdbonly 35 | true 36 | bin\Release\ 37 | TRACE 38 | prompt 39 | 4 40 | 41 | 42 | 43 | ..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll 44 | 45 | 46 | ..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {612c0cbe-0baa-4662-859c-dd6cc9a59498} 58 | CouponReader.Common 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Source/CouponReader.Tests/CouponsServiceTests.cs: -------------------------------------------------------------------------------- 1 | using CouponReader.Common.Services; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace CouponReader.Tests 5 | { 6 | [TestClass] 7 | public class CouponsServiceTests 8 | { 9 | [TestMethod] 10 | public void GetCouponsTest() 11 | { 12 | var coupons = CouponsService.Instance.Coupons; 13 | 14 | Assert.AreNotEqual(coupons.Count, 0); 15 | } 16 | 17 | [TestMethod] 18 | public void GetCouponHistoryTest() 19 | { 20 | var couponHistory = CouponsService.Instance.CouponHistory; 21 | 22 | Assert.AreNotEqual(couponHistory.Count, 0); 23 | } 24 | 25 | [TestMethod] 26 | public void FindCouponByCodeTest() 27 | { 28 | var code = "Code50"; 29 | var coupon = CouponsService.Instance.FindCouponByCode(code); 30 | 31 | Assert.IsNotNull(coupon); 32 | } 33 | 34 | [TestMethod] 35 | public void RedeemedCouponTest() 36 | { 37 | var code = "Code10"; 38 | var coupon = CouponsService.Instance.FindCouponByCode(code); 39 | 40 | Assert.IsNotNull(coupon); 41 | Assert.AreEqual(coupon.Redeemed, false); 42 | 43 | CouponsService.Instance.RedeemedCoupon(code); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Source/CouponReader.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("CouponReader.Tests")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("CouponReader.Tests")] 10 | [assembly: AssemblyCopyright("Copyright © 2018")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("f0088704-5db1-493c-a50c-0e180c4718d0")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /Source/CouponReader.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Source/CouponReader.UnitTests/CouponReader.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Source/CouponReader.UnitTests/CouponsServiceTests.cs: -------------------------------------------------------------------------------- 1 | using CouponReader.Common.Services; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace CouponReader.UnitTests 5 | { 6 | [TestClass] 7 | public class CouponsServiceTests 8 | { 9 | [TestMethod] 10 | public void GetCouponsTest() 11 | { 12 | var coupons = CouponsService.Instance.Coupons; 13 | 14 | Assert.AreNotEqual(coupons.Count, 0); 15 | } 16 | 17 | [TestMethod] 18 | public void GetCouponHistoryTest() 19 | { 20 | var couponHistory = CouponsService.Instance.CouponHistory; 21 | 22 | Assert.AreNotEqual(couponHistory.Count, 0); 23 | } 24 | 25 | [TestMethod] 26 | public void FindCouponByCodeTest() 27 | { 28 | var code = "Code50"; 29 | var coupon = CouponsService.Instance.FindCouponByCode(code); 30 | 31 | Assert.IsNotNull(coupon); 32 | } 33 | 34 | [TestMethod] 35 | public void RedeemedCouponTest() 36 | { 37 | var code = "Code10"; 38 | var coupon = CouponsService.Instance.FindCouponByCode(code); 39 | 40 | Assert.IsNotNull(coupon); 41 | Assert.AreEqual(coupon.Redeemed, false); 42 | 43 | CouponsService.Instance.RedeemedCoupon(code); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Source/CouponReader.WPF.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.106 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Core.Common", "CouponReader.Core.Common\CouponReader.Core.Common.csproj", "{9F3D84C1-E358-438F-819C-C2A3AFD41030}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Core.Wpf", "CouponReader.Core.Wpf\CouponReader.Core.Wpf.csproj", "{D2E413E8-2EFB-40A2-A511-46935407CDB3}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Wpf.Core.Module", "CouponReader.Wpf.Core.Module\CouponReader.Wpf.Core.Module.csproj", "{4C23E5D4-2249-4962-BF27-50370147BB65}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{5CF01A23-DBCD-47EF-B6AC-F40205850600}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DB738021-55D5-4008-96D7-0A0ADA0D557F}" 15 | ProjectSection(SolutionItems) = preProject 16 | Directory.Build.props = Directory.Build.props 17 | NuGet.config = NuGet.config 18 | EndProjectSection 19 | EndProject 20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{761D5854-6F19-4097-B0A9-B66F2CB26F45}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.UnitTests", "CouponReader.UnitTests\CouponReader.UnitTests.csproj", "{A7A1EFEF-9AD8-44A6-BE0F-EEC4877C9B02}" 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Designers", "Designers", "{5C02CFB2-47F8-4FA9-A017-2B5C4AB472EE}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPFNetFX", "WPFNetFX\WPFNetFX.csproj", "{F8FCBE59-4D67-40F6-894F-A49F69ED954A}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {D2E413E8-2EFB-40A2-A511-46935407CDB3}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {4C23E5D4-2249-4962-BF27-50370147BB65}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {A7A1EFEF-9AD8-44A6-BE0F-EEC4877C9B02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {A7A1EFEF-9AD8-44A6-BE0F-EEC4877C9B02}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {A7A1EFEF-9AD8-44A6-BE0F-EEC4877C9B02}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {A7A1EFEF-9AD8-44A6-BE0F-EEC4877C9B02}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {F8FCBE59-4D67-40F6-894F-A49F69ED954A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {F8FCBE59-4D67-40F6-894F-A49F69ED954A}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {F8FCBE59-4D67-40F6-894F-A49F69ED954A}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {F8FCBE59-4D67-40F6-894F-A49F69ED954A}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(NestedProjects) = preSolution 59 | {9F3D84C1-E358-438F-819C-C2A3AFD41030} = {5CF01A23-DBCD-47EF-B6AC-F40205850600} 60 | {4C23E5D4-2249-4962-BF27-50370147BB65} = {5CF01A23-DBCD-47EF-B6AC-F40205850600} 61 | {A7A1EFEF-9AD8-44A6-BE0F-EEC4877C9B02} = {761D5854-6F19-4097-B0A9-B66F2CB26F45} 62 | {F8FCBE59-4D67-40F6-894F-A49F69ED954A} = {5C02CFB2-47F8-4FA9-A017-2B5C4AB472EE} 63 | EndGlobalSection 64 | GlobalSection(ExtensibilityGlobals) = postSolution 65 | SolutionGuid = {264B945D-0967-4D4D-B7F5-C5A8650582D0} 66 | EndGlobalSection 67 | EndGlobal 68 | -------------------------------------------------------------------------------- /Source/CouponReader.WinForms.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28315.86 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Core.Common", "CouponReader.Core.Common\CouponReader.Core.Common.csproj", "{9F3D84C1-E358-438F-819C-C2A3AFD41030}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{5CF01A23-DBCD-47EF-B6AC-F40205850600}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DB738021-55D5-4008-96D7-0A0ADA0D557F}" 11 | ProjectSection(SolutionItems) = preProject 12 | Directory.Build.props = Directory.Build.props 13 | NuGet.config = NuGet.config 14 | EndProjectSection 15 | EndProject 16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{761D5854-6F19-4097-B0A9-B66F2CB26F45}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.UnitTests", "CouponReader.UnitTests\CouponReader.UnitTests.csproj", "{BC39A56C-073D-49A2-9B4F-8F098A27AA60}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CouponReader.Core.WindowsForms", "CouponReader.Core.Forms\CouponReader.Core.WindowsForms.csproj", "{AF913F73-55C3-413E-A927-75D32B79BCE7}" 21 | EndProject 22 | Global 23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 24 | Debug|Any CPU = Debug|Any CPU 25 | Release|Any CPU = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {9F3D84C1-E358-438F-819C-C2A3AFD41030}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {BC39A56C-073D-49A2-9B4F-8F098A27AA60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {BC39A56C-073D-49A2-9B4F-8F098A27AA60}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {BC39A56C-073D-49A2-9B4F-8F098A27AA60}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {BC39A56C-073D-49A2-9B4F-8F098A27AA60}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {AF913F73-55C3-413E-A927-75D32B79BCE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {AF913F73-55C3-413E-A927-75D32B79BCE7}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {AF913F73-55C3-413E-A927-75D32B79BCE7}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {AF913F73-55C3-413E-A927-75D32B79BCE7}.Release|Any CPU.Build.0 = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(SolutionProperties) = preSolution 42 | HideSolutionNode = FALSE 43 | EndGlobalSection 44 | GlobalSection(NestedProjects) = preSolution 45 | {9F3D84C1-E358-438F-819C-C2A3AFD41030} = {5CF01A23-DBCD-47EF-B6AC-F40205850600} 46 | {BC39A56C-073D-49A2-9B4F-8F098A27AA60} = {761D5854-6F19-4097-B0A9-B66F2CB26F45} 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {264B945D-0967-4D4D-B7F5-C5A8650582D0} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /Source/CouponReader.Wpf.Core.Module/CouponReader.Wpf.Core.Module.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | CouponReader.Wpf.Module 6 | CouponReader.Wpf.Module 7 | true 8 | 9 | 10 | 11 | TRACE;DEBUG 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd 25 | true 26 | false 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | MSBuild:Compile 37 | 38 | 39 | MSBuild:Compile 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Source/CouponReader.Wpf.Core.Module/CouponReaderModule.cs: -------------------------------------------------------------------------------- 1 | using CouponReader.Wpf.Module; 2 | using CouponReader.Wpf.Module.Services; 3 | using CouponReader.Wpf.Module.Views; 4 | using Prism.Ioc; 5 | using Prism.Modularity; 6 | using Prism.Regions; 7 | 8 | namespace CouponReader.Wpf.CoreModule 9 | { 10 | public class CouponReaderModule : IModule 11 | { 12 | public void OnInitialized(IContainerProvider containerProvider) 13 | { 14 | var regionManager = containerProvider.Resolve(); 15 | regionManager.RequestNavigate(RegionNames.ContentRegion, "LoginView"); 16 | } 17 | 18 | public void RegisterTypes(IContainerRegistry containerRegistry) 19 | { 20 | containerRegistry.RegisterForNavigation(); 21 | containerRegistry.RegisterForNavigation(); 22 | 23 | containerRegistry.Register(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Source/CouponReader.Wpf.Core.Module/RegionNames.cs: -------------------------------------------------------------------------------- 1 | namespace CouponReader.Wpf.Module 2 | { 3 | public class RegionNames 4 | { 5 | public static string ContentRegion = "ContentRegion"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Source/CouponReader.Wpf.Core.Module/Services/LoginService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace CouponReader.Wpf.Module.Services 4 | { 5 | public class LoginService 6 | { 7 | public async Task SignInAsync() 8 | { 9 | await Task.Delay(500); 10 | 11 | return true; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Source/CouponReader.Wpf.Core.Module/ViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using CouponReader.Wpf.Module.Services; 4 | using Prism.Commands; 5 | using Prism.Mvvm; 6 | using Prism.Regions; 7 | 8 | namespace CouponReader.Wpf.Module.ViewModels 9 | { 10 | public class LoginViewModel : BindableBase, INavigationAware 11 | { 12 | private DelegateCommand _loginCommand; 13 | private string _message; 14 | 15 | IRegionManager _regionManager; 16 | LoginService _loginService; 17 | public LoginViewModel(IRegionManager regionManager, LoginService loginService) 18 | { 19 | _regionManager = regionManager; 20 | _loginService = loginService; 21 | } 22 | 23 | public DelegateCommand LoginCommand => 24 | _loginCommand ?? (_loginCommand = new DelegateCommand(async () => await ExecuteLoginAsync())); 25 | 26 | public string Message 27 | { 28 | get { return _message; } 29 | set { SetProperty(ref _message, value); } 30 | } 31 | 32 | public async Task ExecuteLoginAsync() 33 | { 34 | try 35 | { 36 | var success = await _loginService.SignInAsync(); 37 | 38 | if (success) 39 | { 40 | Message = string.Empty; 41 | 42 | _regionManager.RequestNavigate(RegionNames.ContentRegion, "MainView"); 43 | } 44 | else 45 | { 46 | Message = "The Sign In process could not be completed successfully."; 47 | } 48 | } 49 | catch(Exception ex) 50 | { 51 | Message = ex.Message; 52 | } 53 | } 54 | 55 | public bool IsNavigationTarget(NavigationContext navigationContext) 56 | { 57 | return true; 58 | } 59 | 60 | public void OnNavigatedFrom(NavigationContext navigationContext) 61 | { 62 | 63 | } 64 | 65 | public void OnNavigatedTo(NavigationContext navigationContext) 66 | { 67 | 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /Source/CouponReader.Wpf.Core.Module/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CouponReader.Common.Models; 3 | using CouponReader.Common.Services; 4 | using Prism.Commands; 5 | using Prism.Events; 6 | using Prism.Interactivity.InteractionRequest; 7 | using Prism.Mvvm; 8 | using Prism.Regions; 9 | 10 | namespace CouponReader.Wpf.Module.ViewModels 11 | { 12 | public class MainViewModel : BindableBase, INavigationAware 13 | { 14 | private string _search; 15 | private List _couponHistory; 16 | private bool _isCouponHistory; 17 | private DelegateCommand _scanCommand; 18 | private DelegateCommand _cleanCommand; 19 | private DelegateCommand _historyCommand; 20 | 21 | private IEventAggregator _eventAggregator; 22 | 23 | public MainViewModel(IEventAggregator eventAggregator) 24 | { 25 | _eventAggregator = eventAggregator; 26 | 27 | CouponHistory = new List(); 28 | NotificationRequest = new InteractionRequest(); 29 | } 30 | 31 | public string Search 32 | { 33 | get { return _search; } 34 | set { SetProperty(ref _search, value); } 35 | } 36 | 37 | public bool IsCouponHistory 38 | { 39 | get { return _isCouponHistory; } 40 | set { SetProperty(ref _isCouponHistory, value); } 41 | } 42 | 43 | public List CouponHistory 44 | { 45 | get { return _couponHistory; } 46 | set { SetProperty(ref _couponHistory, value); } 47 | } 48 | 49 | public DelegateCommand ScanCommand => 50 | _scanCommand ?? (_scanCommand = new DelegateCommand(ExecuteScan)); 51 | 52 | public DelegateCommand CleanCommand => 53 | _cleanCommand ?? (_cleanCommand = new DelegateCommand(ExecuteClean)); 54 | 55 | public DelegateCommand HistoryCommand => 56 | _historyCommand ?? (_historyCommand = new DelegateCommand(ExecuteHistory)); 57 | 58 | public InteractionRequest NotificationRequest { get; set; } 59 | 60 | public void OnNavigatedTo(NavigationContext navigationContext) 61 | { 62 | var couponHistory = CouponsService.Instance.CouponHistory; 63 | 64 | foreach(var coupon in couponHistory) 65 | { 66 | CouponHistory.Add(coupon); 67 | } 68 | } 69 | 70 | public bool IsNavigationTarget(NavigationContext navigationContext) 71 | { 72 | return true; 73 | } 74 | 75 | public void OnNavigatedFrom(NavigationContext navigationContext) 76 | { 77 | 78 | } 79 | 80 | private void ExecuteScan() 81 | { 82 | if (string.IsNullOrEmpty(Search)) 83 | { 84 | NotificationRequest.Raise(new Notification { Content = "Enter a valid coupon code", Title = "Invalid Coupon" }, r => r.Title = "Notified"); 85 | return; 86 | } 87 | var coupon = CouponsService.Instance.FindCouponByCode(Search); 88 | 89 | if (coupon == default) 90 | { 91 | return; 92 | } 93 | 94 | // Publish event 95 | _eventAggregator.GetEvent>().Publish(coupon); 96 | } 97 | 98 | private void ExecuteClean() 99 | { 100 | Search = string.Empty; 101 | } 102 | 103 | private void ExecuteHistory() 104 | { 105 | IsCouponHistory = !IsCouponHistory; 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /Source/CouponReader.Wpf.Core.Module/Views/LoginView.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 18 | 19 | 29 | 30 | 60 | 61 | 65 | 66 | 67 | 68 | 70 | 72 | 73 | 74 | 75 | 76 | 77 | 82 |