Initial commit

This commit is contained in:
Franklin 2023-05-03 12:03:31 -04:00
commit a6bc84dfb3
20 changed files with 1994 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
.env

1608
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

22
Cargo.toml Normal file
View File

@ -0,0 +1,22 @@
[package]
name = "realtor-lp-types"
version = "0.1.0"
edition = "2021"
[lib]
[dependencies]
chrono = { version = "0.4.23", features = [ "serde" ] }
chrono-tz = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.88"
uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] }
format_num = "0.1.0"
sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "uuid" ], optional = true }
bincode = "1.3.3"
rand = "0.8.5"
[features]
default = ["all"]
all = ["sqlx", "wasm"]
sqlx = ["dep:sqlx"]
wasm = ["uuid/js"]

20
src/domain/click.rs Normal file
View File

@ -0,0 +1,20 @@
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use super::clickable::Clickable;
/// This is a click on a realtors page. Can be many things.
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Click {
pub id: Uuid,
#[serde(rename = "realtorId")]
pub realtor_id: Uuid,
pub clickable: Clickable,
#[serde(rename = "trackableId")]
pub trackable_id: Uuid,
#[serde(rename = "timeCreated")]
pub time_created: DateTime<Utc>,
#[serde(rename = "lastUpdated")]
pub last_updated: DateTime<Utc>
}

View File

@ -0,0 +1,35 @@
use sqlx::{
encode::IsNull,
error::BoxDynError,
postgres::{PgArgumentBuffer, PgTypeInfo, PgValueRef},
Postgres,
};
use super::Clickable;
impl sqlx::Encode<'_, Postgres> for Clickable {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
let binding = serde_json::to_string(self).unwrap();
<&str as sqlx::Encode<Postgres>>::encode(&binding, buf)
}
}
impl sqlx::Decode<'_, Postgres> for Clickable {
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
let column = value.as_str()?;
match serde_json::from_str(column) {
Ok(listing_state) => Ok(listing_state),
Err(error) => Err(Box::new(error)),
}
}
}
impl sqlx::Type<Postgres> for Clickable {
fn type_info() -> PgTypeInfo {
PgTypeInfo::with_name("TEXT")
}
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
*ty == Self::type_info()
}
}

View File

@ -0,0 +1,16 @@
#[cfg(feature = "sqlx")]
pub mod impls;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Clickable {
/// When clicking on a contact button. Could be anything really, but most importantly could be either a phone number or an email.
Contact(String),
}
impl Default for Clickable {
fn default() -> Self {
Self::Contact(String::default())
}
}

13
src/domain/error.rs Normal file
View File

@ -0,0 +1,13 @@
use std::fmt::Display;
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct FromStrError;
impl Display for FromStrError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Error converting string to Type specified.")
}
}
impl std::error::Error for FromStrError {}

62
src/domain/media/impls.rs Normal file
View File

@ -0,0 +1,62 @@
use sqlx::{
encode::IsNull,
error::BoxDynError,
postgres::{PgArgumentBuffer, PgTypeInfo, PgValueRef},
Postgres,
};
use super::{Media, MediaList};
impl sqlx::Encode<'_, Postgres> for Media {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
let binding = serde_json::to_string(self).unwrap();
<&str as sqlx::Encode<Postgres>>::encode(&binding, buf)
}
}
impl sqlx::Decode<'_, Postgres> for Media {
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
let column = value.as_str()?;
match serde_json::from_str(column) {
Ok(listing_state) => Ok(listing_state),
Err(error) => Err(Box::new(error)),
}
}
}
impl sqlx::Type<Postgres> for Media {
fn type_info() -> PgTypeInfo {
PgTypeInfo::with_name("TEXT")
}
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
*ty == Self::type_info()
}
}
impl sqlx::Encode<'_, Postgres> for MediaList {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
let binding = serde_json::to_string(self).unwrap();
<&str as sqlx::Encode<Postgres>>::encode(&binding, buf)
}
}
impl sqlx::Decode<'_, Postgres> for MediaList {
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
let column = value.as_str()?;
match serde_json::from_str(column) {
Ok(listing_state) => Ok(listing_state),
Err(error) => Err(Box::new(error)),
}
}
}
impl sqlx::Type<Postgres> for MediaList {
fn type_info() -> PgTypeInfo {
PgTypeInfo::with_name("TEXT")
}
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
*ty == Self::type_info()
}
}

16
src/domain/media/mod.rs Normal file
View File

@ -0,0 +1,16 @@
#[cfg(feature = "sqlx")]
pub mod impls;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Media {
Photo(String),
Video(String),
}
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct MediaList {
#[serde(rename = "mediaList")]
pub media_list: Vec<Media>,
}

12
src/domain/mod.rs Normal file
View File

@ -0,0 +1,12 @@
pub mod property;
pub mod realtor;
pub mod view;
pub mod project;
pub mod media;
pub mod thing_pk;
pub mod click;
pub mod clickable;
pub mod trackable;
pub mod error;

25
src/domain/project.rs Normal file
View File

@ -0,0 +1,25 @@
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use super::media::MediaList;
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Project {
pub id: Uuid,
pub title: Option<String>,
pub description: String,
#[serde(rename = "realtorId")]
pub realtor_id: Uuid,
pub media: MediaList,
/// This gives the realtor the option to order the projects/properties. On birth,
#[serde(rename = "orderIndex")]
pub order_index: u16,
#[serde(rename = "timeCreated")]
pub time_created: DateTime<Utc>,
#[serde(rename = "lastUpdated")]
pub last_updated: DateTime<Utc>
}

22
src/domain/property.rs Normal file
View File

@ -0,0 +1,22 @@
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use super::media::MediaList;
/// A property can belong to a project, or not. It should always belong to a realtor.
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Property {
pub id: Uuid,
#[serde(rename = "projectId")]
pub project_id: Option<Uuid>,
#[serde(rename = "realtorId")]
pub realtor_id: Uuid,
pub media: MediaList,
#[serde(rename = "timeCreated")]
pub time_created: DateTime<Utc>,
#[serde(rename = "lastUpdated")]
pub last_updated: DateTime<Utc>
}

21
src/domain/realtor.rs Normal file
View File

@ -0,0 +1,21 @@
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Realtor {
pub id: Uuid,
pub name: String,
pub bio: String,
#[serde(rename = "phoneNumber")]
pub phone_number: String,
pub email: Option<String>,
#[serde(rename = "profilePictureUrl")]
pub profile_picture_url: String,
#[serde(rename = "remaxAgentId")]
pub remax_agent_id: Option<i32>,
#[serde(rename = "timeCreated")]
pub time_created: DateTime<Utc>,
#[serde(rename = "lastUpdated")]
pub last_updated: DateTime<Utc>,
}

View File

@ -0,0 +1,64 @@
use std::{str::FromStr, fmt::Display};
use sqlx::{
encode::IsNull,
error::BoxDynError,
postgres::{PgArgumentBuffer, PgTypeInfo, PgValueRef},
Postgres,
};
use crate::domain::error::FromStrError;
use super::ThingPk;
impl Display for ThingPk {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ThingPk::Realtor => write!(f, "Realtor"),
ThingPk::Property => write!(f, "Property"),
ThingPk::Project => write!(f, "Project"),
}
}
}
impl FromStr for ThingPk {
type Err = FromStrError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Project" => Ok(Self::Project),
"Realtor" => Ok(Self::Realtor),
"Property" => Ok(Self::Property),
_ => Err(FromStrError)
}
}
}
#[cfg(feature = "sqlx")]
impl sqlx::Encode<'_, Postgres> for ThingPk {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
let binding = self.to_string();
<&str as sqlx::Encode<Postgres>>::encode(&binding, buf)
}
}
#[cfg(feature = "sqlx")]
impl sqlx::Decode<'_, Postgres> for ThingPk {
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
let column = value.as_str()?;
match Self::from_str(column) {
Ok(listing_state) => Ok(listing_state),
Err(error) => Err(Box::new(error)),
}
}
}
#[cfg(feature = "sqlx")]
impl sqlx::Type<Postgres> for ThingPk {
fn type_info() -> PgTypeInfo {
PgTypeInfo::with_name("TEXT")
}
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
*ty == Self::type_info()
}
}

View File

@ -0,0 +1,11 @@
pub mod impls;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ThingPk {
#[default]
Realtor,
Property,
Project,
}

24
src/domain/trackable.rs Normal file
View File

@ -0,0 +1,24 @@
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
/// A user that can be tracked. All the info that you can gather from the user based on their browser & IP network.
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Trackable {
pub id: Uuid,
/// This field is used to indetify if a user has been to the website before. Pretty much checks to see if the user already has a Trackable UUID in record.
/// But has changed things like IpAddress or user agent.
#[serde(rename = "whoWas")]
pub who_was: Option<Uuid>,
#[serde(rename = "ipAddress")]
pub ip_address: String,
/// Used to determine on what device the user is
#[serde(rename = "browserWidth")]
pub browser_width: u32,
/// Used to determine on what device the user is
#[serde(rename = "browserWidth")]
pub browser_height: u32,
#[serde(rename = "userAgent")]
pub user_agent: String,
pub time_created: DateTime<Utc>,
}

18
src/domain/view.rs Normal file
View File

@ -0,0 +1,18 @@
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use super::thing_pk::ThingPk;
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct View {
pub id: Uuid,
#[serde(rename = "thingId")]
pub thing_id: Uuid,
#[serde(rename = "thingPk")]
pub thing_pk: ThingPk,
#[serde(rename = "trackableId")]
pub trackable_id: Uuid,
#[serde(rename = "timeCreated")]
pub time_created: DateTime<Utc>
}

1
src/dto/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod payloads;

0
src/dto/payloads/mod.rs Normal file
View File

2
src/lib.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod domain;
pub mod dto;