added frontend for social + feed partiali working
This commit is contained in:
@@ -5,14 +5,18 @@
|
||||
*/
|
||||
|
||||
export type ApiSocialMessagesListParams = {
|
||||
/**
|
||||
* The pagination cursor value.
|
||||
*/
|
||||
cursor?: string;
|
||||
/**
|
||||
* Which field to use when ordering the results.
|
||||
*/
|
||||
ordering?: string;
|
||||
/**
|
||||
* A page number within the paginated result set.
|
||||
* Number of results to return per page.
|
||||
*/
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
/**
|
||||
* A search term.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Generated by orval v8.8.0 🍺
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
|
||||
export type ApiSocialPostsFeedListParams = {
|
||||
author?: number;
|
||||
/**
|
||||
* Opaque pagination cursor.
|
||||
*/
|
||||
cursor?: string;
|
||||
/**
|
||||
* Algorithm key, default `recent`.
|
||||
*/
|
||||
feed_strategy?: string;
|
||||
hub?: number;
|
||||
/**
|
||||
* Which field to use when ordering the results.
|
||||
*/
|
||||
ordering?: string;
|
||||
/**
|
||||
* A page number within the paginated result set.
|
||||
*/
|
||||
page?: number;
|
||||
reply_to?: number;
|
||||
/**
|
||||
* A search term.
|
||||
*/
|
||||
search?: string;
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Generated by orval v8.8.0 🍺
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
|
||||
export type ApiSocialPostsMediaCreateBody = {
|
||||
file: Blob;
|
||||
};
|
||||
20
frontend/src/api/generated/private/models/authorMinimal.ts
Normal file
20
frontend/src/api/generated/private/models/authorMinimal.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Generated by orval v8.8.0 🍺
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
|
||||
export interface AuthorMinimal {
|
||||
readonly id: number;
|
||||
/**
|
||||
* Požadováno. 150 znaků nebo méně. Pouze písmena, číslice a znaky @/./+/-/_.
|
||||
* @maxLength 150
|
||||
* @pattern ^[\w.@+-]+$
|
||||
*/
|
||||
username: string;
|
||||
/** @maxLength 150 */
|
||||
first_name?: string;
|
||||
/** @maxLength 150 */
|
||||
last_name?: string;
|
||||
readonly avatar: string;
|
||||
}
|
||||
@@ -42,4 +42,6 @@ export interface CustomUser {
|
||||
postal_code?: string | null;
|
||||
readonly gdpr: boolean;
|
||||
is_active?: boolean;
|
||||
/** @nullable */
|
||||
avatar?: string | null;
|
||||
}
|
||||
|
||||
@@ -26,8 +26,11 @@ export * from "./apiSocialHubsModeratorsListParams";
|
||||
export * from "./apiSocialHubsTagsListParams";
|
||||
export * from "./apiSocialChatsListParams";
|
||||
export * from "./apiSocialMessagesListParams";
|
||||
export * from "./apiSocialPostsFeedListParams";
|
||||
export * from "./apiSocialPostsListParams";
|
||||
export * from "./apiSocialPostsMediaCreateBody";
|
||||
export * from "./apiZasilkovnaShipmentsListParams";
|
||||
export * from "./authorMinimal";
|
||||
export * from "./callback";
|
||||
export * from "./carrierRead";
|
||||
export * from "./cart";
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import type { Message } from "./message";
|
||||
|
||||
export interface PaginatedMessageList {
|
||||
count: number;
|
||||
/** @nullable */
|
||||
next?: string | null;
|
||||
/** @nullable */
|
||||
|
||||
@@ -42,4 +42,6 @@ export interface PatchedCustomUser {
|
||||
postal_code?: string | null;
|
||||
readonly gdpr?: boolean;
|
||||
is_active?: boolean;
|
||||
/** @nullable */
|
||||
avatar?: string | null;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
import type { AuthorMinimal } from "./authorMinimal";
|
||||
import type { PostContent } from "./postContent";
|
||||
import type { Tags } from "./tags";
|
||||
|
||||
@@ -12,10 +13,14 @@ export interface PatchedPost {
|
||||
readonly created_at?: Date;
|
||||
readonly updated_at?: Date;
|
||||
readonly author?: number;
|
||||
readonly author_detail?: AuthorMinimal;
|
||||
/** @nullable */
|
||||
hub?: number | null;
|
||||
/** @nullable */
|
||||
reply_to?: number | null;
|
||||
readonly tags?: readonly Tags[];
|
||||
readonly contents?: readonly PostContent[];
|
||||
readonly vote_score?: string;
|
||||
readonly user_vote?: string;
|
||||
readonly reply_count?: number;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
import type { AuthorMinimal } from "./authorMinimal";
|
||||
import type { PostContent } from "./postContent";
|
||||
import type { Tags } from "./tags";
|
||||
|
||||
@@ -12,10 +13,14 @@ export interface Post {
|
||||
readonly created_at: Date;
|
||||
readonly updated_at: Date;
|
||||
readonly author: number;
|
||||
readonly author_detail: AuthorMinimal;
|
||||
/** @nullable */
|
||||
hub?: number | null;
|
||||
/** @nullable */
|
||||
reply_to?: number | null;
|
||||
readonly tags: readonly Tags[];
|
||||
readonly contents: readonly PostContent[];
|
||||
readonly vote_score: string;
|
||||
readonly user_vote: string;
|
||||
readonly reply_count: number;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,22 @@
|
||||
*/
|
||||
|
||||
export interface UserRegistration {
|
||||
/**
|
||||
* Užívatelské jméno
|
||||
* @maxLength 150
|
||||
* @pattern ^[\w.@+-]+$
|
||||
*/
|
||||
username?: string;
|
||||
/**
|
||||
* Křestní jméno uživatele
|
||||
* @maxLength 150
|
||||
*/
|
||||
first_name: string;
|
||||
first_name?: string;
|
||||
/**
|
||||
* Příjmení uživatele
|
||||
* @maxLength 150
|
||||
*/
|
||||
last_name: string;
|
||||
last_name?: string;
|
||||
/**
|
||||
* Emailová adresa uživatele
|
||||
* @maxLength 254
|
||||
@@ -26,7 +32,7 @@ export interface UserRegistration {
|
||||
* @nullable
|
||||
* @pattern ^\+?\d{9,15}$
|
||||
*/
|
||||
phone_number: string | null;
|
||||
phone_number?: string | null;
|
||||
/** Heslo musí mít alespoň 8 znaků, obsahovat velká a malá písmena a číslici. */
|
||||
password: string;
|
||||
/**
|
||||
@@ -34,20 +40,20 @@ export interface UserRegistration {
|
||||
* @maxLength 100
|
||||
* @nullable
|
||||
*/
|
||||
city: string | null;
|
||||
city?: string | null;
|
||||
/**
|
||||
* Ulice uživatele
|
||||
* @maxLength 200
|
||||
* @nullable
|
||||
*/
|
||||
street: string | null;
|
||||
street?: string | null;
|
||||
/**
|
||||
* PSČ uživatele
|
||||
* @maxLength 5
|
||||
* @nullable
|
||||
* @pattern ^\d{5}$
|
||||
*/
|
||||
postal_code: string | null;
|
||||
postal_code?: string | null;
|
||||
/** Souhlas se zpracováním osobních údajů */
|
||||
gdpr: boolean;
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ import type {
|
||||
} from "@tanstack/react-query";
|
||||
|
||||
import type {
|
||||
ApiSocialPostsFeedListParams,
|
||||
ApiSocialPostsListParams,
|
||||
ApiSocialPostsMediaCreateBody,
|
||||
PaginatedPostList,
|
||||
PatchedPost,
|
||||
Post,
|
||||
PostContent,
|
||||
PostVote,
|
||||
TagAttach,
|
||||
} from "../models";
|
||||
@@ -712,6 +715,97 @@ export const useApiSocialPostsDestroy = <TError = unknown, TContext = unknown>(
|
||||
queryClient,
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Attach an image or video file to a post. Only the post author can upload.
|
||||
* @summary Upload media to a post
|
||||
*/
|
||||
export const apiSocialPostsMediaCreate = (
|
||||
id: number,
|
||||
apiSocialPostsMediaCreateBody: ApiSocialPostsMediaCreateBody,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
const formData = new FormData();
|
||||
formData.append(`file`, apiSocialPostsMediaCreateBody.file);
|
||||
|
||||
return privateMutator<PostContent>({
|
||||
url: `/api/social/posts/${id}/media/`,
|
||||
method: "POST",
|
||||
data: formData,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getApiSocialPostsMediaCreateMutationOptions = <
|
||||
TError = unknown,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsMediaCreate>>,
|
||||
TError,
|
||||
{ id: number; data: ApiSocialPostsMediaCreateBody },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsMediaCreate>>,
|
||||
TError,
|
||||
{ id: number; data: ApiSocialPostsMediaCreateBody },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ["apiSocialPostsMediaCreate"];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
"mutationKey" in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof apiSocialPostsMediaCreate>>,
|
||||
{ id: number; data: ApiSocialPostsMediaCreateBody }
|
||||
> = (props) => {
|
||||
const { id, data } = props ?? {};
|
||||
|
||||
return apiSocialPostsMediaCreate(id, data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type ApiSocialPostsMediaCreateMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof apiSocialPostsMediaCreate>>
|
||||
>;
|
||||
export type ApiSocialPostsMediaCreateMutationBody =
|
||||
ApiSocialPostsMediaCreateBody;
|
||||
export type ApiSocialPostsMediaCreateMutationError = unknown;
|
||||
|
||||
/**
|
||||
* @summary Upload media to a post
|
||||
*/
|
||||
export const useApiSocialPostsMediaCreate = <
|
||||
TError = unknown,
|
||||
TContext = unknown,
|
||||
>(
|
||||
options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsMediaCreate>>,
|
||||
TError,
|
||||
{ id: number; data: ApiSocialPostsMediaCreateBody },
|
||||
TContext
|
||||
>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseMutationResult<
|
||||
Awaited<ReturnType<typeof apiSocialPostsMediaCreate>>,
|
||||
TError,
|
||||
{ id: number; data: ApiSocialPostsMediaCreateBody },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(
|
||||
getApiSocialPostsMediaCreateMutationOptions(options),
|
||||
queryClient,
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Attaches an existing hub tag to the post. The tag must belong to the same hub as the post. Any authenticated hub member can attach tags.
|
||||
* @summary Attach a tag to a post
|
||||
@@ -976,3 +1070,162 @@ export const useApiSocialPostsVoteCreate = <
|
||||
queryClient,
|
||||
);
|
||||
};
|
||||
/**
|
||||
* Returns a cursor-paginated stream of top-level posts (excluding replies) aggregated from the user's joined hubs, public hubs, and hub-less posts. Pass `feed_strategy` to switch between ranking algorithms (currently only `recent` is implemented; reserved for future custom algorithms).
|
||||
* @summary Get the user's post feed
|
||||
*/
|
||||
export const apiSocialPostsFeedList = (
|
||||
params?: ApiSocialPostsFeedListParams,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return privateMutator<PaginatedPostList>({
|
||||
url: `/api/social/posts/feed/`,
|
||||
method: "GET",
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getApiSocialPostsFeedListQueryKey = (
|
||||
params?: ApiSocialPostsFeedListParams,
|
||||
) => {
|
||||
return [`/api/social/posts/feed/`, ...(params ? [params] : [])] as const;
|
||||
};
|
||||
|
||||
export const getApiSocialPostsFeedListQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
params?: ApiSocialPostsFeedListParams,
|
||||
options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getApiSocialPostsFeedListQueryKey(params);
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>
|
||||
> = ({ signal }) => apiSocialPostsFeedList(params, signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: DataTag<QueryKey, TData, TError> };
|
||||
};
|
||||
|
||||
export type ApiSocialPostsFeedListQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>
|
||||
>;
|
||||
export type ApiSocialPostsFeedListQueryError = unknown;
|
||||
|
||||
export function useApiSocialPostsFeedList<
|
||||
TData = Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
params: undefined | ApiSocialPostsFeedListParams,
|
||||
options: {
|
||||
query: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
> &
|
||||
Pick<
|
||||
DefinedInitialDataOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>
|
||||
>,
|
||||
"initialData"
|
||||
>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): DefinedUseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
};
|
||||
export function useApiSocialPostsFeedList<
|
||||
TData = Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
params?: ApiSocialPostsFeedListParams,
|
||||
options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
> &
|
||||
Pick<
|
||||
UndefinedInitialDataOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>
|
||||
>,
|
||||
"initialData"
|
||||
>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
};
|
||||
export function useApiSocialPostsFeedList<
|
||||
TData = Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
params?: ApiSocialPostsFeedListParams,
|
||||
options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
};
|
||||
/**
|
||||
* @summary Get the user's post feed
|
||||
*/
|
||||
|
||||
export function useApiSocialPostsFeedList<
|
||||
TData = Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError = unknown,
|
||||
>(
|
||||
params?: ApiSocialPostsFeedListParams,
|
||||
options?: {
|
||||
query?: Partial<
|
||||
UseQueryOptions<
|
||||
Awaited<ReturnType<typeof apiSocialPostsFeedList>>,
|
||||
TError,
|
||||
TData
|
||||
>
|
||||
>;
|
||||
},
|
||||
queryClient?: QueryClient,
|
||||
): UseQueryResult<TData, TError> & {
|
||||
queryKey: DataTag<QueryKey, TData, TError>;
|
||||
} {
|
||||
const queryOptions = getApiSocialPostsFeedListQueryOptions(params, options);
|
||||
|
||||
const query = useQuery(queryOptions, queryClient) as UseQueryResult<
|
||||
TData,
|
||||
TError
|
||||
> & { queryKey: DataTag<QueryKey, TData, TError> };
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
20
frontend/src/api/generated/public/models/authorMinimal.ts
Normal file
20
frontend/src/api/generated/public/models/authorMinimal.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Generated by orval v8.8.0 🍺
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
|
||||
export interface AuthorMinimal {
|
||||
readonly id: number;
|
||||
/**
|
||||
* Požadováno. 150 znaků nebo méně. Pouze písmena, číslice a znaky @/./+/-/_.
|
||||
* @maxLength 150
|
||||
* @pattern ^[\w.@+-]+$
|
||||
*/
|
||||
username: string;
|
||||
/** @maxLength 150 */
|
||||
first_name?: string;
|
||||
/** @maxLength 150 */
|
||||
last_name?: string;
|
||||
readonly avatar: string;
|
||||
}
|
||||
@@ -42,4 +42,6 @@ export interface CustomUser {
|
||||
postal_code?: string | null;
|
||||
readonly gdpr: boolean;
|
||||
is_active?: boolean;
|
||||
/** @nullable */
|
||||
avatar?: string | null;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ export * from "./apiDownloaderDownloadRetrieveParams";
|
||||
export * from "./apiChoicesRetrieve200";
|
||||
export * from "./apiChoicesRetrieve200Item";
|
||||
export * from "./apiChoicesRetrieveParams";
|
||||
export * from "./authorMinimal";
|
||||
export * from "./callback";
|
||||
export * from "./carrierRead";
|
||||
export * from "./cart";
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import type { Message } from "./message";
|
||||
|
||||
export interface PaginatedMessageList {
|
||||
count: number;
|
||||
/** @nullable */
|
||||
next?: string | null;
|
||||
/** @nullable */
|
||||
|
||||
@@ -42,4 +42,6 @@ export interface PatchedCustomUser {
|
||||
postal_code?: string | null;
|
||||
readonly gdpr?: boolean;
|
||||
is_active?: boolean;
|
||||
/** @nullable */
|
||||
avatar?: string | null;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
import type { AuthorMinimal } from "./authorMinimal";
|
||||
import type { PostContent } from "./postContent";
|
||||
import type { Tags } from "./tags";
|
||||
|
||||
@@ -12,10 +13,14 @@ export interface PatchedPost {
|
||||
readonly created_at?: Date;
|
||||
readonly updated_at?: Date;
|
||||
readonly author?: number;
|
||||
readonly author_detail?: AuthorMinimal;
|
||||
/** @nullable */
|
||||
hub?: number | null;
|
||||
/** @nullable */
|
||||
reply_to?: number | null;
|
||||
readonly tags?: readonly Tags[];
|
||||
readonly contents?: readonly PostContent[];
|
||||
readonly vote_score?: string;
|
||||
readonly user_vote?: string;
|
||||
readonly reply_count?: number;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Do not edit manually.
|
||||
* OpenAPI spec version: 0.0.0
|
||||
*/
|
||||
import type { AuthorMinimal } from "./authorMinimal";
|
||||
import type { PostContent } from "./postContent";
|
||||
import type { Tags } from "./tags";
|
||||
|
||||
@@ -12,10 +13,14 @@ export interface Post {
|
||||
readonly created_at: Date;
|
||||
readonly updated_at: Date;
|
||||
readonly author: number;
|
||||
readonly author_detail: AuthorMinimal;
|
||||
/** @nullable */
|
||||
hub?: number | null;
|
||||
/** @nullable */
|
||||
reply_to?: number | null;
|
||||
readonly tags: readonly Tags[];
|
||||
readonly contents: readonly PostContent[];
|
||||
readonly vote_score: string;
|
||||
readonly user_vote: string;
|
||||
readonly reply_count: number;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,22 @@
|
||||
*/
|
||||
|
||||
export interface UserRegistration {
|
||||
/**
|
||||
* Užívatelské jméno
|
||||
* @maxLength 150
|
||||
* @pattern ^[\w.@+-]+$
|
||||
*/
|
||||
username?: string;
|
||||
/**
|
||||
* Křestní jméno uživatele
|
||||
* @maxLength 150
|
||||
*/
|
||||
first_name: string;
|
||||
first_name?: string;
|
||||
/**
|
||||
* Příjmení uživatele
|
||||
* @maxLength 150
|
||||
*/
|
||||
last_name: string;
|
||||
last_name?: string;
|
||||
/**
|
||||
* Emailová adresa uživatele
|
||||
* @maxLength 254
|
||||
@@ -26,7 +32,7 @@ export interface UserRegistration {
|
||||
* @nullable
|
||||
* @pattern ^\+?\d{9,15}$
|
||||
*/
|
||||
phone_number: string | null;
|
||||
phone_number?: string | null;
|
||||
/** Heslo musí mít alespoň 8 znaků, obsahovat velká a malá písmena a číslici. */
|
||||
password: string;
|
||||
/**
|
||||
@@ -34,20 +40,20 @@ export interface UserRegistration {
|
||||
* @maxLength 100
|
||||
* @nullable
|
||||
*/
|
||||
city: string | null;
|
||||
city?: string | null;
|
||||
/**
|
||||
* Ulice uživatele
|
||||
* @maxLength 200
|
||||
* @nullable
|
||||
*/
|
||||
street: string | null;
|
||||
street?: string | null;
|
||||
/**
|
||||
* PSČ uživatele
|
||||
* @maxLength 5
|
||||
* @nullable
|
||||
* @pattern ^\d{5}$
|
||||
*/
|
||||
postal_code: string | null;
|
||||
postal_code?: string | null;
|
||||
/** Souhlas se zpracováním osobních údajů */
|
||||
gdpr: boolean;
|
||||
}
|
||||
|
||||
75
frontend/src/api/social/feed.ts
Normal file
75
frontend/src/api/social/feed.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Hand-written wrappers for endpoints not yet picked up by orval regen.
|
||||
* Run `npm run api:gen` after running the backend to migrate to the generated client.
|
||||
*/
|
||||
import { privateMutator } from "../privateClient";
|
||||
import type { Post } from "../generated/private/models/post";
|
||||
import type { Message } from "../generated/private/models/message";
|
||||
|
||||
export interface CursorPaginated<T> {
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: T[];
|
||||
}
|
||||
|
||||
export type FeedStrategy = "recent";
|
||||
|
||||
export interface FeedParams {
|
||||
cursor?: string | null;
|
||||
feed_strategy?: FeedStrategy;
|
||||
page_size?: number;
|
||||
}
|
||||
|
||||
export const apiSocialPostsFeed = (
|
||||
params?: FeedParams,
|
||||
signal?: AbortSignal,
|
||||
) =>
|
||||
privateMutator<CursorPaginated<Post>>({
|
||||
url: `/api/social/posts/feed/`,
|
||||
method: "GET",
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
|
||||
export const feedQueryKey = (params?: Omit<FeedParams, "cursor">) =>
|
||||
["social", "posts", "feed", params ?? {}] as const;
|
||||
|
||||
export interface RepliesParams {
|
||||
reply_to: number;
|
||||
cursor?: string | null;
|
||||
page_size?: number;
|
||||
}
|
||||
|
||||
export const apiSocialPostReplies = (
|
||||
params: RepliesParams,
|
||||
signal?: AbortSignal,
|
||||
) =>
|
||||
privateMutator<CursorPaginated<Post>>({
|
||||
url: `/api/social/posts/`,
|
||||
method: "GET",
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
|
||||
export const repliesQueryKey = (postId: number) =>
|
||||
["social", "posts", "replies", postId] as const;
|
||||
|
||||
export interface MessagesParams {
|
||||
chat: number;
|
||||
cursor?: string | null;
|
||||
page_size?: number;
|
||||
}
|
||||
|
||||
export const apiSocialMessagesCursor = (
|
||||
params: MessagesParams,
|
||||
signal?: AbortSignal,
|
||||
) =>
|
||||
privateMutator<CursorPaginated<Message>>({
|
||||
url: `/api/social/messages/`,
|
||||
method: "GET",
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
|
||||
export const messagesQueryKey = (chatId: number) =>
|
||||
["social", "messages", chatId] as const;
|
||||
23
frontend/src/api/social/ws.ts
Normal file
23
frontend/src/api/social/ws.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Derives the WebSocket base URL from env. Mirrors the BE Channels routing,
|
||||
* which lives behind the same host as the REST API.
|
||||
*
|
||||
* Set `VITE_WS_URL` to override (e.g. wss://example.com); otherwise we flip the
|
||||
* scheme of `VITE_BACKEND_URL`.
|
||||
*/
|
||||
export function getChatSocketUrl(chatId: number | string): string {
|
||||
const explicit = import.meta.env.VITE_WS_URL as string | undefined;
|
||||
if (explicit) {
|
||||
return `${stripTrailing(explicit)}/ws/chat/${chatId}/`;
|
||||
}
|
||||
const backend = (import.meta.env.VITE_BACKEND_URL as string | undefined)
|
||||
?? "http://localhost:8000";
|
||||
const wsBase = backend.replace(/^http/, "ws");
|
||||
// WS endpoints live at the host root (/ws/chat/<id>/), not under /api/.
|
||||
const hostOnly = wsBase.replace(/\/api\/?$/, "");
|
||||
return `${stripTrailing(hostOnly)}/ws/chat/${chatId}/`;
|
||||
}
|
||||
|
||||
function stripTrailing(s: string): string {
|
||||
return s.endsWith("/") ? s.slice(0, -1) : s;
|
||||
}
|
||||
Reference in New Issue
Block a user