Packages
phoenix_kit
1.7.39
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/modules/shop/events.ex
defmodule PhoenixKit.Modules.Shop.Events do
@moduledoc """
PubSub event broadcasting for Shop module.
This module provides functions to broadcast cart changes across
multiple browser tabs and devices for the same user/session, as well
as product, category, and inventory updates for real-time admin dashboards.
## Topics
- `shop:cart:user:{user_id}` - Cart events for authenticated users
- `shop:cart:session:{session_id}` - Cart events for guest sessions
- `shop:products` - Product events (created, updated, deleted)
- `shop:categories` - Category events (created, updated, deleted)
- `shop:inventory` - Inventory events (stock changes)
- `shop:products:{product_id}` - Individual product events
## Events
### Cart Events
- `{:cart_updated, cart}` - Cart totals changed (generic update)
- `{:item_added, cart, item}` - Item added to cart
- `{:item_removed, cart, item_id}` - Item removed from cart
- `{:quantity_updated, cart, item}` - Item quantity changed
- `{:shipping_selected, cart}` - Shipping method selected/changed
- `{:payment_selected, cart}` - Payment option selected/changed
- `{:cart_cleared, cart}` - All items removed from cart
### Product Events
- `{:product_created, product}` - New product created
- `{:product_updated, product}` - Product updated
- `{:product_deleted, product_id}` - Product deleted
- `{:products_bulk_status_changed, product_ids, status}` - Bulk status update
### Category Events
- `{:category_created, category}` - New category created
- `{:category_updated, category}` - Category updated
- `{:category_deleted, category_id}` - Category deleted
### Inventory Events
- `{:inventory_updated, product_id, stock_change}` - Stock level changed
## Examples
# Subscribe to cart updates for authenticated user
Events.subscribe_to_user_cart(user_id)
# Subscribe to cart updates for guest session
Events.subscribe_to_session_cart(session_id)
# Subscribe to product updates (admin dashboard)
Events.subscribe_products()
# Broadcast item added
Events.broadcast_item_added(cart, item)
# Broadcast product created
Events.broadcast_product_created(product)
# Handle in LiveView
def handle_info({:item_added, cart, _item}, socket) do
{:noreply, assign(socket, :cart, cart)}
end
"""
alias PhoenixKit.Modules.Shop.Cart
alias PhoenixKit.PubSub.Manager
# ============================================
# TOPIC CONSTANTS
# ============================================
@products_topic "shop:products"
@categories_topic "shop:categories"
@inventory_topic "shop:inventory"
# ============================================
# TOPIC GETTERS
# ============================================
@doc """
Returns the PubSub topic for all products.
"""
def products_topic, do: @products_topic
@doc """
Returns the PubSub topic for all categories.
"""
def categories_topic, do: @categories_topic
@doc """
Returns the PubSub topic for inventory events.
"""
def inventory_topic, do: @inventory_topic
# ============================================
# TOPIC BUILDERS
# ============================================
@doc """
Returns the PubSub topic for a user's cart.
"""
def user_cart_topic(user_id) when not is_nil(user_id) do
"shop:cart:user:#{user_id}"
end
@doc """
Returns the PubSub topic for a session's cart.
"""
def session_cart_topic(session_id) when not is_nil(session_id) do
"shop:cart:session:#{session_id}"
end
@doc """
Returns the appropriate topic(s) for a cart.
"""
def cart_topics(%Cart{user_id: user_id, session_id: session_id}) do
topics = []
topics = if user_id, do: [user_cart_topic(user_id) | topics], else: topics
topics = if session_id, do: [session_cart_topic(session_id) | topics], else: topics
topics
end
@doc """
Returns the PubSub topic for a specific product.
"""
def product_topic(product_id) when not is_nil(product_id) do
"#{@products_topic}:#{product_id}"
end
# ============================================
# SUBSCRIPTION FUNCTIONS
# ============================================
# --------------------------------------------
# Product Subscriptions
# --------------------------------------------
@doc """
Subscribes to product events.
"""
def subscribe_products do
Manager.subscribe(@products_topic)
end
@doc """
Subscribes to events for a specific product.
"""
def subscribe_product(product_id) when not is_nil(product_id) do
Manager.subscribe(product_topic(product_id))
end
# --------------------------------------------
# Category Subscriptions
# --------------------------------------------
@doc """
Subscribes to category events.
"""
def subscribe_categories do
Manager.subscribe(@categories_topic)
end
# --------------------------------------------
# Inventory Subscriptions
# --------------------------------------------
@doc """
Subscribes to inventory events.
"""
def subscribe_inventory do
Manager.subscribe(@inventory_topic)
end
@doc """
Subscribes to cart events for a specific cart.
Subscribes to all relevant topics (user and/or session).
"""
def subscribe_to_cart(%Cart{} = cart) do
cart
|> cart_topics()
|> Enum.each(&Manager.subscribe/1)
end
@doc """
Subscribes to cart events for an authenticated user.
"""
def subscribe_to_user_cart(user_id) when not is_nil(user_id) do
Manager.subscribe(user_cart_topic(user_id))
end
@doc """
Subscribes to cart events for a guest session.
"""
def subscribe_to_session_cart(session_id) when not is_nil(session_id) do
Manager.subscribe(session_cart_topic(session_id))
end
@doc """
Unsubscribes from cart events for a specific cart.
"""
def unsubscribe_from_cart(%Cart{} = cart) do
cart
|> cart_topics()
|> Enum.each(&Manager.unsubscribe/1)
end
@doc """
Unsubscribes from cart events for an authenticated user.
"""
def unsubscribe_from_user_cart(user_id) when not is_nil(user_id) do
Manager.unsubscribe(user_cart_topic(user_id))
end
@doc """
Unsubscribes from cart events for a guest session.
"""
def unsubscribe_from_session_cart(session_id) when not is_nil(session_id) do
Manager.unsubscribe(session_cart_topic(session_id))
end
# ============================================
# PRODUCT BROADCAST FUNCTIONS
# ============================================
@doc """
Broadcasts product created event.
"""
def broadcast_product_created(product) do
broadcast(@products_topic, {:product_created, product})
end
@doc """
Broadcasts product updated event.
"""
def broadcast_product_updated(product) do
broadcast(@products_topic, {:product_updated, product})
broadcast(product_topic(product.id), {:product_updated, product})
end
@doc """
Broadcasts product deleted event.
"""
def broadcast_product_deleted(product_id) do
broadcast(@products_topic, {:product_deleted, product_id})
end
@doc """
Broadcasts bulk product status changed event.
"""
def broadcast_products_bulk_status_changed(product_ids, status) do
broadcast(@products_topic, {:products_bulk_status_changed, product_ids, status})
end
# ============================================
# CATEGORY BROADCAST FUNCTIONS
# ============================================
@doc """
Broadcasts category created event.
"""
def broadcast_category_created(category) do
broadcast(@categories_topic, {:category_created, category})
end
@doc """
Broadcasts category updated event.
"""
def broadcast_category_updated(category) do
broadcast(@categories_topic, {:category_updated, category})
end
@doc """
Broadcasts category deleted event.
"""
def broadcast_category_deleted(category_id) do
broadcast(@categories_topic, {:category_deleted, category_id})
end
@doc """
Broadcasts bulk category status changed event.
"""
def broadcast_categories_bulk_status_changed(category_ids, status) do
broadcast(@categories_topic, {:categories_bulk_status_changed, category_ids, status})
end
@doc """
Broadcasts bulk category parent changed event.
"""
def broadcast_categories_bulk_parent_changed(category_ids, parent_uuid) do
broadcast(@categories_topic, {:categories_bulk_parent_changed, category_ids, parent_uuid})
end
@doc """
Broadcasts bulk category deleted event.
"""
def broadcast_categories_bulk_deleted(category_ids) do
broadcast(@categories_topic, {:categories_bulk_deleted, category_ids})
end
# ============================================
# INVENTORY BROADCAST FUNCTIONS
# ============================================
@doc """
Broadcasts inventory updated event.
"""
def broadcast_inventory_updated(product_id, stock_change) do
broadcast(@inventory_topic, {:inventory_updated, product_id, stock_change})
broadcast(product_topic(product_id), {:inventory_updated, product_id, stock_change})
end
# ============================================
# CART BROADCAST FUNCTIONS
# ============================================
@doc """
Broadcasts a generic cart update event.
"""
def broadcast_cart_updated(%Cart{} = cart) do
broadcast_to_cart(cart, {:cart_updated, cart})
end
@doc """
Broadcasts item added event.
"""
def broadcast_item_added(%Cart{} = cart, item) do
broadcast_to_cart(cart, {:item_added, cart, item})
end
@doc """
Broadcasts item removed event.
"""
def broadcast_item_removed(%Cart{} = cart, item_id) do
broadcast_to_cart(cart, {:item_removed, cart, item_id})
end
@doc """
Broadcasts quantity updated event.
"""
def broadcast_quantity_updated(%Cart{} = cart, item) do
broadcast_to_cart(cart, {:quantity_updated, cart, item})
end
@doc """
Broadcasts shipping method selected event.
"""
def broadcast_shipping_selected(%Cart{} = cart) do
broadcast_to_cart(cart, {:shipping_selected, cart})
end
@doc """
Broadcasts payment option selected event.
"""
def broadcast_payment_selected(%Cart{} = cart) do
broadcast_to_cart(cart, {:payment_selected, cart})
end
@doc """
Broadcasts cart cleared event.
"""
def broadcast_cart_cleared(%Cart{} = cart) do
broadcast_to_cart(cart, {:cart_cleared, cart})
end
# ============================================
# PRIVATE FUNCTIONS
# ============================================
defp broadcast_to_cart(%Cart{} = cart, message) do
cart
|> cart_topics()
|> Enum.each(fn topic ->
Manager.broadcast(topic, message)
end)
end
defp broadcast(topic, message) do
Manager.broadcast(topic, message)
end
end