Repository: teddysmithdev/RunGroop
Branch: master
Commit: 3695f75527d0
Files: 119
Total size: 850.3 KB
Directory structure:
gitextract_r3gp682_/
├── .gitignore
├── README.md
├── RunGroopWebApp/
│ ├── ClaimsPrincipalExtensions.cs
│ ├── Controllers/
│ │ ├── AccountController.cs
│ │ ├── ClubController.cs
│ │ ├── DashboardController.cs
│ │ ├── HomeController.cs
│ │ ├── RaceController.cs
│ │ └── UserController.cs
│ ├── Data/
│ │ ├── ApplicationDbContext.cs
│ │ ├── Enum/
│ │ │ ├── ClubCategory.cs
│ │ │ └── RaceCategory.cs
│ │ ├── Seed.cs
│ │ └── UserRoles.cs
│ ├── Extensions/
│ │ ├── NumberExtensions.cs
│ │ └── StringExtensions.cs
│ ├── Helpers/
│ │ ├── CloudinarySettings.cs
│ │ ├── IPInfo.cs
│ │ ├── Location.cs
│ │ └── StateConverter.cs
│ ├── Interfaces/
│ │ ├── IClubRepository.cs
│ │ ├── IDashboardRepository.cs
│ │ ├── ILocationService.cs
│ │ ├── IPhotoService.cs
│ │ ├── IRaceRepository.cs
│ │ └── IUserRepository.cs
│ ├── Migrations/
│ │ ├── 20220215112438_InitialCreate.Designer.cs
│ │ ├── 20220215112438_InitialCreate.cs
│ │ └── ApplicationDbContextModelSnapshot.cs
│ ├── Models/
│ │ ├── Address.cs
│ │ ├── AppUser.cs
│ │ ├── City.cs
│ │ ├── Club.cs
│ │ ├── ErrorViewModel.cs
│ │ ├── Race.cs
│ │ └── State.cs
│ ├── Program.cs
│ ├── Properties/
│ │ └── launchSettings.json
│ ├── Repository/
│ │ ├── ClubRepository.cs
│ │ ├── DashboardRepository.cs
│ │ ├── RaceRepository.cs
│ │ └── UserRepository.cs
│ ├── RunGroopWebApp.csproj
│ ├── Services/
│ │ ├── LocationService.cs
│ │ └── PhotoService.cs
│ ├── ViewModels/
│ │ ├── CreateClubViewModel.cs
│ │ ├── CreateRaceViewModel.cs
│ │ ├── DashboardViewModel.cs
│ │ ├── EditClubViewModel.cs
│ │ ├── EditProfileViewModel.cs
│ │ ├── EditRaceViewModel.cs
│ │ ├── HomeUserCreateViewModel.cs
│ │ ├── HomeViewModel.cs
│ │ ├── IndexClubViewModel.cs
│ │ ├── IndexRaceViewModel.cs
│ │ ├── ListClubByCityViewModel.cs
│ │ ├── ListClubByStateViewModel.cs
│ │ ├── LoginViewModel.cs
│ │ ├── RegisterViewModel.cs
│ │ ├── RunningClubByCity.cs
│ │ ├── RunningClubByState.cs
│ │ ├── UserDetailViewModel.cs
│ │ ├── UserViewModel.cs
│ │ └── WelcomeViewModel.cs
│ ├── Views/
│ │ ├── Account/
│ │ │ ├── Login.cshtml
│ │ │ ├── Register.cshtml
│ │ │ └── Welcome.cshtml
│ │ ├── Club/
│ │ │ ├── Create.cshtml
│ │ │ ├── Delete.cshtml
│ │ │ ├── DetailClub.cshtml
│ │ │ ├── Edit.cshtml
│ │ │ ├── Index.cshtml
│ │ │ ├── ListClubsByCity.cshtml
│ │ │ ├── ListClubsByState.cshtml
│ │ │ ├── RunningClubsByCityDirectory.cshtml
│ │ │ ├── RunningClubsByStateDirectory.cshtml
│ │ │ └── RunningClubsByStateForCityDirectory.cshtml
│ │ ├── Dashboard/
│ │ │ └── Index.cshtml
│ │ ├── Home/
│ │ │ ├── Index.cshtml
│ │ │ ├── Privacy.cshtml
│ │ │ └── Register.cshtml
│ │ ├── Race/
│ │ │ ├── Create.cshtml
│ │ │ ├── Delete.cshtml
│ │ │ ├── DetailRace.cshtml
│ │ │ ├── Edit.cshtml
│ │ │ └── Index.cshtml
│ │ ├── Shared/
│ │ │ ├── Error.cshtml
│ │ │ ├── _Layout.cshtml
│ │ │ ├── _Layout.cshtml.css
│ │ │ └── _ValidationScriptsPartial.cshtml
│ │ ├── User/
│ │ │ ├── Detail.cshtml
│ │ │ ├── EditProfile.cshtml
│ │ │ └── Index.cshtml
│ │ ├── _ViewImports.cshtml
│ │ └── _ViewStart.cshtml
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ └── wwwroot/
│ ├── css/
│ │ ├── custom.css
│ │ ├── entypo.css
│ │ ├── socicon.css
│ │ └── theme.css
│ └── js/
│ ├── aos.js
│ ├── bootstrap.js
│ ├── custom.js
│ ├── flickity.pkgd.js
│ ├── prism.js
│ ├── scrollMonitor.js
│ └── theme.js
├── RunGroopWebApp.Scraper/
│ ├── Data/
│ │ └── ScraperDBContext.cs
│ ├── Extensions/
│ │ └── DateTimeExtension.cs
│ ├── Interfaces/
│ │ └── IAtraScraper.cs
│ ├── Program.cs
│ ├── RunGroopWebApp.Scraper.csproj
│ └── Services/
│ ├── AtraScraper.cs
│ └── MeetupScraper.cs
├── RunGroopWebApp.Tests/
│ ├── Controller/
│ │ └── ClubControllerTests.cs
│ ├── Repository/
│ │ └── ClubRepositoryTests.cs
│ └── RunGroopWebApp.Tests.csproj
└── RunGroopWebApp.sln
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
================================================
FILE: README.md
================================================
# RunGroops
Rungroops is an online platform for runners. This platform will help you to find clubs, schedule events, and meet other runners in your area.

## 🏃 Getting Started
[Youtube video on how to get database setup](https://www.youtube.com/watch?v=af_tK9LUiX0)
1. Go into directory where you plan on keeping project and run.
```bash
git fork https://github.com/teddysmithdev/RunGroop.git
```
2. Create a local database. (If you are unsure how to do this, watch my Youtube video )
3. Add connection string to app settings.json. It will look something like this:
```bash
Data Source=DESKTOP-EI2TOGP\\SQLEXPRESS;Initial Catalog=RunGroops;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False
```
4. Register for a [Cloudinary Account](https://cloudinary.com/users/register/free) (%100 free) and add Cloudname, ApiKey, and Api secret to appsettings.json.
================================================
FILE: RunGroopWebApp/ClaimsPrincipalExtensions.cs
================================================
using System.Security.Claims;
namespace RunGroopWebApp
{
public static class ClaimsPrincipalExtensions
{
public static string GetUserId(this ClaimsPrincipal user)
{
return user.FindFirst(ClaimTypes.NameIdentifier).Value;
}
}
}
================================================
FILE: RunGroopWebApp/Controllers/AccountController.cs
================================================
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using RunGroopWebApp.Data;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
using RunGroopWebApp.ViewModels;
namespace RunGroopWebApp.Controllers
{
public class AccountController : Controller
{
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly ApplicationDbContext _context;
private readonly ILocationService _locationService;
public AccountController(UserManager userManager,
SignInManager signInManager,
ApplicationDbContext context,
ILocationService locationService)
{
_context = context;
_locationService = locationService;
_signInManager = signInManager;
_userManager = userManager;
}
[HttpGet]
public IActionResult Login()
{
var response = new LoginViewModel();
return View(response);
}
[HttpPost]
public async Task Login(LoginViewModel loginViewModel)
{
if (!ModelState.IsValid) return View(loginViewModel);
var user = await _userManager.FindByEmailAsync(loginViewModel.EmailAddress);
if (user != null)
{
//User is found, check password
var passwordCheck = await _userManager.CheckPasswordAsync(user, loginViewModel.Password);
if (passwordCheck)
{
//Password correct, sign in
var result = await _signInManager.PasswordSignInAsync(user, loginViewModel.Password, false, false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Race");
}
}
//Password is incorrect
TempData["Error"] = "Wrong credentials. Please try again";
return View(loginViewModel);
}
//User not found
TempData["Error"] = "Wrong credentials. Please try again";
return View(loginViewModel);
}
[HttpGet]
public IActionResult Register()
{
var response = new RegisterViewModel();
return View(response);
}
[HttpPost]
public async Task Register(RegisterViewModel registerViewModel)
{
if (!ModelState.IsValid) return View(registerViewModel);
var user = await _userManager.FindByEmailAsync(registerViewModel.EmailAddress);
if (user != null)
{
TempData["Error"] = "This email address is already in use";
return View(registerViewModel);
}
var newUser = new AppUser()
{
Email = registerViewModel.EmailAddress,
UserName = registerViewModel.EmailAddress
};
var newUserResponse = await _userManager.CreateAsync(newUser, registerViewModel.Password);
if (newUserResponse.Succeeded)
await _userManager.AddToRoleAsync(newUser, UserRoles.User);
return RedirectToAction("Index", "Race");
}
[HttpGet]
public async Task Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index", "Race");
}
[HttpGet]
[Route("Account/Welcome")]
public async Task Welcome(int page = 0)
{
if(page == 0)
{
return View();
}
return View();
}
[HttpGet]
public async Task GetLocation(string location)
{
if(location == null)
{
return Json("Not found");
}
var locationResult = await _locationService.GetLocationSearch(location);
return Json(locationResult);
}
}
}
================================================
FILE: RunGroopWebApp/Controllers/ClubController.cs
================================================
using Microsoft.AspNetCore.Mvc;
using RunGroopWebApp.Data.Enum;
using RunGroopWebApp.Helpers;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
using RunGroopWebApp.ViewModels;
namespace RunGroopWebApp.Controllers
{
public class ClubController : Controller
{
private readonly IClubRepository _clubRepository;
private readonly IPhotoService _photoService;
public ClubController(IClubRepository clubRepository, IPhotoService photoService)
{
_clubRepository = clubRepository;
_photoService = photoService;
}
[HttpGet]
[Route("RunningClubs")]
public async Task Index(int category = -1, int page = 1, int pageSize = 6)
{
if (page < 1 || pageSize < 1)
{
return NotFound();
}
// if category is -1 (All) dont filter else filter by selected category
var clubs = category switch
{
-1 => await _clubRepository.GetSliceAsync((page - 1) * pageSize, pageSize),
_ => await _clubRepository.GetClubsByCategoryAndSliceAsync((ClubCategory)category, (page - 1) * pageSize, pageSize),
};
var count = category switch
{
-1 => await _clubRepository.GetCountAsync(),
_ => await _clubRepository.GetCountByCategoryAsync((ClubCategory)category),
};
var clubViewModel = new IndexClubViewModel
{
Clubs = clubs,
Page = page,
PageSize = pageSize,
TotalClubs = count,
TotalPages = (int)Math.Ceiling(count / (double)pageSize),
Category = category,
};
return View(clubViewModel);
}
[HttpGet]
[Route("RunningClubs/{state}")]
public async Task ListClubsByState(string state)
{
var clubs = await _clubRepository.GetClubsByState(StateConverter.GetStateByName(state).ToString());
var clubVM = new ListClubByStateViewModel()
{
Clubs = clubs
};
if (clubs.Count() == 0)
{
clubVM.NoClubWarning = true;
}
else
{
clubVM.State = state;
}
return View(clubVM);
}
[HttpGet]
[Route("RunningClubs/{city}/{state}")]
public async Task ListClubsByCity(string city, string state)
{
var clubs = await _clubRepository.GetClubByCity(city);
var clubVM = new ListClubByCityViewModel()
{
Clubs = clubs
};
if (clubs.Count() == 0)
{
clubVM.NoClubWarning = true;
}
else
{
clubVM.State = state;
clubVM.City = city;
}
return View(clubVM);
}
[HttpGet]
[Route("club/{runningClub}/{id}")]
public async Task DetailClub(int id, string runningClub)
{
var club = await _clubRepository.GetByIdAsync(id);
return club == null ? NotFound() : View(club);
}
[HttpGet]
[Route("RunningClubs/State")]
public async Task RunningClubsByStateDirectory()
{
var states = await _clubRepository.GetAllStates();
var clubVM = new RunningClubByState()
{
States = states
};
return states == null ? NotFound() : View(clubVM);
}
[HttpGet]
[Route("RunningClubs/State/City")]
public async Task RunningClubsByStateForCityDirectory()
{
var states = await _clubRepository.GetAllStates();
var clubVM = new RunningClubByState()
{
States = states
};
return states == null ? NotFound() : View(clubVM);
}
[HttpGet]
[Route("RunningClubs/{state}/City")]
public async Task RunningClubsByCityDirectory(string state)
{
var cities = await _clubRepository.GetAllCitiesByState(StateConverter.GetStateByName(state).ToString());
var clubVM = new RunningClubByCity()
{
Cities = cities
};
return cities == null ? NotFound() : View(clubVM);
}
[HttpGet]
public IActionResult Create()
{
var curUserId = HttpContext.User.GetUserId();
var createClubViewModel = new CreateClubViewModel { AppUserId = curUserId };
return View(createClubViewModel);
}
[HttpPost]
public async Task Create(CreateClubViewModel clubVM)
{
if (ModelState.IsValid)
{
var result = await _photoService.AddPhotoAsync(clubVM.Image);
var club = new Club
{
Title = clubVM.Title,
Description = clubVM.Description,
Image = result.Url.ToString(),
ClubCategory = clubVM.ClubCategory,
AppUserId = clubVM.AppUserId,
Address = new Address
{
Street = clubVM.Address.Street,
City = clubVM.Address.City,
State = clubVM.Address.State,
}
};
_clubRepository.Add(club);
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("", "Photo upload failed");
}
return View(clubVM);
}
[HttpGet]
public async Task Edit(int id)
{
var club = await _clubRepository.GetByIdAsync(id);
if (club == null) return View("Error");
var clubVM = new EditClubViewModel
{
Title = club.Title,
Description = club.Description,
AddressId = club.AddressId,
Address = club.Address,
URL = club.Image,
ClubCategory = club.ClubCategory
};
return View(clubVM);
}
[HttpPost]
public async Task Edit(int id, EditClubViewModel clubVM)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError("", "Failed to edit club");
return View("Edit", clubVM);
}
var userClub = await _clubRepository.GetByIdAsyncNoTracking(id);
if (userClub == null)
{
return View("Error");
}
var photoResult = await _photoService.AddPhotoAsync(clubVM.Image);
if (photoResult.Error != null)
{
ModelState.AddModelError("Image", "Photo upload failed");
return View(clubVM);
}
if (!string.IsNullOrEmpty(userClub.Image))
{
_ = _photoService.DeletePhotoAsync(userClub.Image);
}
var club = new Club
{
Id = id,
Title = clubVM.Title,
Description = clubVM.Description,
Image = photoResult.Url.ToString(),
AddressId = clubVM.AddressId,
Address = clubVM.Address,
};
_clubRepository.Update(club);
return RedirectToAction("Index");
}
[HttpGet]
public async Task Delete(int id)
{
var clubDetails = await _clubRepository.GetByIdAsync(id);
if (clubDetails == null) return View("Error");
return View(clubDetails);
}
[HttpPost, ActionName("Delete")]
public async Task DeleteClub(int id)
{
var clubDetails = await _clubRepository.GetByIdAsync(id);
if (clubDetails == null)
{
return View("Error");
}
if (!string.IsNullOrEmpty(clubDetails.Image))
{
_ = _photoService.DeletePhotoAsync(clubDetails.Image);
}
_clubRepository.Delete(clubDetails);
return RedirectToAction("Index");
}
}
}
================================================
FILE: RunGroopWebApp/Controllers/DashboardController.cs
================================================
using CloudinaryDotNet.Actions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
using RunGroopWebApp.ViewModels;
namespace RunGroopWebApp.Controllers
{
[Authorize]
public class DashboardController : Controller
{
private readonly IDashboardRepository _dashboardRespository;
private readonly IPhotoService _photoService;
public DashboardController(IDashboardRepository dashboardRespository, IPhotoService photoService)
{
_dashboardRespository = dashboardRespository;
_photoService = photoService;
}
public async Task Index()
{
var userRaces = await _dashboardRespository.GetAllUserRaces();
var userClubs = await _dashboardRespository.GetAllUserClubs();
var dashboardViewModel = new DashboardViewModel()
{
Races = userRaces,
Clubs = userClubs
};
return View(dashboardViewModel);
}
}
}
================================================
FILE: RunGroopWebApp/Controllers/HomeController.cs
================================================
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using RunGroopWebApp.Data;
using RunGroopWebApp.Helpers;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
using RunGroopWebApp.ViewModels;
using System.Diagnostics;
using System.Globalization;
using System.Net;
namespace RunGroopWebApp.Controllers
{
public class HomeController : Controller
{
private readonly ILogger _logger;
private readonly IClubRepository _clubRepository;
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly ILocationService _locationService;
private readonly IConfiguration _config;
public HomeController(ILogger logger, IClubRepository clubRepository,
UserManager userManager, SignInManager signInManager, ILocationService locationService, IConfiguration config)
{
_logger = logger;
_clubRepository = clubRepository;
_userManager = userManager;
_signInManager = signInManager;
_locationService = locationService;
_config = config;
}
public async Task Index()
{
var ipInfo = new IPInfo();
var homeViewModel = new HomeViewModel();
try
{
string url = "https://ipinfo.io?token=" + _config.GetValue("IPInfoToken");
var info = new WebClient().DownloadString(url);
ipInfo = JsonConvert.DeserializeObject(info);
RegionInfo myRI1 = new RegionInfo(ipInfo.Country);
ipInfo.Country = myRI1.EnglishName;
homeViewModel.City = ipInfo.City;
homeViewModel.State = ipInfo.Region;
if (homeViewModel.City != null)
{
homeViewModel.Clubs = await _clubRepository.GetClubByCity(homeViewModel.City);
}
return View(homeViewModel);
}
catch (Exception)
{
homeViewModel.Clubs = null;
}
return View(homeViewModel);
}
public IActionResult Register()
{
var response = new HomeUserCreateViewModel();
return View(response);
}
[HttpPost]
public async Task Index(HomeViewModel homeVM)
{
var createVM = homeVM.Register;
if (!ModelState.IsValid) return View(homeVM);
var user = await _userManager.FindByEmailAsync(createVM.Email);
if (user != null)
{
ModelState.AddModelError("Register.Email", "This email address is already in use");
return View(homeVM);
}
var userLocation = await _locationService.GetCityByZipCode(createVM.ZipCode ?? 0);
if (userLocation == null)
{
ModelState.AddModelError("Register.ZipCode", "Could not find zip code!");
return View(homeVM);
}
var newUser = new AppUser
{
UserName = createVM.UserName,
Email = createVM.Email,
Address = new Address()
{
State = userLocation.StateCode,
City = userLocation.CityName,
ZipCode = createVM.ZipCode ?? 0,
}
};
var newUserResponse = await _userManager.CreateAsync(newUser, createVM.Password);
if (newUserResponse.Succeeded)
{
await _signInManager.SignInAsync(newUser, isPersistent: false);
await _userManager.AddToRoleAsync(newUser, UserRoles.User);
}
return RedirectToAction("Index", "Club");
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
================================================
FILE: RunGroopWebApp/Controllers/RaceController.cs
================================================
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RunGroopWebApp.Data;
using RunGroopWebApp.Data.Enum;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
using RunGroopWebApp.ViewModels;
namespace RunGroopWebApp.Controllers
{
public class RaceController : Controller
{
private readonly IRaceRepository _raceRepository;
private readonly IPhotoService _photoService;
private readonly IHttpContextAccessor _httpContextAccessor;
public RaceController(IRaceRepository raceRepository, IPhotoService photoService, IHttpContextAccessor httpContextAccessor)
{
_raceRepository = raceRepository;
_photoService = photoService;
_httpContextAccessor = httpContextAccessor;
}
[HttpGet]
public async Task Index(int category = -1, int page = 1, int pageSize = 6)
{
if (page < 1 || pageSize < 1)
{
return NotFound();
}
// if category is -1 (All) dont filter else filter by selected category
var races = category switch
{
-1 => await _raceRepository.GetSliceAsync((page - 1) * pageSize, pageSize),
_ => await _raceRepository.GetRacesByCategoryAndSliceAsync((RaceCategory)category, (page - 1) * pageSize, pageSize),
};
var count = category switch
{
-1 => await _raceRepository.GetCountAsync(),
_ => await _raceRepository.GetCountByCategoryAsync((RaceCategory)category),
};
var viewModel = new IndexRaceViewModel
{
Races = races,
Page = page,
PageSize = pageSize,
TotalRaces = count,
TotalPages = (int)Math.Ceiling(count / (double)pageSize),
Category = category,
};
return View(viewModel);
}
[HttpGet]
[Route("event/{runningRace}/{id}")]
public async Task DetailRace(int id, string runningRace)
{
var race = await _raceRepository.GetByIdAsync(id);
return race == null ? NotFound() : View(race);
}
[HttpGet]
public IActionResult Create()
{
var curUserID = _httpContextAccessor.HttpContext?.User.GetUserId();
var createRaceViewModel = new CreateRaceViewModel { AppUserId = curUserID };
return View(createRaceViewModel);
}
[HttpPost]
public async Task Create(CreateRaceViewModel raceVM)
{
if (ModelState.IsValid)
{
var result = await _photoService.AddPhotoAsync(raceVM.Image);
var race = new Race
{
Title = raceVM.Title,
Description = raceVM.Description,
Image = result.Url.ToString(),
AppUserId = raceVM.AppUserId,
RaceCategory = raceVM.RaceCategory,
Address = new Address
{
Street = raceVM.Address.Street,
City = raceVM.Address.City,
State = raceVM.Address.State,
}
};
_raceRepository.Add(race);
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("", "Photo upload failed");
}
return View(raceVM);
}
[HttpGet]
public async Task Edit(int id)
{
var race = await _raceRepository.GetByIdAsync(id);
if (race == null) return View("Error");
var raceVM = new EditRaceViewModel
{
Title = race.Title,
Description = race.Description,
AddressId = race.AddressId,
Address = race.Address,
URL = race.Image,
RaceCategory = race.RaceCategory
};
return View(raceVM);
}
[HttpPost]
public async Task Edit(int id, EditRaceViewModel raceVM)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError("", "Failed to edit club");
return View(raceVM);
}
var userRace = await _raceRepository.GetByIdAsyncNoTracking(id);
if (userRace == null)
{
return View("Error");
}
var photoResult = await _photoService.AddPhotoAsync(raceVM.Image);
if (photoResult.Error != null)
{
ModelState.AddModelError("Image", "Photo upload failed");
return View(raceVM);
}
if (!string.IsNullOrEmpty(userRace.Image))
{
_ = _photoService.DeletePhotoAsync(userRace.Image);
}
var race = new Race
{
Id = id,
Title = raceVM.Title,
Description = raceVM.Description,
Image = photoResult.Url.ToString(),
AddressId = raceVM.AddressId,
Address = raceVM.Address,
};
_raceRepository.Update(race);
return RedirectToAction("Index");
}
[HttpGet]
public async Task Delete(int id)
{
var clubDetails = await _raceRepository.GetByIdAsync(id);
if (clubDetails == null) return View("Error");
return View(clubDetails);
}
[HttpPost, ActionName("Delete")]
public async Task DeleteClub(int id)
{
var raceDetails = await _raceRepository.GetByIdAsync(id);
if (raceDetails == null)
{
return View("Error");
}
if (!string.IsNullOrEmpty(raceDetails.Image))
{
_ = _photoService.DeletePhotoAsync(raceDetails.Image);
}
_raceRepository.Delete(raceDetails);
return RedirectToAction("Index");
}
}
}
================================================
FILE: RunGroopWebApp/Controllers/UserController.cs
================================================
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using RunGroopWebApp.ViewModels;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Controllers
{
public class UserController : Controller
{
private readonly IUserRepository _userRepository;
private readonly UserManager _userManager;
private readonly IPhotoService _photoService;
public UserController(IUserRepository userRepository, UserManager userManager, IPhotoService photoService)
{
_userRepository = userRepository;
_userManager = userManager;
_photoService = photoService;
}
[HttpGet("users")]
public async Task Index()
{
var users = await _userRepository.GetAllUsers();
List result = new List();
foreach (var user in users)
{
var userViewModel = new UserViewModel()
{
Id = user.Id,
Pace = user.Pace,
City = user.City,
State = user.State,
Mileage = user.Mileage,
UserName = user.UserName,
ProfileImageUrl = user.ProfileImageUrl ?? "/img/avatar-male-4.jpg",
};
result.Add(userViewModel);
}
return View(result);
}
[HttpGet]
public async Task Detail(string id)
{
var user = await _userRepository.GetUserById(id);
if (user == null)
{
return RedirectToAction("Index", "Users");
}
var userDetailViewModel = new UserDetailViewModel()
{
Id = user.Id,
Pace = user.Pace,
City = user.City,
State = user.State,
Mileage = user.Mileage,
UserName = user.UserName,
ProfileImageUrl = user.ProfileImageUrl ?? "/img/avatar-male-4.jpg",
};
return View(userDetailViewModel);
}
[HttpGet]
[Authorize]
public async Task EditProfile()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return View("Error");
}
var editMV = new EditProfileViewModel()
{
City = user.City,
State = user.State,
Pace = user.Pace,
Mileage = user.Mileage,
ProfileImageUrl = user.ProfileImageUrl,
};
return View(editMV);
}
[HttpPost]
[Authorize]
public async Task EditProfile(EditProfileViewModel editVM)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError("", "Failed to edit profile");
return View("EditProfile", editVM);
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return View("Error");
}
if (editVM.Image != null) // only update profile image
{
var photoResult = await _photoService.AddPhotoAsync(editVM.Image);
if (photoResult.Error != null)
{
ModelState.AddModelError("Image", "Failed to upload image");
return View("EditProfile", editVM);
}
if (!string.IsNullOrEmpty(user.ProfileImageUrl))
{
_ = _photoService.DeletePhotoAsync(user.ProfileImageUrl);
}
user.ProfileImageUrl = photoResult.Url.ToString();
editVM.ProfileImageUrl = user.ProfileImageUrl;
await _userManager.UpdateAsync(user);
return View(editVM);
}
user.City = editVM.City;
user.State = editVM.State;
user.Pace = editVM.Pace;
user.Mileage = editVM.Mileage;
await _userManager.UpdateAsync(user);
return RedirectToAction("Detail", "User", new { user.Id });
}
}
}
================================================
FILE: RunGroopWebApp/Data/ApplicationDbContext.cs
================================================
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options)
{
}
public DbSet Races { get; set; }
public DbSet Clubs { get; set; }
public DbSet Addresses { get; set; }
public DbSet States { get; set; }
public DbSet Cities { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Data/Enum/ClubCategory.cs
================================================
namespace RunGroopWebApp.Data.Enum
{
public enum ClubCategory
{
RoadRunner,
Womens,
City,
Trail,
Endurance
}
}
================================================
FILE: RunGroopWebApp/Data/Enum/RaceCategory.cs
================================================
namespace RunGroopWebApp.Data.Enum
{
public enum RaceCategory
{
Marathon,
Ultra,
FiveK,
TenK,
HalfMarathon
}
}
================================================
FILE: RunGroopWebApp/Data/Seed.cs
================================================
using Microsoft.AspNetCore.Identity;
using RunGroopWebApp.Data.Enum;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Data
{
public class Seed
{
public static void SeedData(IApplicationBuilder applicationBuilder)
{
using (var serviceScope = applicationBuilder.ApplicationServices.CreateScope())
{
var context = serviceScope.ServiceProvider.GetService();
context.Database.EnsureCreated();
if (!context.Clubs.Any())
{
context.Clubs.AddRange(new List()
{
new Club()
{
Title = "Running Club 1",
Image = "https://www.eatthis.com/wp-content/uploads/sites/4/2020/05/running.jpg?quality=82&strip=1&resize=640%2C360",
Description = "This is the description of the first cinema",
ClubCategory = ClubCategory.City,
Address = new Address()
{
Street = "123 Main St",
City = "Charlotte",
State = "NC"
}
},
new Club()
{
Title = "Running Club 2",
Image = "https://www.eatthis.com/wp-content/uploads/sites/4/2020/05/running.jpg?quality=82&strip=1&resize=640%2C360",
Description = "This is the description of the first cinema",
ClubCategory = ClubCategory.Endurance,
Address = new Address()
{
Street = "123 Main St",
City = "Charlotte",
State = "NC"
}
},
new Club()
{
Title = "Running Club 3",
Image = "https://www.eatthis.com/wp-content/uploads/sites/4/2020/05/running.jpg?quality=82&strip=1&resize=640%2C360",
Description = "This is the description of the first club",
ClubCategory = ClubCategory.Trail,
Address = new Address()
{
Street = "123 Main St",
City = "Charlotte",
State = "NC"
}
},
new Club()
{
Title = "Running Club 3",
Image = "https://www.eatthis.com/wp-content/uploads/sites/4/2020/05/running.jpg?quality=82&strip=1&resize=640%2C360",
Description = "This is the description of the first club",
ClubCategory = ClubCategory.City,
Address = new Address()
{
Street = "123 Main St",
City = "Michigan",
State = "NC"
}
}
});
context.SaveChanges();
}
//Races
if (!context.Races.Any())
{
context.Races.AddRange(new List()
{
new Race()
{
Title = "Running Race 1",
Image = "https://www.eatthis.com/wp-content/uploads/sites/4/2020/05/running.jpg?quality=82&strip=1&resize=640%2C360",
Description = "This is the description of the first race",
RaceCategory = RaceCategory.Marathon,
Address = new Address()
{
Street = "123 Main St",
City = "Charlotte",
State = "NC"
}
},
new Race()
{
Title = "Running Race 2",
Image = "https://www.eatthis.com/wp-content/uploads/sites/4/2020/05/running.jpg?quality=82&strip=1&resize=640%2C360",
Description = "This is the description of the first race",
RaceCategory = RaceCategory.Ultra,
AddressId = 5,
Address = new Address()
{
Street = "123 Main St",
City = "Charlotte",
State = "NC"
}
}
});
context.SaveChanges();
}
}
}
public static async Task SeedUsersAndRolesAsync(IApplicationBuilder applicationBuilder)
{
using (var serviceScope = applicationBuilder.ApplicationServices.CreateScope())
{
//Roles
var roleManager = serviceScope.ServiceProvider.GetRequiredService>();
if (!await roleManager.RoleExistsAsync(UserRoles.Admin))
await roleManager.CreateAsync(new IdentityRole(UserRoles.Admin));
if (!await roleManager.RoleExistsAsync(UserRoles.User))
await roleManager.CreateAsync(new IdentityRole(UserRoles.User));
//Users
var userManager = serviceScope.ServiceProvider.GetRequiredService>();
string adminUserEmail = "teddysmithdeveloper@gmail.com";
var adminUser = await userManager.FindByEmailAsync(adminUserEmail);
if (adminUser == null)
{
var newAdminUser = new AppUser()
{
UserName = "teddysmithdev",
Email = adminUserEmail,
EmailConfirmed = true,
Address = new Address()
{
Street = "123 Main St",
City = "Charlotte",
State = "NC"
}
};
await userManager.CreateAsync(newAdminUser, "Coding@1234?");
await userManager.AddToRoleAsync(newAdminUser, UserRoles.Admin);
}
string appUserEmail = "user@etickets.com";
var appUser = await userManager.FindByEmailAsync(appUserEmail);
if (appUser == null)
{
var newAppUser = new AppUser()
{
UserName = "app-user",
Email = appUserEmail,
EmailConfirmed = true,
Address = new Address()
{
Street = "123 Main St",
City = "Charlotte",
State = "NC"
}
};
await userManager.CreateAsync(newAppUser, "Coding@1234?");
await userManager.AddToRoleAsync(newAppUser, UserRoles.User);
}
}
}
}
}
================================================
FILE: RunGroopWebApp/Data/UserRoles.cs
================================================
namespace RunGroopWebApp.Data
{
public static class UserRoles
{
public const string Admin = "admin";
public const string User = "user";
}
}
================================================
FILE: RunGroopWebApp/Extensions/NumberExtensions.cs
================================================
namespace RunGroopWebApp.Extensions
{
public static class NumberExtensions
{
public static bool IsNumericType(this object o)
{
switch (Type.GetTypeCode(o.GetType()))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
}
}
================================================
FILE: RunGroopWebApp/Extensions/StringExtensions.cs
================================================
using System.Text.RegularExpressions;
namespace RunGroopWebApp.Extensions
{
public static class StringExtensions
{
public static string FirstCharToUpper(this string input) =>
input switch
{
null => throw new ArgumentNullException(nameof(input)),
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
_ => string.Concat(input[0].ToString().ToUpper(), input.AsSpan(1))
};
public static string GenerateSlug(this string phrase)
{
string str = phrase.RemoveAccent().ToLower();
// invalid chars
str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
// convert multiple spaces into one space
str = Regex.Replace(str, @"\s+", " ").Trim();
// cut and trim
str = str.Substring(0, str.Length <= 45 ? str.Length : 45).Trim();
str = Regex.Replace(str, @"\s", "-"); // hyphens
return str;
}
public static string RemoveAccent(this string txt)
{
byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt);
return System.Text.Encoding.ASCII.GetString(bytes);
}
}
}
================================================
FILE: RunGroopWebApp/Helpers/CloudinarySettings.cs
================================================
namespace RunGroopWebApp.Helpers
{
public class CloudinarySettings
{
public string CloudName { get; set; }
public string ApiKey { get; set; }
public string ApiSecret { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Helpers/IPInfo.cs
================================================
using Newtonsoft.Json;
namespace RunGroopWebApp.Helpers
{
public class IPInfo
{
[JsonProperty("ip")]
public string Ip { get; set; }
[JsonProperty("hostname")]
public string Hostname { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("region")]
public string Region { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("loc")]
public string Location { get; set; }
[JsonProperty("org")]
public string Org { get; set; }
[JsonProperty("postal")]
public string Postal { get; set; }
[JsonProperty("timezone")]
public string Timezone { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Helpers/Location.cs
================================================
namespace RunGroopWebApp.Helpers
{
public class Location
{
public string City { get; set; }
public string State { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Helpers/StateConverter.cs
================================================
namespace RunGroopWebApp.Helpers
{
public static class StateConverter
{
public static string GetState(State state)
{
switch (state)
{
case State.AL:
return "ALABAMA";
case State.AK:
return "ALASKA";
case State.AS:
return "AMERICAN SAMOA";
case State.AZ:
return "ARIZONA";
case State.AR:
return "ARKANSAS";
case State.CA:
return "CALIFORNIA";
case State.CO:
return "COLORADO";
case State.CT:
return "CONNECTICUT";
case State.DE:
return "DELAWARE";
case State.DC:
return "DISTRICT OF COLUMBIA";
case State.FM:
return "FEDERATED STATES OF MICRONESIA";
case State.FL:
return "FLORIDA";
case State.GA:
return "GEORGIA";
case State.GU:
return "GUAM";
case State.HI:
return "HAWAII";
case State.ID:
return "IDAHO";
case State.IL:
return "ILLINOIS";
case State.IN:
return "INDIANA";
case State.IA:
return "IOWA";
case State.KS:
return "KANSAS";
case State.KY:
return "KENTUCKY";
case State.LA:
return "LOUISIANA";
case State.ME:
return "MAINE";
case State.MH:
return "MARSHALL ISLANDS";
case State.MD:
return "MARYLAND";
case State.MA:
return "MASSACHUSETTS";
case State.MI:
return "MICHIGAN";
case State.MN:
return "MINNESOTA";
case State.MS:
return "MISSISSIPPI";
case State.MO:
return "MISSOURI";
case State.MT:
return "MONTANA";
case State.NE:
return "NEBRASKA";
case State.NV:
return "NEVADA";
case State.NH:
return "NEW HAMPSHIRE";
case State.NJ:
return "NEW JERSEY";
case State.NM:
return "NEW MEXICO";
case State.NY:
return "NEW YORK";
case State.NC:
return "NORTH CAROLINA";
case State.ND:
return "NORTH DAKOTA";
case State.MP:
return "NORTHERN MARIANA ISLANDS";
case State.OH:
return "OHIO";
case State.OK:
return "OKLAHOMA";
case State.OR:
return "OREGON";
case State.PW:
return "PALAU";
case State.PA:
return "PENNSYLVANIA";
case State.PR:
return "PUERTO RICO";
case State.RI:
return "RHODE ISLAND";
case State.SC:
return "SOUTH CAROLINA";
case State.SD:
return "SOUTH DAKOTA";
case State.TN:
return "TENNESSEE";
case State.TX:
return "TEXAS";
case State.UT:
return "UTAH";
case State.VT:
return "VERMONT";
case State.VI:
return "VIRGIN ISLANDS";
case State.VA:
return "VIRGINIA";
case State.WA:
return "WASHINGTON";
case State.WV:
return "WEST VIRGINIA";
case State.WI:
return "WISCONSIN";
case State.WY:
return "WYOMING";
}
throw new Exception("Not Available");
}
public static State GetStateByName(string name)
{
switch (name.ToUpper())
{
case "ALABAMA":
return State.AL;
case "ALASKA":
return State.AK;
case "AMERICAN SAMOA":
return State.AS;
case "ARIZONA":
return State.AZ;
case "ARKANSAS":
return State.AR;
case "CALIFORNIA":
return State.CA;
case "COLORADO":
return State.CO;
case "CONNECTICUT":
return State.CT;
case "DELAWARE":
return State.DE;
case "DISTRICT OF COLUMBIA":
return State.DC;
case "FEDERATED STATES OF MICRONESIA":
return State.FM;
case "FLORIDA":
return State.FL;
case "GEORGIA":
return State.GA;
case "GUAM":
return State.GU;
case "HAWAII":
return State.HI;
case "IDAHO":
return State.ID;
case "ILLINOIS":
return State.IL;
case "INDIANA":
return State.IN;
case "IOWA":
return State.IA;
case "KANSAS":
return State.KS;
case "KENTUCKY":
return State.KY;
case "LOUISIANA":
return State.LA;
case "MAINE":
return State.ME;
case "MARSHALL ISLANDS":
return State.MH;
case "MARYLAND":
return State.MD;
case "MASSACHUSETTS":
return State.MA;
case "MICHIGAN":
return State.MI;
case "MINNESOTA":
return State.MN;
case "MISSISSIPPI":
return State.MS;
case "MISSOURI":
return State.MO;
case "MONTANA":
return State.MT;
case "NEBRASKA":
return State.NE;
case "NEVADA":
return State.NV;
case "NEW HAMPSHIRE":
return State.NH;
case "NEW JERSEY":
return State.NJ;
case "NEW MEXICO":
return State.NM;
case "NEW YORK":
return State.NY;
case "NORTH CAROLINA":
return State.NC;
case "NORTH DAKOTA":
return State.ND;
case "NORTHERN MARIANA ISLANDS":
return State.MP;
case "OHIO":
return State.OH;
case "OKLAHOMA":
return State.OK;
case "OREGON":
return State.OR;
case "PALAU":
return State.PW;
case "PENNSYLVANIA":
return State.PA;
case "PUERTO RICO":
return State.PR;
case "RHODE ISLAND":
return State.RI;
case "SOUTH CAROLINA":
return State.SC;
case "SOUTH DAKOTA":
return State.SD;
case "TENNESSEE":
return State.TN;
case "TEXAS":
return State.TX;
case "UTAH":
return State.UT;
case "VERMONT":
return State.VT;
case "VIRGIN ISLANDS":
return State.VI;
case "VIRGINIA":
return State.VA;
case "WASHINGTON":
return State.WA;
case "WEST VIRGINIA":
return State.WV;
case "WISCONSIN":
return State.WI;
case "WYOMING":
return State.WY;
}
throw new Exception("Not Available");
}
public enum State
{
AL,
AK,
AS,
AZ,
AR,
CA,
CO,
CT,
DE,
DC,
FM,
FL,
GA,
GU,
HI,
ID,
IL,
IN,
IA,
KS,
KY,
LA,
ME,
MH,
MD,
MA,
MI,
MN,
MS,
MO,
MT,
NE,
NV,
NH,
NJ,
NM,
NY,
NC,
ND,
MP,
OH,
OK,
OR,
PW,
PA,
PR,
RI,
SC,
SD,
TN,
TX,
UT,
VT,
VI,
VA,
WA,
WV,
WI,
WY
}
}
}
================================================
FILE: RunGroopWebApp/Interfaces/IClubRepository.cs
================================================
using RunGroopWebApp.Data.Enum;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Interfaces
{
public interface IClubRepository
{
Task> GetAll();
Task> GetSliceAsync(int offset, int size);
Task> GetClubsByState(string state);
Task> GetClubsByCategoryAndSliceAsync(ClubCategory category, int offset, int size);
Task> GetAllStates();
Task> GetAllCitiesByState(string state);
Task GetByIdAsync(int id);
Task GetByIdAsyncNoTracking(int id);
Task> GetClubByCity(string city);
Task GetCountAsync();
Task GetCountByCategoryAsync(ClubCategory category);
bool Add(Club club);
bool Update(Club club);
bool Delete(Club club);
bool Save();
}
}
================================================
FILE: RunGroopWebApp/Interfaces/IDashboardRepository.cs
================================================
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Interfaces
{
public interface IDashboardRepository
{
Task> GetAllUserRaces();
Task> GetAllUserClubs();
Task GetUserById(string id);
Task GetByIdNoTracking(string id);
bool Update(AppUser user);
bool Save();
}
}
================================================
FILE: RunGroopWebApp/Interfaces/ILocationService.cs
================================================
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Interfaces
{
public interface ILocationService
{
Task> GetLocationSearch(string location);
Task GetCityByZipCode(int zipCode);
}
}
================================================
FILE: RunGroopWebApp/Interfaces/IPhotoService.cs
================================================
using CloudinaryDotNet.Actions;
namespace RunGroopWebApp.Interfaces
{
public interface IPhotoService
{
Task AddPhotoAsync(IFormFile file);
Task DeletePhotoAsync(string publicUrl);
}
}
================================================
FILE: RunGroopWebApp/Interfaces/IRaceRepository.cs
================================================
using RunGroopWebApp.Data.Enum;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Interfaces
{
public interface IRaceRepository
{
Task GetCountAsync();
Task GetCountByCategoryAsync(RaceCategory category);
Task GetByIdAsync(int id);
Task GetByIdAsyncNoTracking(int id);
Task> GetAll();
Task> GetAllRacesByCity(string city);
Task> GetSliceAsync(int offset, int size);
Task> GetRacesByCategoryAndSliceAsync(RaceCategory category, int offset, int size);
bool Add(Race race);
bool Update(Race race);
bool Delete(Race race);
bool Save();
}
}
================================================
FILE: RunGroopWebApp/Interfaces/IUserRepository.cs
================================================
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Interfaces
{
public interface IUserRepository
{
Task> GetAllUsers();
Task GetUserById(string id);
bool Add(AppUser user);
bool Update(AppUser user);
bool Delete(AppUser user);
bool Save();
}
}
================================================
FILE: RunGroopWebApp/Migrations/20220215112438_InitialCreate.Designer.cs
================================================
//
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using RunGroopWebApp.Data;
#nullable disable
namespace RunGroopWebApp.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20220215112438_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
modelBuilder.Entity("RunGroopWebApp.Models.Address", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("City")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("State")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Street")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Addresses");
});
modelBuilder.Entity("RunGroopWebApp.Models.AppUser", b =>
{
b.Property("Id")
.HasColumnType("nvarchar(450)");
b.Property("AddressId")
.HasColumnType("int");
b.Property("Mileage")
.HasColumnType("int");
b.Property("Pace")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("AddressId");
b.ToTable("AppUser");
});
modelBuilder.Entity("RunGroopWebApp.Models.Club", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("AddressId")
.HasColumnType("int");
b.Property("AppUserId")
.HasColumnType("nvarchar(450)");
b.Property("ClubCategory")
.HasColumnType("int");
b.Property("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Image")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("AppUserId");
b.ToTable("Clubs");
});
modelBuilder.Entity("RunGroopWebApp.Models.Race", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("AddressId")
.HasColumnType("int");
b.Property("AppUserId")
.HasColumnType("nvarchar(450)");
b.Property("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Image")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("RaceCategory")
.HasColumnType("int");
b.Property("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("AppUserId");
b.ToTable("Races");
});
modelBuilder.Entity("RunGroopWebApp.Models.AppUser", b =>
{
b.HasOne("RunGroopWebApp.Models.Address", "Address")
.WithMany()
.HasForeignKey("AddressId");
b.Navigation("Address");
});
modelBuilder.Entity("RunGroopWebApp.Models.Club", b =>
{
b.HasOne("RunGroopWebApp.Models.Address", "Address")
.WithMany()
.HasForeignKey("AddressId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("RunGroopWebApp.Models.AppUser", "AppUser")
.WithMany("Clubs")
.HasForeignKey("AppUserId");
b.Navigation("Address");
b.Navigation("AppUser");
});
modelBuilder.Entity("RunGroopWebApp.Models.Race", b =>
{
b.HasOne("RunGroopWebApp.Models.Address", "Address")
.WithMany()
.HasForeignKey("AddressId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("RunGroopWebApp.Models.AppUser", "AppUser")
.WithMany("Races")
.HasForeignKey("AppUserId");
b.Navigation("Address");
b.Navigation("AppUser");
});
modelBuilder.Entity("RunGroopWebApp.Models.AppUser", b =>
{
b.Navigation("Clubs");
b.Navigation("Races");
});
#pragma warning restore 612, 618
}
}
}
================================================
FILE: RunGroopWebApp/Migrations/20220215112438_InitialCreate.cs
================================================
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace RunGroopWebApp.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Addresses",
columns: table => new
{
Id = table.Column(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Street = table.Column(type: "nvarchar(max)", nullable: false),
City = table.Column(type: "nvarchar(max)", nullable: false),
State = table.Column(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Addresses", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AppUser",
columns: table => new
{
Id = table.Column(type: "nvarchar(450)", nullable: false),
Pace = table.Column(type: "int", nullable: true),
Mileage = table.Column(type: "int", nullable: true),
AddressId = table.Column(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AppUser", x => x.Id);
table.ForeignKey(
name: "FK_AppUser_Addresses_AddressId",
column: x => x.AddressId,
principalTable: "Addresses",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "Clubs",
columns: table => new
{
Id = table.Column(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column(type: "nvarchar(max)", nullable: false),
Description = table.Column(type: "nvarchar(max)", nullable: false),
Image = table.Column(type: "nvarchar(max)", nullable: false),
AddressId = table.Column(type: "int", nullable: false),
ClubCategory = table.Column(type: "int", nullable: false),
AppUserId = table.Column(type: "nvarchar(450)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Clubs", x => x.Id);
table.ForeignKey(
name: "FK_Clubs_Addresses_AddressId",
column: x => x.AddressId,
principalTable: "Addresses",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Clubs_AppUser_AppUserId",
column: x => x.AppUserId,
principalTable: "AppUser",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "Races",
columns: table => new
{
Id = table.Column(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column(type: "nvarchar(max)", nullable: false),
Description = table.Column(type: "nvarchar(max)", nullable: false),
Image = table.Column(type: "nvarchar(max)", nullable: false),
AddressId = table.Column(type: "int", nullable: false),
RaceCategory = table.Column(type: "int", nullable: false),
AppUserId = table.Column(type: "nvarchar(450)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Races", x => x.Id);
table.ForeignKey(
name: "FK_Races_Addresses_AddressId",
column: x => x.AddressId,
principalTable: "Addresses",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Races_AppUser_AppUserId",
column: x => x.AppUserId,
principalTable: "AppUser",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_AppUser_AddressId",
table: "AppUser",
column: "AddressId");
migrationBuilder.CreateIndex(
name: "IX_Clubs_AddressId",
table: "Clubs",
column: "AddressId");
migrationBuilder.CreateIndex(
name: "IX_Clubs_AppUserId",
table: "Clubs",
column: "AppUserId");
migrationBuilder.CreateIndex(
name: "IX_Races_AddressId",
table: "Races",
column: "AddressId");
migrationBuilder.CreateIndex(
name: "IX_Races_AppUserId",
table: "Races",
column: "AppUserId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Clubs");
migrationBuilder.DropTable(
name: "Races");
migrationBuilder.DropTable(
name: "AppUser");
migrationBuilder.DropTable(
name: "Addresses");
}
}
}
================================================
FILE: RunGroopWebApp/Migrations/ApplicationDbContextModelSnapshot.cs
================================================
//
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using RunGroopWebApp.Data;
#nullable disable
namespace RunGroopWebApp.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property("Id")
.HasColumnType("nvarchar(450)");
b.Property("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
{
b.Property("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
{
b.Property("UserId")
.HasColumnType("nvarchar(450)");
b.Property("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
{
b.Property("UserId")
.HasColumnType("nvarchar(450)");
b.Property("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property("Name")
.HasColumnType("nvarchar(450)");
b.Property("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("RunGroopWebApp.Models.Address", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("City")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("State")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Street")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Addresses");
});
modelBuilder.Entity("RunGroopWebApp.Models.AppUser", b =>
{
b.Property("Id")
.HasColumnType("nvarchar(450)");
b.Property("AccessFailedCount")
.HasColumnType("int");
b.Property("AddressId")
.HasColumnType("int");
b.Property("City")
.HasColumnType("nvarchar(max)");
b.Property("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property("EmailConfirmed")
.HasColumnType("bit");
b.Property("LockoutEnabled")
.HasColumnType("bit");
b.Property("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property("Mileage")
.HasColumnType("int");
b.Property("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property("Pace")
.HasColumnType("int");
b.Property("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property("ProfileImageUrl")
.HasColumnType("nvarchar(max)");
b.Property("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property("State")
.HasColumnType("nvarchar(max)");
b.Property("TwoFactorEnabled")
.HasColumnType("bit");
b.Property("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("RunGroopWebApp.Models.City", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("CityName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("County")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Latitude")
.HasColumnType("real");
b.Property("Longitude")
.HasColumnType("real");
b.Property("StateCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Zip")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Cities");
});
modelBuilder.Entity("RunGroopWebApp.Models.Club", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("AddressId")
.HasColumnType("int");
b.Property("AppUserId")
.HasColumnType("nvarchar(450)");
b.Property("ClubCategory")
.HasColumnType("int");
b.Property("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Image")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("AppUserId");
b.ToTable("Clubs");
});
modelBuilder.Entity("RunGroopWebApp.Models.Race", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("AddressId")
.HasColumnType("int");
b.Property("AppUserId")
.HasColumnType("nvarchar(450)");
b.Property("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("Image")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("RaceCategory")
.HasColumnType("int");
b.Property("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("AddressId");
b.HasIndex("AppUserId");
b.ToTable("Races");
});
modelBuilder.Entity("RunGroopWebApp.Models.State", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1);
b.Property("StateCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property("StateName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("States");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
{
b.HasOne("RunGroopWebApp.Models.AppUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
{
b.HasOne("RunGroopWebApp.Models.AppUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("RunGroopWebApp.Models.AppUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
{
b.HasOne("RunGroopWebApp.Models.AppUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("RunGroopWebApp.Models.AppUser", b =>
{
b.HasOne("RunGroopWebApp.Models.Address", "Address")
.WithMany()
.HasForeignKey("AddressId");
b.Navigation("Address");
});
modelBuilder.Entity("RunGroopWebApp.Models.Club", b =>
{
b.HasOne("RunGroopWebApp.Models.Address", "Address")
.WithMany()
.HasForeignKey("AddressId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("RunGroopWebApp.Models.AppUser", "AppUser")
.WithMany("Clubs")
.HasForeignKey("AppUserId");
b.Navigation("Address");
b.Navigation("AppUser");
});
modelBuilder.Entity("RunGroopWebApp.Models.Race", b =>
{
b.HasOne("RunGroopWebApp.Models.Address", "Address")
.WithMany()
.HasForeignKey("AddressId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("RunGroopWebApp.Models.AppUser", "AppUser")
.WithMany("Races")
.HasForeignKey("AppUserId");
b.Navigation("Address");
b.Navigation("AppUser");
});
modelBuilder.Entity("RunGroopWebApp.Models.AppUser", b =>
{
b.Navigation("Clubs");
b.Navigation("Races");
});
#pragma warning restore 612, 618
}
}
}
================================================
FILE: RunGroopWebApp/Models/Address.cs
================================================
using System.ComponentModel.DataAnnotations;
namespace RunGroopWebApp.Models
{
public class Address
{
[Key]
public int Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public int ZipCode { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Models/AppUser.cs
================================================
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RunGroopWebApp.Models
{
public class AppUser : IdentityUser
{
public int? Pace { get; set; }
public int? Mileage { get; set; }
public string? ProfileImageUrl { get; set; }
public string? City { get; set; }
public string? State { get; set; }
[ForeignKey("Address")]
public int? AddressId { get; set; }
public Address? Address { get; set; }
public ICollection Clubs { get; set; }
public ICollection Races { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Models/City.cs
================================================
namespace RunGroopWebApp.Models
{
public class City
{
public int Id { get; set; }
public string CityName { get; set; }
public string StateCode { get; set; }
public int Zip { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public string County { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Models/Club.cs
================================================
using RunGroopWebApp.Data.Enum;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RunGroopWebApp.Models
{
public class Club
{
[Key]
public int Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public string? Image { get; set; }
[ForeignKey("Address")]
public int? AddressId { get; set; }
public Address? Address { get; set; }
public ClubCategory ClubCategory { get; set; }
[ForeignKey("AppUser")]
public string? AppUserId { get; set; }
public AppUser? AppUser { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Models/ErrorViewModel.cs
================================================
namespace RunGroopWebApp.Models
{
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}
================================================
FILE: RunGroopWebApp/Models/Race.cs
================================================
using RunGroopWebApp.Data.Enum;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace RunGroopWebApp.Models
{
public class Race
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string? Image { get; set; }
public DateTime? StartTime { get; set; }
public int? EntryFee { get; set; }
public string? Website { get; set; }
public string? Twitter { get; set; }
public string? Facebook { get; set; }
public string? Contact { get; set; }
[ForeignKey("Address")]
public int AddressId { get; set; }
public Address Address { get; set; }
public RaceCategory RaceCategory { get; set; }
[ForeignKey("AppUser")]
public string? AppUserId { get; set; }
public AppUser? AppUser { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Models/State.cs
================================================
namespace RunGroopWebApp.Models
{
public class State
{
public int Id { get; set; }
public string StateName { get; set; }
public string StateCode { get; set; }
}
}
================================================
FILE: RunGroopWebApp/Program.cs
================================================
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using RunGroopWebApp.Data;
using RunGroopWebApp.Helpers;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
using RunGroopWebApp.Repository;
using RunGroopWebApp.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.Configure(builder.Configuration.GetSection("CloudinarySettings"));
builder.Services.AddDbContext(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
builder.Services.AddIdentity()
.AddEntityFrameworkStores();
builder.Services.AddMemoryCache();
builder.Services.AddSession();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
var app = builder.Build();
if (args.Length == 1 && args[0].ToLower() == "seeddata")
{
await Seed.SeedUsersAndRolesAsync(app);
//Seed.SeedData(app);
}
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
================================================
FILE: RunGroopWebApp/Properties/launchSettings.json
================================================
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:42985",
"sslPort": 44364
}
},
"profiles": {
"RunGroopWebApp": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7195;http://localhost:5195",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
================================================
FILE: RunGroopWebApp/Repository/ClubRepository.cs
================================================
using Microsoft.EntityFrameworkCore;
using RunGroopWebApp.Data;
using RunGroopWebApp.Data.Enum;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Repository
{
public class ClubRepository : IClubRepository
{
private readonly ApplicationDbContext _context;
public ClubRepository(ApplicationDbContext context)
{
_context = context;
}
public bool Add(Club club)
{
_context.Add(club);
return Save();
}
public bool Delete(Club club)
{
_context.Remove(club);
return Save();
}
public async Task> GetAll()
{
return await _context.Clubs.ToListAsync();
}
public async Task> GetAllStates()
{
return await _context.States.ToListAsync();
}
public async Task> GetSliceAsync(int offset, int size)
{
return await _context.Clubs.Include(i => i.Address).Skip(offset).Take(size).ToListAsync();
}
public async Task> GetClubsByCategoryAndSliceAsync(ClubCategory category, int offset, int size)
{
return await _context.Clubs
.Include(i => i.Address)
.Where(c => c.ClubCategory == category)
.Skip(offset)
.Take(size)
.ToListAsync();
}
public async Task GetCountByCategoryAsync(ClubCategory category)
{
return await _context.Clubs.CountAsync(c => c.ClubCategory == category);
}
public async Task GetByIdAsync(int id)
{
return await _context.Clubs.Include(i => i.Address).FirstOrDefaultAsync(i => i.Id == id);
}
public async Task GetByIdAsyncNoTracking(int id)
{
return await _context.Clubs.Include(i => i.Address).AsNoTracking().FirstOrDefaultAsync(i => i.Id == id);
}
public async Task> GetClubByCity(string city)
{
return await _context.Clubs.Where(c => c.Address.City.Contains(city)).Distinct().ToListAsync();
}
public bool Save()
{
var saved = _context.SaveChanges();
return saved > 0;
}
public bool Update(Club club)
{
_context.Update(club);
return Save();
}
public async Task GetCountAsync()
{
return await _context.Clubs.CountAsync();
}
public async Task> GetClubsByState(string state)
{
return await _context.Clubs.Where(c => c.Address.State.Contains(state)).ToListAsync();
}
public async Task> GetAllCitiesByState(string state)
{
return await _context.Cities.Where(c => c.StateCode.Contains(state)).ToListAsync();
}
}
}
================================================
FILE: RunGroopWebApp/Repository/DashboardRepository.cs
================================================
using Microsoft.EntityFrameworkCore;
using RunGroopWebApp.Data;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Repository
{
public class DashboardRepository : IDashboardRepository
{
private readonly ApplicationDbContext _context;
private readonly IHttpContextAccessor _httpContextAccessor;
public DashboardRepository(ApplicationDbContext context, IHttpContextAccessor httpContextAccessor)
{
_context = context;
_httpContextAccessor = httpContextAccessor;
}
public async Task> GetAllUserClubs()
{
var curUser = _httpContextAccessor.HttpContext?.User.GetUserId();
var userClubs = _context.Clubs.Where(r => r.AppUser.Id == curUser);
return userClubs.ToList();
}
public async Task> GetAllUserRaces()
{
var curUser = _httpContextAccessor.HttpContext?.User.GetUserId();
var userRaces = _context.Races.Where(r => r.AppUser.Id == curUser);
return userRaces.ToList();
}
public async Task GetUserById(string id)
{
return await _context.Users.FindAsync(id);
}
public async Task GetByIdNoTracking(string id)
{
return await _context.Users.Where(u => u.Id == id).AsNoTracking().FirstOrDefaultAsync();
}
public bool Update(AppUser user)
{
_context.Users.Update(user);
return Save();
}
public bool Save()
{
var saved = _context.SaveChanges();
return saved > 0 ? true : false;
}
}
}
================================================
FILE: RunGroopWebApp/Repository/RaceRepository.cs
================================================
using Microsoft.EntityFrameworkCore;
using RunGroopWebApp.Data;
using RunGroopWebApp.Data.Enum;
using RunGroopWebApp.Interfaces;
using RunGroopWebApp.Models;
namespace RunGroopWebApp.Repository
{
public class RaceRepository : IRaceRepository
{
private readonly ApplicationDbContext _context;
public RaceRepository(ApplicationDbContext context)
{
_context = context;
}
public bool Add(Race race)
{
_context.Add(race);
return Save();
}
public bool Delete(Race race)
{
_context.Remove(race);
return Save();
}
public async Task> GetAll()
{
return await _context.Races.ToListAsync();
}
public async Task> GetAllRacesByCity(string city)
{
return await _context.Races.Where(c => c.Address.City.Contains(city)).ToListAsync();
}
public async Task GetByIdAsync(int id)
{
return await _context.Races.Include(i => i.Address).FirstOrDefaultAsync(x => x.Id == id);
}
public async Task GetByIdAsyncNoTracking(int id)
{
return await _context.Races.Include(i => i.Address).AsNoTracking().FirstOrDefaultAsync();
}
public async Task