@recruitnepal/shared-packages 1.8.3 → 1.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ export type JobsSearchBarFilter = {
2
+ keyword: string;
3
+ location: string;
4
+ category: string[];
5
+ };
6
+ export type JobsSearchBarProps = {
7
+ /** Read URL/search state (e.g. from useSearchParams().get in Next) */
8
+ getSearchParam: (key: string) => string | null;
9
+ /** Called when filter changes (debounced in live mode) */
10
+ handleSearch: (filter: JobsSearchBarFilter) => void;
11
+ /** In submit mode, Search button calls this with current filter so parent can navigate */
12
+ onSubmitSearch?: (filter: JobsSearchBarFilter) => void;
13
+ mode?: 'live' | 'submit';
14
+ hideCategory?: boolean;
15
+ presetCategory?: string;
16
+ showPopularSearch?: boolean;
17
+ /** Optional auth token for categories API (when publicFetch is false) */
18
+ token?: string | null;
19
+ /** Optional className for the wrapper */
20
+ className?: string;
21
+ };
22
+ export declare function JobsSearchBar({ getSearchParam, handleSearch, onSubmitSearch, mode, hideCategory, presetCategory, showPopularSearch, token, className, }: JobsSearchBarProps): import("react/jsx-runtime").JSX.Element;
23
+ export default JobsSearchBar;
24
+ //# sourceMappingURL=JobsSearchBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobsSearchBar.d.ts","sourceRoot":"","sources":["../../src/components/JobsSearchBar.tsx"],"names":[],"mappings":"AAkBA,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,sEAAsE;IACtE,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC/C,0DAA0D;IAC1D,YAAY,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACpD,0FAA0F;IAC1F,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAOF,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,YAAY,EACZ,cAAc,EACd,IAAa,EACb,YAAoB,EACpB,cAAc,EACd,iBAAyB,EACzB,KAAK,EACL,SAAS,GACV,EAAE,kBAAkB,2CAuKpB;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,85 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useMemo, useRef, useState } from 'react';
4
+ import { Check, MapPin, Search } from 'lucide-react';
5
+ import { Button } from './ui/Button';
6
+ import { Input } from './ui/Input';
7
+ import { cn } from '../utils/cn';
8
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogTrigger, } from './ui/Dialog';
9
+ import { useVacancyCategories } from '../hooks/useVacancyCategories';
10
+ /** Display label for a category (Recruit uses title, Intern may use name) */
11
+ function categoryLabel(c) {
12
+ return String(c.title ?? c.name ?? '').trim() || '—';
13
+ }
14
+ export function JobsSearchBar({ getSearchParam, handleSearch, onSubmitSearch, mode = 'live', hideCategory = false, presetCategory, showPopularSearch = false, token, className, }) {
15
+ const [searchQuery, setSearchQuery] = useState({
16
+ keyword: getSearchParam('query') || '',
17
+ location: getSearchParam('location') || '',
18
+ category: (getSearchParam('category') || '').split(',').map((s) => s.trim()).filter(Boolean),
19
+ });
20
+ const [catOpen, setCatOpen] = useState(false);
21
+ const [catQuery, setCatQuery] = useState('');
22
+ const { categories = [], isLoading: isCatsLoading } = useVacancyCategories({
23
+ publicFetch: true,
24
+ limit: 200,
25
+ token,
26
+ });
27
+ useEffect(() => {
28
+ if (!presetCategory)
29
+ return;
30
+ setSearchQuery((prev) => (prev.category[0] === presetCategory ? prev : { ...prev, category: [presetCategory] }));
31
+ }, [presetCategory]);
32
+ useEffect(() => {
33
+ const q = getSearchParam('query') || '';
34
+ const loc = getSearchParam('location') || '';
35
+ const cat = getSearchParam('category') || '';
36
+ const nextCat = presetCategory ? [presetCategory] : (cat ? cat.split(',').map((s) => s.trim()).filter(Boolean) : []);
37
+ setSearchQuery((prev) => {
38
+ if (prev.keyword === q && prev.location === loc && prev.category.join(',') === nextCat.join(','))
39
+ return prev;
40
+ return { keyword: q, location: loc, category: nextCat };
41
+ });
42
+ }, [getSearchParam('query'), getSearchParam('location'), getSearchParam('category'), presetCategory]);
43
+ const latestSearchFnRef = useRef(handleSearch);
44
+ const latestStateRef = useRef(searchQuery);
45
+ useEffect(() => {
46
+ latestSearchFnRef.current = handleSearch;
47
+ }, [handleSearch]);
48
+ useEffect(() => {
49
+ latestStateRef.current = searchQuery;
50
+ if (mode !== 'live')
51
+ return;
52
+ const t = window.setTimeout(() => latestSearchFnRef.current(latestStateRef.current), 500);
53
+ return () => window.clearTimeout(t);
54
+ }, [searchQuery, mode]);
55
+ const onChangeField = (e) => {
56
+ const { name, value } = e.target;
57
+ setSearchQuery((prev) => ({ ...prev, [name]: value }));
58
+ };
59
+ const canChangeCategory = !presetCategory;
60
+ const toggleCategory = (title) => {
61
+ setSearchQuery((prev) => {
62
+ if (!canChangeCategory)
63
+ return prev;
64
+ const current = prev.category[0];
65
+ return { ...prev, category: current === title ? [] : [title] };
66
+ });
67
+ };
68
+ const clearCategory = () => setSearchQuery((p) => ({ ...p, category: presetCategory ? [presetCategory] : [] }));
69
+ const norm = (s) => s.trim().toLowerCase();
70
+ const filteredCategories = useMemo(() => {
71
+ if (!catQuery.trim())
72
+ return categories;
73
+ return categories.filter((c) => norm(categoryLabel(c)).includes(norm(catQuery)));
74
+ }, [categories, catQuery]);
75
+ const submitSearch = () => {
76
+ if (onSubmitSearch)
77
+ onSubmitSearch(searchQuery);
78
+ };
79
+ return (_jsxs("div", { className: cn('w-full max-w-6xl mx-auto p-2 pt-0', className), children: [_jsxs("div", { className: "border rounded-xl bg-white flex items-center", children: [_jsxs("div", { className: "relative flex-1 p-2", children: [_jsx(Search, { className: "absolute left-5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { name: "keyword", placeholder: "Job title, keywords or company", value: searchQuery.keyword, onChange: onChangeField, className: "pl-8 py-0 border-0 h-9" })] }), _jsxs("div", { className: "relative flex-1 p-2 hidden md:block", children: [_jsx(MapPin, { className: "absolute left-5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { name: "location", placeholder: "City, Location", value: searchQuery.location, onChange: onChangeField, className: "pl-8 py-0 border-0 h-9" })] }), !hideCategory && (_jsx("div", { className: "p-2 hidden md:block", children: _jsxs(Dialog, { open: catOpen, onOpenChange: setCatOpen, children: [_jsx(DialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", className: "text-sm w-full md:w-[260px] justify-between h-9", children: searchQuery.category.length === 0 ? 'Category' : searchQuery.category[0] }) }), _jsxs(DialogContent, { className: "max-w-[900px] w-[92vw] p-0 overflow-hidden", children: [_jsx(DialogHeader, { className: "p-4 pb-2", children: _jsx(DialogTitle, { children: "Select a Category" }) }), _jsx("div", { className: "px-4 pb-4", children: _jsx(Input, { placeholder: "Search category\u2026", value: catQuery, onChange: (e) => setCatQuery(e.target.value), className: "h-9" }) }), _jsx("div", { className: "max-h-[60vh] overflow-y-auto px-4 pb-2", children: isCatsLoading ? (_jsx("div", { className: "text-sm text-muted-foreground px-1 py-6", children: "Loading\u2026" })) : filteredCategories.length === 0 ? (_jsx("div", { className: "text-sm text-muted-foreground px-1 py-6", children: "No category found." })) : (_jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2", children: filteredCategories.map((c) => {
80
+ const title = categoryLabel(c);
81
+ const selected = searchQuery.category[0] === title;
82
+ return (_jsx("button", { type: "button", onClick: () => toggleCategory(title), className: cn('text-left text-sm px-3 py-2 rounded-lg border transition', selected ? 'border-primary bg-primary/10 text-primary' : 'hover:bg-muted/60'), children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate", children: title }), _jsx(Check, { className: cn('ml-auto h-4 w-4', selected ? 'opacity-100' : 'opacity-0') })] }) }, title));
83
+ }) })) }), _jsxs(DialogFooter, { className: "p-4 border-t flex items-center justify-between", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: clearCategory, children: "Clear" }), _jsx(Button, { size: "sm", onClick: () => setCatOpen(false), children: "Done" })] })] })] }) })), mode === 'submit' && (_jsx("div", { className: "p-2", children: _jsx(Button, { onClick: submitSearch, children: "Search" }) }))] }), showPopularSearch && mode === 'live' && (_jsx("div", { className: "hidden md:block" }))] }));
84
+ }
85
+ export default JobsSearchBar;
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
3
+ declare const Dialog: React.FC<DialogPrimitive.DialogProps>;
4
+ declare const DialogTrigger: React.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
5
+ declare const DialogPortal: React.FC<DialogPrimitive.DialogPortalProps>;
6
+ declare const DialogClose: React.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
7
+ declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
8
+ declare const DialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
9
+ declare const DialogHeader: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element;
10
+ declare const DialogFooter: ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => import("react/jsx-runtime").JSX.Element;
11
+ declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
12
+ export { Dialog, DialogTrigger, DialogPortal, DialogClose, DialogOverlay, DialogContent, DialogHeader, DialogFooter, DialogTitle, };
13
+ //# sourceMappingURL=Dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAG1D,QAAA,MAAM,MAAM,uCAAuB,CAAC;AACpC,QAAA,MAAM,aAAa,8GAA0B,CAAC;AAC9C,QAAA,MAAM,YAAY,6CAAyB,CAAC;AAC5C,QAAA,MAAM,WAAW,4GAAwB,CAAC;AAE1C,QAAA,MAAM,aAAa,8JAYjB,CAAC;AAGH,QAAA,MAAM,aAAa,8JAiBjB,CAAC;AAGH,QAAA,MAAM,YAAY,GAAI,yBAAyB,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,4CAElF,CAAC;AACF,QAAA,MAAM,YAAY,GAAI,yBAAyB,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,4CAElF,CAAC;AACF,QAAA,MAAM,WAAW,oKAKf,CAAC;AAGH,OAAO,EACL,MAAM,EACN,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,CAAC"}
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
5
+ import { cn } from '../../utils/cn';
6
+ const Dialog = DialogPrimitive.Root;
7
+ const DialogTrigger = DialogPrimitive.Trigger;
8
+ const DialogPortal = DialogPrimitive.Portal;
9
+ const DialogClose = DialogPrimitive.Close;
10
+ const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn('fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', className), ...props })));
11
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
12
+ const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsx(DialogPrimitive.Content, { ref: ref, className: cn('fixed left-[50%] top-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:max-w-lg', className), ...props, children: children })] })));
13
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
14
+ const DialogHeader = ({ className, ...props }) => (_jsx("div", { className: cn('flex flex-col gap-2 text-center sm:text-left', className), ...props }));
15
+ const DialogFooter = ({ className, ...props }) => (_jsx("div", { className: cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className), ...props }));
16
+ const DialogTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Title, { ref: ref, className: cn('text-lg font-semibold leading-none', className), ...props })));
17
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
18
+ export { Dialog, DialogTrigger, DialogPortal, DialogClose, DialogOverlay, DialogContent, DialogHeader, DialogFooter, DialogTitle, };
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
3
+ className?: string;
4
+ }
5
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
6
+ export { Input };
7
+ //# sourceMappingURL=Input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Input.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,WAAW,UAAW,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,KAAK,qFAYV,CAAC;AAGF,OAAO,EAAE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { cn } from '../../utils/cn';
5
+ const Input = React.forwardRef(({ className, type = 'text', ...props }, ref) => (_jsx("input", { type: type, ref: ref, className: cn('flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', className), ...props })));
6
+ Input.displayName = 'Input';
7
+ export { Input };
@@ -5,7 +5,7 @@ declare const Command: React.ForwardRefExoticComponent<Omit<{
5
5
  ref?: React.Ref<HTMLDivElement>;
6
6
  } & {
7
7
  asChild?: boolean;
8
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
8
+ }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
9
9
  label?: string;
10
10
  shouldFilter?: boolean;
11
11
  filter?: (value: string, search: string, keywords?: string[]) => number;
@@ -20,7 +20,7 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
20
20
  ref?: React.Ref<HTMLInputElement>;
21
21
  } & {
22
22
  asChild?: boolean;
23
- }, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "value" | "onChange"> & {
23
+ }, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "value" | "onChange"> & {
24
24
  value?: string;
25
25
  onValueChange?: (search: string) => void;
26
26
  } & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
@@ -30,7 +30,7 @@ declare const CommandList: React.ForwardRefExoticComponent<Omit<{
30
30
  ref?: React.Ref<HTMLDivElement>;
31
31
  } & {
32
32
  asChild?: boolean;
33
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
33
+ }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
34
34
  label?: string;
35
35
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
36
36
  declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
@@ -39,14 +39,14 @@ declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
39
39
  ref?: React.Ref<HTMLDivElement>;
40
40
  } & {
41
41
  asChild?: boolean;
42
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
42
+ }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
43
43
  declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
44
44
  children?: React.ReactNode;
45
45
  } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
46
46
  ref?: React.Ref<HTMLDivElement>;
47
47
  } & {
48
48
  asChild?: boolean;
49
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "value" | "heading"> & {
49
+ }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "value" | "heading"> & {
50
50
  heading?: React.ReactNode;
51
51
  value?: string;
52
52
  forceMount?: boolean;
@@ -57,7 +57,7 @@ declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
57
57
  ref?: React.Ref<HTMLDivElement>;
58
58
  } & {
59
59
  asChild?: boolean;
60
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "value" | "disabled" | "onSelect"> & {
60
+ }, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "value" | "disabled" | "onSelect"> & {
61
61
  disabled?: boolean;
62
62
  onSelect?: (value: string) => void;
63
63
  value?: string;
@@ -0,0 +1,18 @@
1
+ import type { VacancyCategory } from '../types/vacancy-category';
2
+ export type UseVacancyCategoriesParams = {
3
+ limit?: number;
4
+ queryObject?: Record<string, unknown>;
5
+ maxPages?: number;
6
+ /** If true, fetch without auth (public). If false, use token when provided. */
7
+ publicFetch?: boolean;
8
+ /** Optional auth token (e.g. from app session). When publicFetch is true, this is ignored. */
9
+ token?: string | null;
10
+ };
11
+ export declare function useVacancyCategories({ limit, queryObject, maxPages, publicFetch, token, }?: UseVacancyCategoriesParams): {
12
+ categories: VacancyCategory[];
13
+ isLoading: boolean;
14
+ isError: boolean;
15
+ error: Error | null;
16
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<VacancyCategory[], Error>>;
17
+ };
18
+ //# sourceMappingURL=useVacancyCategories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVacancyCategories.d.ts","sourceRoot":"","sources":["../../src/hooks/useVacancyCategories.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,2BAA2B,CAAC;AAiBxF,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EACnC,KAAW,EACX,WAAgB,EAChB,QAAQ,EACR,WAAkB,EAClB,KAAK,GACN,GAAE,0BAA+B;;;;;;EAgDjC"}
@@ -0,0 +1,61 @@
1
+ 'use client';
2
+ import { useQuery } from '@tanstack/react-query';
3
+ import { apiRequest } from '../utils/api-request';
4
+ import { generateSearchQuery } from '../utils/generateSearchQuery';
5
+ const coerceCategory = (c) => ({
6
+ id: c?.id != null ? (typeof c.id === 'number' ? c.id : String(c.id)) : undefined,
7
+ title: c?.title != null ? String(c.title) : undefined,
8
+ name: c?.name != null ? String(c.name) : undefined,
9
+ description: c?.description != null ? String(c.description) : undefined,
10
+ });
11
+ function mapResponse(res) {
12
+ const body = res.data;
13
+ const raw = body?.data?.data ?? [];
14
+ const items = raw.map((c) => coerceCategory(c));
15
+ const nextPage = body?.data?.pagination?.nextPage ?? null;
16
+ return { items, nextPage };
17
+ }
18
+ export function useVacancyCategories({ limit = 200, queryObject = {}, maxPages, publicFetch = true, token, } = {}) {
19
+ const getVacancyCategories = useQuery({
20
+ queryKey: ['vacancy-categories', 'all', { limit, queryObject, maxPages, publicFetch }],
21
+ enabled: publicFetch || !!token,
22
+ queryFn: async () => {
23
+ let nextPage = 1;
24
+ let pagesFetched = 0;
25
+ const all = [];
26
+ while (nextPage) {
27
+ const page = nextPage;
28
+ const searchQuery = generateSearchQuery({ ...queryObject, page, limit });
29
+ const res = await apiRequest({
30
+ endpoint: `/vacancy/categories?${searchQuery}`,
31
+ method: 'GET',
32
+ token: publicFetch ? undefined : token ?? undefined,
33
+ });
34
+ if (!res.success) {
35
+ const errs = res.errors;
36
+ const firstMsg = errs && Object.values(errs).flat()[0];
37
+ throw new Error(firstMsg || 'Failed to fetch categories');
38
+ }
39
+ const { items, nextPage: apiNext } = mapResponse(res);
40
+ if (items.length)
41
+ all.push(...items);
42
+ pagesFetched += 1;
43
+ if (maxPages && pagesFetched >= maxPages) {
44
+ nextPage = null;
45
+ }
46
+ else {
47
+ nextPage = apiNext ?? null;
48
+ }
49
+ }
50
+ return all;
51
+ },
52
+ staleTime: 60 * 60 * 1000,
53
+ });
54
+ return {
55
+ categories: getVacancyCategories.data ?? [],
56
+ isLoading: getVacancyCategories.isLoading,
57
+ isError: getVacancyCategories.isError,
58
+ error: getVacancyCategories.error,
59
+ refetch: getVacancyCategories.refetch,
60
+ };
61
+ }
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export type { SavedVacancyItem, SavedVacancyApiResponse, SavedVacancyPayload, }
5
5
  export type { Question, AnswerOption, VacancyQuestionsResponse, } from './types/questions';
6
6
  export { WORKSTATUS, WORK_STATUS_VALUES, } from './types/easy-apply';
7
7
  export type { WorkStatusValue, QuestionsAPIRes, ScreeningAnswersApiResNew, } from './types/easy-apply';
8
+ export type { VacancyCategory, VacancyCategoryAPIRes } from './types/vacancy-category';
8
9
  export { apiRequest } from './utils/api-request';
9
10
  export type { ApiResponse } from './utils/api-request';
10
11
  export { cn } from './utils/cn';
@@ -16,6 +17,8 @@ export { useDesignations } from './hooks/useDesignations';
16
17
  export type { Designation, DesignationPayload, UseDesignationsParams } from './hooks/useDesignations';
17
18
  export { useSkills } from './hooks/useSkills';
18
19
  export type { Skill, UseSkillsParams } from './hooks/useSkills';
20
+ export { useVacancyCategories } from './hooks/useVacancyCategories';
21
+ export type { UseVacancyCategoriesParams } from './hooks/useVacancyCategories';
19
22
  export { useGetAllVacancy } from './hooks/useGetAllVacancy';
20
23
  export { default as useGetAllVacancyDefault } from './hooks/useGetAllVacancy';
21
24
  export { useSavedVacancyMutations } from './hooks/useSavedVacancyMutations';
@@ -32,10 +35,15 @@ export { default as JobsClient } from './components/JobsClient';
32
35
  export type { JobsClientProps } from './components/JobsClient';
33
36
  export { default as JobDescriptionClient } from './components/JobDescriptionClient';
34
37
  export type { JobDescriptionClientProps } from './components/JobDescriptionClient';
38
+ export { JobsSearchBar, default as JobsSearchBarDefault } from './components/JobsSearchBar';
39
+ export type { JobsSearchBarProps, JobsSearchBarFilter } from './components/JobsSearchBar';
35
40
  export { RatingStars } from './components/ui/RatingStars';
36
41
  export { default as IndustrySelect } from './components/ui/IndustrySelect';
37
42
  export { default as DesignationSelect } from './components/ui/DesignationSelect';
38
43
  export { MultiSelectOptions } from './components/ui/MultiSelectOptions';
39
44
  export type { MultiSelectOptionsProps } from './components/ui/MultiSelectOptions';
45
+ export { Input } from './components/ui/Input';
46
+ export type { InputProps } from './components/ui/Input';
47
+ export { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, } from './components/ui/Dialog';
40
48
  export * from './career-personality-test';
41
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ export { useDebounce } from './hooks/useDebounce';
10
10
  export { useIndustries } from './hooks/useIndustries';
11
11
  export { useDesignations } from './hooks/useDesignations';
12
12
  export { useSkills } from './hooks/useSkills';
13
+ export { useVacancyCategories } from './hooks/useVacancyCategories';
13
14
  // Hooks
14
15
  export { useGetAllVacancy } from './hooks/useGetAllVacancy';
15
16
  export { default as useGetAllVacancyDefault } from './hooks/useGetAllVacancy';
@@ -24,10 +25,13 @@ export { useEasyApplyFormHook, easyApplyUserSchema, screeningAnswerSchema, scree
24
25
  // Components
25
26
  export { default as JobsClient } from './components/JobsClient';
26
27
  export { default as JobDescriptionClient } from './components/JobDescriptionClient';
28
+ export { JobsSearchBar, default as JobsSearchBarDefault } from './components/JobsSearchBar';
27
29
  // UI Components
28
30
  export { RatingStars } from './components/ui/RatingStars';
29
31
  export { default as IndustrySelect } from './components/ui/IndustrySelect';
30
32
  export { default as DesignationSelect } from './components/ui/DesignationSelect';
31
33
  export { MultiSelectOptions } from './components/ui/MultiSelectOptions';
34
+ export { Input } from './components/ui/Input';
35
+ export { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, } from './components/ui/Dialog';
32
36
  // Career Personality Test
33
37
  export * from './career-personality-test';
@@ -0,0 +1,19 @@
1
+ /** Vacancy category (from /vacancy/categories API) - supports both title (Recruit) and name (Intern) */
2
+ export interface VacancyCategory {
3
+ id?: string | number;
4
+ title?: string;
5
+ name?: string;
6
+ description?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ /** API response shape for paginated categories */
10
+ export interface VacancyCategoryAPIRes {
11
+ data?: {
12
+ data?: VacancyCategory[];
13
+ pagination?: {
14
+ nextPage?: number;
15
+ };
16
+ };
17
+ [key: string]: unknown;
18
+ }
19
+ //# sourceMappingURL=vacancy-category.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vacancy-category.d.ts","sourceRoot":"","sources":["../../src/types/vacancy-category.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE;QACL,IAAI,CAAC,EAAE,eAAe,EAAE,CAAC;QACzB,UAAU,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KACpC,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recruitnepal/shared-packages",
3
- "version": "1.8.3",
3
+ "version": "1.8.4",
4
4
  "description": "Shared hooks, API client, types and utils for Recruit Nepal (CV builder UI and preprocess stay in each repo)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,6 +29,7 @@
29
29
  "tailwind-merge": "^2.5.0",
30
30
  "cmdk": "^1.0.0",
31
31
  "class-variance-authority": "^0.7.0",
32
+ "@radix-ui/react-dialog": "^1.0.5",
32
33
  "@radix-ui/react-popover": "^1.1.0",
33
34
  "@radix-ui/react-slot": "^1.1.0",
34
35
  "react-intersection-observer": "^9.16.0",
@@ -41,6 +42,7 @@
41
42
  "lucide-react": "^0.460.0",
42
43
  "cmdk": "^1.0.0",
43
44
  "class-variance-authority": "^0.7.0",
45
+ "@radix-ui/react-dialog": "^1.0.5",
44
46
  "@radix-ui/react-popover": "^1.1.0",
45
47
  "@radix-ui/react-slot": "^1.1.0",
46
48
  "react-intersection-observer": "^9.16.0",