filters #26
@@ -48,17 +48,13 @@
|
|||||||
"name": "Locale",
|
"name": "Locale",
|
||||||
"description": "Locale selection endpoints (under /api/v1/restricted/langs-and-countries, requires authentication)"
|
"description": "Locale selection endpoints (under /api/v1/restricted/langs-and-countries, requires authentication)"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Repo",
|
|
||||||
"description": "Repository time tracking data endpoints (under /api/v1/restricted/repo, requires authentication)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Admin",
|
|
||||||
"description": "Admin-only endpoints"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Settings",
|
"name": "Settings",
|
||||||
"description": "Application settings and configuration endpoints"
|
"description": "Application settings and configuration endpoints"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Carts",
|
||||||
|
"description": "Shopping cart management endpoints (under /api/v1/restricted/carts, requires authentication)"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
@@ -629,6 +625,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/v1/public/auth/update-choice": {
|
||||||
|
"post": {
|
||||||
|
"tags": ["Auth"],
|
||||||
|
"summary": "Update JWT token choice",
|
||||||
|
"description": "Updates the user's JWT token preference or refreshes the token. Requires authentication.",
|
||||||
|
"operationId": "updateChoice",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"CookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Token choice updated successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ApiResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Not authenticated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/public/auth/google": {
|
"/api/v1/public/auth/google": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": ["Auth"],
|
"tags": ["Auth"],
|
||||||
@@ -733,292 +764,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/restricted/repo/get-repos": {
|
|
||||||
"get": {
|
|
||||||
"tags": ["Repo"],
|
|
||||||
"summary": "Get accessible repositories",
|
|
||||||
"description": "Returns a list of repository IDs that the authenticated user has access to.",
|
|
||||||
"operationId": "getRepos",
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"CookieAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "List of repository IDs",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint"
|
|
||||||
},
|
|
||||||
"example": [1, 2, 5]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Invalid user session",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"description": "Not authenticated",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/v1/restricted/repo/get-years": {
|
|
||||||
"get": {
|
|
||||||
"tags": ["Repo"],
|
|
||||||
"summary": "Get available years for a repository",
|
|
||||||
"description": "Returns a list of years for which tracked time data exists in the given repository. User must have access to the repository.",
|
|
||||||
"operationId": "getYears",
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"CookieAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "repoID",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Repository ID",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "List of years with tracked time data",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint"
|
|
||||||
},
|
|
||||||
"example": [2023, 2024, 2025]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Invalid repoID parameter or user does not have access to the repository",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"description": "Not authenticated",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/v1/restricted/repo/get-quarters": {
|
|
||||||
"get": {
|
|
||||||
"tags": ["Repo"],
|
|
||||||
"summary": "Get quarterly time data for a repository",
|
|
||||||
"description": "Returns time tracked per quarter for the given repository and year. All 4 quarters are returned; quarters with no data have time=0. User must have access to the repository.",
|
|
||||||
"operationId": "getQuarters",
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"CookieAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "repoID",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Repository ID",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "year",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Year to retrieve quarterly data for",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint",
|
|
||||||
"example": 2024
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Quarterly time data",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/QuarterData"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Invalid repoID or year parameter, or user does not have access to the repository",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"description": "Not authenticated",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/v1/restricted/repo/get-issues": {
|
|
||||||
"get": {
|
|
||||||
"tags": ["Repo"],
|
|
||||||
"summary": "Get issues with time summaries",
|
|
||||||
"description": "Returns a paginated list of issues with time tracking summaries for the given repository, year, and quarter. User must have access to the repository.",
|
|
||||||
"operationId": "getIssues",
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"CookieAuth": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "repoID",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Repository ID",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "year",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Year to filter issues by",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint",
|
|
||||||
"example": 2024
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "quarter",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Quarter number (1-4) to filter issues by",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 4,
|
|
||||||
"example": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "page_number",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Page number for pagination (1-based)",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint",
|
|
||||||
"example": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "elements_per_page",
|
|
||||||
"in": "query",
|
|
||||||
"description": "Number of items per page",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint",
|
|
||||||
"example": 30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "Paginated list of issues with time summaries",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/PaginatedIssues"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
"description": "Invalid parameters or user does not have access to the repository",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"401": {
|
|
||||||
"description": "Not authenticated",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/api/v1/settings": {
|
"/api/v1/settings": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": ["Settings"],
|
"tags": ["Settings"],
|
||||||
@@ -1043,7 +788,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"tags": ["Products"],
|
"tags": ["Products"],
|
||||||
"summary": "Get product listing",
|
"summary": "Get product listing",
|
||||||
"description": "Returns a paginated list of products with their basic information. Supports filtering via query parameters with operators (e.g., product_id_eq=12, name=~gold). Use sort parameter for ordering. Requires authentication.",
|
"description": "Returns a paginated list of products with their basic information. Supports filtering via query parameters with operators (e.g., product_id_eq=12, name=~wałek). Use sort parameter for ordering. Requires authentication.",
|
||||||
"operationId": "getProductListing",
|
"operationId": "getProductListing",
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
@@ -1093,11 +838,10 @@
|
|||||||
{
|
{
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"description": "Filter by product name using LIKE (case-insensitive). Use ~ prefix for partial match (e.g., '~gold')",
|
"description": "Filter by product name using LIKE (case-insensitive). Use ~ prefix for partial match (e.g., '~wałek')",
|
||||||
"required": false,
|
"required": false,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string",
|
"type": "string"
|
||||||
"example": "~gold"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1767,6 +1511,280 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/restricted/carts/add-new-cart": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Carts"],
|
||||||
|
"summary": "Create a new cart",
|
||||||
|
"description": "Creates a new shopping cart for the authenticated user. Requires authentication.",
|
||||||
|
"operationId": "addNewCart",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"CookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Cart created successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ApiResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Not authenticated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/restricted/carts/change-cart-name": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Carts"],
|
||||||
|
"summary": "Change cart name",
|
||||||
|
"description": "Updates the name of an existing cart. Requires authentication.",
|
||||||
|
"operationId": "changeCartName",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"CookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "cart_id",
|
||||||
|
"in": "query",
|
||||||
|
"description": "ID of the cart to rename",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "new_name",
|
||||||
|
"in": "query",
|
||||||
|
"description": "New name for the cart",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Cart name updated successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ApiResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request parameters",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Not authenticated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/restricted/carts/retrieve-carts-info": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Carts"],
|
||||||
|
"summary": "Retrieve all carts info",
|
||||||
|
"description": "Returns information about all carts belonging to the authenticated user. Requires authentication.",
|
||||||
|
"operationId": "retrieveCartsInfo",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"CookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Carts info retrieved successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ApiResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Not authenticated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/restricted/carts/retrieve-cart": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Carts"],
|
||||||
|
"summary": "Retrieve cart details",
|
||||||
|
"description": "Returns detailed contents of a specific cart. Requires authentication.",
|
||||||
|
"operationId": "retrieveCart",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"CookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "cart_id",
|
||||||
|
"in": "query",
|
||||||
|
"description": "ID of the cart to retrieve",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Cart retrieved successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ApiResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request parameters",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Not authenticated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/restricted/carts/add-product-to-cart": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Carts"],
|
||||||
|
"summary": "Add product to cart",
|
||||||
|
"description": "Adds a product to the specified cart. Requires authentication.",
|
||||||
|
"operationId": "addProductToCart",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"CookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "cart_id",
|
||||||
|
"in": "query",
|
||||||
|
"description": "ID of the cart to add product to",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "product_id",
|
||||||
|
"in": "query",
|
||||||
|
"description": "ID of the product to add",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "product_attribute_id",
|
||||||
|
"in": "query",
|
||||||
|
"description": "ID of the product attribute (optional, for product variants)",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "amount",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Quantity to add",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Product added to cart successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ApiResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request parameters",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Not authenticated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ type ProductInList struct {
|
|||||||
CategoryName string `gorm:"column:category_name" json:"category_name" form:"category_name"`
|
CategoryName string `gorm:"column:category_name" json:"category_name" form:"category_name"`
|
||||||
Reference string `gorm:"column:reference" json:"reference"`
|
Reference string `gorm:"column:reference" json:"reference"`
|
||||||
VariantsNumber uint `gorm:"column:variants_number" json:"variants_number"`
|
VariantsNumber uint `gorm:"column:variants_number" json:"variants_number"`
|
||||||
Quantity uint `gorm:"column:quantity" json:"quantity"`
|
Quantity int64 `gorm:"column:quantity" json:"quantity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductFilters struct {
|
type ProductFilters struct {
|
||||||
|
|||||||
@@ -1,89 +1,102 @@
|
|||||||
<template>
|
<template>
|
||||||
<component :is="Default || 'div'">
|
<component :is="Default || 'div'">
|
||||||
<div class="container mx-auto mt-20">
|
<div class="container mx-auto mt-20">
|
||||||
<div class="flex flex-col gap-5 mb-6">
|
<div class="flex flex-col gap-5 mb-6">
|
||||||
<h1 class="text-2xl font-bold text-black dark:text-white">{{ t('Customer Data') }}</h1>
|
<h1 class="text-2xl font-bold text-black dark:text-white">{{ t('Customer Data') }}</h1>
|
||||||
|
|
||||||
<div v-if="!customerStore.hasAccount" class="flex flex-col items-center justify-center py-12">
|
<div v-if="!customerStore.hasAccount" class="flex flex-col items-center justify-center py-12">
|
||||||
<div class="text-center flex flex-col items-center justify-center mb-6">
|
<div class="text-center flex flex-col items-center justify-center mb-6">
|
||||||
<UIcon name="mdi:domain" class="text-[60px] text-gray-400 dark:text-gray-500" />
|
<UIcon name="mdi:domain" class="text-[60px] text-gray-400 dark:text-gray-500" />
|
||||||
<p class="mt-4 text-lg text-gray-600 dark:text-gray-400">{{ t('No customer account found') }}</p>
|
<p class="mt-4 text-lg text-gray-600 dark:text-gray-400">{{ t('No customer account found') }}
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-500">{{ t('Create an account to manage your company data') }}</p>
|
</p>
|
||||||
</div>
|
<p class="text-sm text-gray-500 dark:text-gray-500">{{ t('Create an account to manage your company data') }}</p>
|
||||||
<UButton color="primary" @click="goToCreateAccount"
|
|
||||||
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
|
|
||||||
<UIcon name="mdi:add-bold" />
|
|
||||||
{{ t('Create Account') }}
|
|
||||||
</UButton>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else class="flex flex-col gap-3">
|
|
||||||
<div class="grid grid-cols-2 gap-5">
|
|
||||||
<div
|
|
||||||
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-4">
|
|
||||||
<h2 class="text-xl font-semibold text-black dark:text-white mb-4 flex items-center gap-2">
|
|
||||||
<UIcon name="mdi:domain"
|
|
||||||
class="text-[24px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
|
||||||
{{ t('Company Information') }}
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
|
|
||||||
<div>
|
|
||||||
<label
|
|
||||||
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{ t('Company Name') }}</label>
|
|
||||||
<p class="text-black dark:text-white">{{ customerStore.customer?.companyName || '-' }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('Company Email') }}</label>
|
|
||||||
<p class="text-black dark:text-white">{{ customerStore.customer?.companyEmail || '-' }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('REGON') }}</label>
|
|
||||||
<p class="text-black dark:text-white">{{ customerStore.customer?.regon || '-' }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('NIP') }}</label>
|
|
||||||
<p class="text-black dark:text-white">{{ customerStore.customer?.nip || '-' }}</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('VAT') }}</label>
|
|
||||||
<p class="text-black dark:text-white">{{ customerStore.customer?.vat || '-' }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-4">
|
<UButton color="primary" @click="goToCreateAccount"
|
||||||
<h2 class="text-xl font-semibold text-black dark:text-white mb-4 flex items-center gap-2">
|
class="bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) text-white hover:bg-(--accent-blue-dark) dark:hover:bg-(--accent-blue-light)">
|
||||||
<UIcon name="mdi:map-marker"
|
<UIcon name="mdi:add-bold" />
|
||||||
class="text-[24px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
{{ t('Create Account') }}
|
||||||
{{ t('Addresses') }}
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-2">{{ t('Company Address') }}</label>
|
|
||||||
<div v-if="companyAddress"
|
|
||||||
class="p-4 bg-white dark:bg-(--black) rounded-md border border-(--border-light) dark:border-(--border-dark)">
|
|
||||||
<p class="text-black dark:text-white">{{ companyAddress.street }}</p>
|
|
||||||
<p class="text-black dark:text-white">{{ companyAddress.zipCode }}, {{
|
|
||||||
companyAddress.city }}</p>
|
|
||||||
<p class="text-black dark:text-white">{{ companyAddress.country }}</p>
|
|
||||||
</div>
|
|
||||||
<p v-else class="text-gray-400 dark:text-gray-500">-</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<UButton color="primary" variant="outline"
|
|
||||||
class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) border-(--accent-blue-light) dark:border-(--accent-blue-dark)"
|
|
||||||
@click="goToCreateAccount">
|
|
||||||
<UIcon name="ic:sharp-edit" />
|
|
||||||
{{ t('Edit Account') }}
|
|
||||||
</UButton>
|
</UButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="flex flex-col gap-3">
|
||||||
|
<div class="grid grid-cols-2 gap-5">
|
||||||
|
<div
|
||||||
|
class="bg-(--second-light) dark:bg-(--main-dark) rounded-lg border border-(--border-light) dark:border-(--border-dark) p-4">
|
||||||
|
<h2 class="text-xl font-semibold text-black dark:text-white mb-4 flex items-center gap-2">
|
||||||
|
<UIcon name="mdi:domain"
|
||||||
|
class="text-[24px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
{{ t('Company Information') }}
|
||||||
|
</h2>
|
||||||
|
<div class="grid grid-cols-1 gap-10">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{ t('Company Name') }}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.companyName || '-'}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{
|
||||||
|
t('Company Email') }}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.companyEmail || '-'}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{ t('REGON')}}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.regon || '-' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('NIP')}}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.nip || '-' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-1">{{t('VAT')}}</label>
|
||||||
|
<p class="text-black dark:text-white">{{ customerStore.customer?.vat || '-' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2
|
||||||
|
class="text-xl font-semibold text-black dark:text-white mb-2 flex items-center gap-2">
|
||||||
|
<UIcon name="mdi:map-marker"
|
||||||
|
class="text-[24px] text-(--accent-blue-light) dark:text-(--accent-blue-dark)" />
|
||||||
|
{{ t('Addresses') }}
|
||||||
|
</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
class="block text-sm font-medium text-gray-500 dark:text-gray-400 mb-2">{{ t('Company Address') }}</label>
|
||||||
|
<div v-if="companyAddress"
|
||||||
|
class="p-4 bg-white dark:bg-(--black) rounded-md border border-(--border-light) dark:border-(--border-dark)">
|
||||||
|
<p class="text-black dark:text-white">{{ companyAddress.street }}</p>
|
||||||
|
<p class="text-black dark:text-white">{{ companyAddress.zipCode }},
|
||||||
|
{{ companyAddress.city }}</p>
|
||||||
|
<p class="text-black dark:text-white">{{ companyAddress.country }}</p>
|
||||||
|
</div>
|
||||||
|
<p v-else class="text-gray-400 dark:text-gray-500">-</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<UButton color="primary" variant="outline"
|
||||||
|
class="text-(--accent-blue-light) dark:text-(--accent-blue-dark) border-(--accent-blue-light) dark:border-(--accent-blue-dark)"
|
||||||
|
@click="goToCreateAccount">
|
||||||
|
<UIcon name="ic:sharp-edit" />
|
||||||
|
{{ t('Edit Account') }}
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<tr v-for="product in productsList" :key="product.product_id"
|
<tr v-for="product in productsList" :key="product.product_id"
|
||||||
class="hover:bg-gray-50 dark:hover:bg-gray-800">
|
class="hover:bg-gray-50 dark:hover:bg-gray-800">
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<img :src="getImageUrl(product.ImageID, product.LinkRewrite,)" alt="product image"
|
<img :src="product.ImageID" alt="product image"
|
||||||
class="w-16 h-16 object-cover rounded" />
|
class="w-16 h-16 object-cover rounded" />
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{
|
||||||
@@ -49,6 +49,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<div class="flex justify-center items-center py-8">
|
||||||
|
<UPagination v-model:page="page" :total="total" :page-size="perPage" />
|
||||||
|
</div>
|
||||||
<div v-if="productsList.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
|
<div v-if="productsList.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
|
||||||
No products found
|
No products found
|
||||||
</div>
|
</div>
|
||||||
@@ -59,17 +62,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, Suspense } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
import { useFetchJson } from '@/composable/useFetchJson'
|
import { useFetchJson } from '@/composable/useFetchJson'
|
||||||
import Default from '@/layouts/default.vue'
|
import Default from '@/layouts/default.vue'
|
||||||
// import CategoryMenu from '@/components/inner/categoryMenu.vue'
|
|
||||||
interface Product {
|
interface Product {
|
||||||
product_id: number
|
product_id: number
|
||||||
name: string
|
name: string
|
||||||
ImageID: number
|
ImageID: string
|
||||||
LinkRewrite: string
|
LinkRewrite: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const page = ref(1)
|
||||||
|
const perPage = ref(15)
|
||||||
|
const total = ref(0)
|
||||||
|
|
||||||
interface ApiResponse {
|
interface ApiResponse {
|
||||||
message: string
|
message: string
|
||||||
items: Product[]
|
items: Product[]
|
||||||
@@ -80,21 +87,26 @@ const productsList = ref<Product[]>([])
|
|||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
function getImageUrl(imageID: number, linkRewrite: string, size: string = 'small_default') {
|
|
||||||
return `https://www.naluconcept.com/${imageID}-${size}/${linkRewrite}.webp`
|
|
||||||
}
|
|
||||||
async function fetchProductList() {
|
async function fetchProductList() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await useFetchJson('/api/v1/restricted/list-products/get-listing?p&elems&shopID=1') as ApiResponse
|
const response = await useFetchJson(
|
||||||
|
`api/v1/restricted/list-products/get-listing?p=${page.value}&elems=${perPage.value}`
|
||||||
|
) as ApiResponse
|
||||||
|
|
||||||
productsList.value = response.items || []
|
productsList.value = response.items || []
|
||||||
|
total.value = response.count || 0
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
error.value = e instanceof Error ? e.message : 'Failed to load products'
|
error.value = e instanceof Error ? e.message : 'Failed to load products'
|
||||||
console.error(e)
|
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(page, () => {
|
||||||
|
fetchProductList()
|
||||||
|
})
|
||||||
onMounted(fetchProductList)
|
onMounted(fetchProductList)
|
||||||
</script>
|
</script>
|
||||||
@@ -238,7 +238,7 @@ const columns = computed<TableColumn<IssueTimeSummary>[]>(() => [
|
|||||||
</h2>
|
</h2>
|
||||||
<UTable :data="issues" :columns="columns" class="flex-1 dark:text-white! text-dark" />
|
<UTable :data="issues" :columns="columns" class="flex-1 dark:text-white! text-dark" />
|
||||||
<div class="pt-4 flex justify-center items-center dark:text-white! text-dark">
|
<div class="pt-4 flex justify-center items-center dark:text-white! text-dark">
|
||||||
<UPagination v-model:page="page" :total="totalItems" />
|
<UPagination v-model:page="page" :total="totalItems" :page-size="10" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user