# @everytravel/shared

A comprehensive shared package for Everytravel containing Mongoose models and CRUD operations for hotel booking, user management, and transaction handling. Includes OAuth authentication support for Google, Facebook, and Apple Sign-In.

## 📦 Package Structure

```
shared/
├── models/           # All Mongoose models
│   ├── User.model.js
│   ├── Host.model.js
│   ├── Property.model.js
│   ├── Suite.model.js
│   ├── Booking.model.js
│   ├── Review.model.js
│   ├── Transaction.model.js
│   ├── Card.model.js
│   ├── Discount.model.js
│   ├── Wallet.mode.js
│   └── index.js
├── create/           # Create operations
│   └── index.js
├── read/             # Read operations
│   └── index.js
├── update/           # Update operations
│   └── index.js
├── delete/           # Delete operations
│   └── index.js
├── methods/          # Main methods index
│   └── index.js
├── index.js          # Main package entry point
├── package.json
└── README.md
```

## 🚀 Installation

```bash
npm install @everytravel/shared
```

## 📋 Dependencies

- **mongoose**: ^8.0.3

## 🔧 Usage

### Import Options

#### 1. Import Everything
```javascript
import * as Shared from '@everytravel/shared';
```

#### 2. Import Specific CRUD Operations
```javascript
import { createOne } from '@everytravel/shared/create';
import { getMany, getOne } from '@everytravel/shared/read';
import { updateOne } from '@everytravel/shared/update';
import { deleteOne } from '@everytravel/shared/delete';
```

#### 3. Import Models
```javascript
import { User, Property, Booking, Suite } from '@everytravel/shared/models';
```

#### 4. Import All Methods (Backward Compatible)
```javascript
import { createOne, getMany, getOne, updateOne, deleteOne } from '@everytravel/shared/methods';
```

## 🗄️ Models

### User Model
```javascript
const userData = {
  firstName: "John",
  lastName: "Doe",
  email: "john@example.com",
  phoneNumber: {
    countryCode: "+1",
    number: "5551234567"
  },
  password: "hashedPassword",
  dateOfBirth: new Date("1990-01-01"),
  gender: "male",
  verifiedEmail: true,
  country: "USA",
  address: "123 Main St",
  profilePicUrl: "https://example.com/avatar.jpg",
  // OAuth provider IDs (optional)
  googleId: "google_oauth_id",
  facebookId: "facebook_oauth_id", 
  appleId: "apple_oauth_id"
};
```

### Host Model
```javascript
const hostData = {
  firstName: "Jane",
  lastName: "Smith", 
  email: "jane@example.com",
  phoneNumber: {
    countryCode: "+1",
    number: "5559876543"
  },
  password: "hashedPassword",
  dateOfBirth: new Date("1985-05-15"),
  gender: "female",
  verifiedEmail: true,
  country: "USA",
  address: "789 Business Ave",
  profilePicUrl: "https://example.com/host-avatar.jpg",
  // OAuth provider IDs (optional)
  googleId: "google_oauth_id",
  facebookId: "facebook_oauth_id",
  appleId: "apple_oauth_id"
};
```

### Property Model
```javascript
const propertyData = {
  name: "Luxury Hotel",
  type: "Hotel", // Hotel, Apartment, Guesthouse, Villa, Resort
  description: "A luxurious 5-star hotel",
  location: {
    address: "456 Luxury Ave",
    city: "New York",
    country: "USA",
    zipCode: "10001",
    coordinates: {
      lat: 40.7128,
      lng: -74.0060
    }
  },
  metaTags: ["luxury", "business"],
  facilities: ["wifi", "pool", "spa"],
  starRating: 5,
  owner: hostId
};
```

### Suite Model
```javascript
const suiteData = {
  property: propertyId,
  roomType: "Deluxe Suite",
  stars: 5,
  rating: 4.8,
  pricePerNight: {
    from: 200,
    to: 300,
    currency: "USD"
  },
  sizeSqMeters: 50,
  numBeds: 1,
  bedType: "king",
  availabilityCount: 5,
  sleeps: 2,
  numBathrooms: 1,
  features: ["wifi", "tv", "minibar"],
  metaTags: ["luxury", "ocean-view"]
};
```

### Booking Model
```javascript
const bookingData = {
  user: userId,
  suite: suiteId,
  property: propertyId,
  checkInDate: new Date("2024-01-15"),
  checkOutDate: new Date("2024-01-18"),
  guests: {
    adults: 2,
    children: 1
  },
  numRooms: 1,
  price: {
    base: 600,
    taxes: 60,
    discounts: 30,
    total: 630,
    currency: "USD"
  },
  paymentStatus: "paid", // pending, paid, failed, refunded
  bookingStatus: "confirmed" // confirmed, cancelled, completed
};
```

## 🔄 CRUD Operations

### Create Operations

#### `createOne(Model, data)`
Creates a new document in the specified model.

```javascript
import { createOne } from '@everytravel/shared/create';
import { User } from '@everytravel/shared/models';

// Create a new user
const newUser = await createOne(User, userData);
console.log('Created user:', newUser);
```

### Read Operations

#### `getMany(Model, filter, options)`
Retrieves multiple documents with optional filtering and pagination.

```javascript
import { getMany } from '@everytravel/shared/read';
import { Property } from '@everytravel/shared/models';

// Get all properties
const allProperties = await getMany(Property);

// Get properties with filters
const luxuryHotels = await getMany(Property, {
  type: "Hotel",
  starRating: { $gte: 4 }
}, {
  sort: { starRating: -1 },
  limit: 10,
  skip: 0,
  populate: "owner"
});
```

#### `getOne(Model, filter, options)`
Retrieves a single document.

```javascript
import { getOne } from '@everytravel/shared/read';
import { User } from '@everytravel/shared/models';

// Get user by email
const user = await getOne(User, { email: "john@example.com" }, {
  populate: "wallet"
});
```

### Update Operations

#### `updateOne(Model, filter, update, options)`
Updates a single document.

```javascript
import { updateOne } from '@everytravel/shared/update';
import { User } from '@everytravel/shared/models';

// Update user profile
const updatedUser = await updateOne(
  User,
  { _id: userId },
  { 
    firstName: "Johnny",
    verifiedEmail: true 
  },
  { new: true }
);
```

### Delete Operations

#### `deleteOne(Model, filter)`
Deletes a single document.

```javascript
import { deleteOne } from '@everytravel/shared/delete';
import { Booking } from '@everytravel/shared/models';

// Delete a booking
const deletedBooking = await deleteOne(Booking, { _id: bookingId });
```

## 📊 Complete Example

```javascript
import { 
  createOne, 
  getMany, 
  getOne, 
  updateOne, 
  deleteOne 
} from '@everytravel/shared/methods';
import { 
  User, 
  Host,
  Property, 
  Suite, 
  Booking 
} from '@everytravel/shared/models';

// Create a host with OAuth support
const host = await createOne(Host, {
  firstName: "Jane",
  lastName: "Smith",
  email: "jane@example.com",
  password: "hashedPassword",
  verifiedEmail: true,
  // OAuth fields (optional)
  googleId: "google_oauth_id",
  facebookId: "facebook_oauth_id"
});

// Create a property
const property = await createOne(Property, {
  name: "Sunset Resort",
  type: "Resort",
  owner: host._id,
  starRating: 5
});

// Create a suite
const suite = await createOne(Suite, {
  property: property._id,
  roomType: "Ocean View Suite",
  pricePerNight: { from: 300, to: 400, currency: "USD" }
});

// Create a user with OAuth support
const user = await createOne(User, {
  firstName: "John",
  lastName: "Doe",
  email: "john@example.com",
  verifiedEmail: true,
  // OAuth fields (optional)
  googleId: "google_oauth_id",
  appleId: "apple_oauth_id"
});

// Create a booking
const booking = await createOne(Booking, {
  user: user._id,
  suite: suite._id,
  property: property._id,
  checkInDate: new Date("2024-02-01"),
  checkOutDate: new Date("2024-02-05"),
  guests: { adults: 2, children: 0 },
  price: { base: 1200, taxes: 120, total: 1320, currency: "USD" }
});

// Get all bookings for a user
const userBookings = await getMany(Booking, 
  { user: user._id },
  { populate: ["suite", "property"] }
);

// Update booking status
await updateOne(Booking, 
  { _id: booking._id },
  { bookingStatus: "completed" }
);

// Find user by OAuth provider ID
const googleUser = await getOne(User, { googleId: "google_oauth_id" });
```

## 🔗 Model Relationships

### User Relationships
- **Wallet**: One-to-one relationship
- **Saved Items**: Arrays of references (Bookings, Rides, Suites)
- **Cards**: Array of Card references
- **Transactions**: Array of Transaction references
- **Offers**: Array of Discount references
- **OAuth Providers**: Google, Facebook, Apple authentication IDs

### Host Relationships
- **Properties Created**: Array of Property references
- **OAuth Providers**: Google, Facebook, Apple authentication IDs

### Property Relationships
- **Owner**: Reference to Host
- **Suites**: Array of Suite references

### Suite Relationships
- **Property**: Reference to Property
- **Reviews**: Array of Review references

### Booking Relationships
- **User**: Reference to User
- **Suite**: Reference to Suite
- **Property**: Reference to Property
- **Discount Used**: Reference to Discount

## 🛠️ Error Handling

All CRUD operations include comprehensive error handling:

```javascript
try {
  const result = await createOne(User, userData);
} catch (error) {
  console.error('Error creating user:', error.message);
  // Handle specific error cases
}
```

## 📦 Package Exports

The package provides the following exports:

```json
{
  "exports": {
    "./models": "./models/index.js",
    "./methods": "./methods/index.js",
    "./create": "./create/index.js",
    "./read": "./read/index.js",
    "./update": "./update/index.js",
    "./delete": "./delete/index.js"
  }
}
```

## 🔐 OAuth Authentication Support

This package includes OAuth provider ID fields for seamless integration with authentication systems:

### Supported OAuth Providers
- **Google OAuth 2.0**: `googleId` field
- **Facebook OAuth**: `facebookId` field  
- **Apple Sign-In**: `appleId` field

### OAuth Integration Example
```javascript
// Find user by OAuth provider ID
const user = await getOne(User, { googleId: "google_oauth_id" });

// Update user with OAuth information
await updateOne(User, 
  { email: "user@example.com" },
  { 
    googleId: "new_google_id",
    verifiedEmail: true,
    profilePicUrl: "https://example.com/avatar.jpg"
  }
);

// Check if user exists with any OAuth provider
const existingUser = await getOne(User, {
  $or: [
    { googleId: "google_id" },
    { facebookId: "facebook_id" },
    { appleId: "apple_id" }
  ]
});
```

## 🤝 Contributing

1. Follow the modular structure
2. Add comprehensive JSDoc comments
3. Include error handling in all operations
4. Maintain backward compatibility
5. Update this README for any new features
6. Test OAuth integration scenarios

## 📄 License

ISC License

## 🔗 Related Packages

- `@everytravel/server-primera` - Backend server implementation with Passport.js OAuth
- `@everytravel/client` - Frontend client application

## 🔄 Version History

### v1.0.3 (Latest)
- ✅ Added OAuth provider ID fields to User and Host models
- ✅ Support for Google, Facebook, and Apple Sign-In
- ✅ Backward compatible with existing data
- ✅ Enhanced documentation with OAuth examples

### v1.0.2
- ✅ Initial OAuth field additions
- ✅ Database schema updates

### v1.0.1
- ✅ Core CRUD operations
- ✅ Basic model structure

---

**Note**: This package is designed to be used with MongoDB and Mongoose. Ensure your MongoDB connection is properly configured before using these models and operations. The OAuth fields are optional and backward compatible. 