six-degrees 0.2.1 → 0.3.0
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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +10 -0
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +39 -11
- package/.next/standalone/.next/required-server-files.json +4 -1
- package/.next/standalone/.next/routes-manifest.json +60 -0
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +9 -9
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/admin-delete/route.js +3 -2
- package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/admin-update/route.js +3 -2
- package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/bridges/route.js +3 -2
- package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/bulk-import/route.js +3 -2
- package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +9 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/company-scores/route.js +3 -2
- package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/connections/route.js +3 -2
- package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/export/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/export/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/export/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/export/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/export/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/export/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/import/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/import/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/import/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/import/route.js +8 -0
- package/.next/standalone/.next/server/app/api/data/import/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/import/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/restart/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/restart/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/restart/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/restart/route.js +8 -0
- package/.next/standalone/.next/server/app/api/data/restart/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/restart/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/reveal/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/data/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/data/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/data/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/data/route.js +7 -0
- package/.next/standalone/.next/server/app/api/data/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/data/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/delete-cluster/route.js +3 -2
- package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ingest/route.js +2 -2
- package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/route.js +3 -2
- package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route.js +3 -2
- package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/outreach/route.js +3 -2
- package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/queue/route.js +3 -2
- package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/scraper/route.js +3 -2
- package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/settings/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/settings/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/settings/route.js +9 -0
- package/.next/standalone/.next/server/app/api/settings/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/settings/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +8 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +8 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/setup-profile/route.js +3 -2
- package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/unlock/route.js +3 -2
- package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/update/route.js +1 -1
- package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/update-images/route.js +3 -2
- package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/users/route.js +3 -2
- package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/avatars/[file]/route.js +2 -1
- package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/favicon.ico/route.js +2 -1
- package/.next/standalone/.next/server/app/favicon.ico/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/import.html +1 -1
- package/.next/standalone/.next/server/app/import.rsc +12 -12
- package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +12 -12
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/launch.html +2 -2
- package/.next/standalone/.next/server/app/launch.rsc +12 -12
- package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/paths.html +1 -1
- package/.next/standalone/.next/server/app/paths.rsc +12 -12
- package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/profile.html +1 -1
- package/.next/standalone/.next/server/app/profile.rsc +12 -12
- package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/queue.html +1 -1
- package/.next/standalone/.next/server/app/queue.rsc +12 -12
- package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +20 -0
- package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +11 -0
- package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/settings/page.js +13 -0
- package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/settings.html +1 -0
- package/.next/standalone/.next/server/app/settings.meta +26 -0
- package/.next/standalone/.next/server/app/settings.rsc +24 -0
- package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +24 -0
- package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +4 -0
- package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +28 -0
- package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup.html +1 -1
- package/.next/standalone/.next/server/app/setup.rsc +12 -12
- package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +11 -11
- package/.next/standalone/.next/server/app-paths-manifest.json +10 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0i5hdu4._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljcioj._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0uag-k5._.js +8 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0um1uey._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +8 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1t3rugi._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +3 -0
- package/.next/standalone/.next/server/chunks/_072jl0y._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1_fynia._.js +21 -3
- package/.next/standalone/.next/server/chunks/_1fn30_l._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1itd1o_._.js +2 -1
- package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1mxn_lb._.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_company-scores_legacy_route_actions_1ncspu_.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_export_route_actions_1lkimty.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_import_route_actions_1eji0kd.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restart_route_actions_00_-u6o.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_reveal_route_actions_0-moqtn.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_route_actions_0j0w5ep.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_route_actions_1bpm9ac.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_sector-preview_route_actions_0w79454.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_sector-suggestions_route_actions_1eoqugp.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +155 -0
- package/.next/standalone/.next/server/chunks/{lib_rpc_0mc73lk.js → lib_rpc_00tx2sm.js} +1 -1
- package/.next/standalone/.next/server/chunks/lib_rpc_02-qa4d.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_02ndsg2.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_08q5vp6.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0_8i3ft.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +5 -2
- package/.next/standalone/.next/server/chunks/lib_rpc_0huvw-3.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0ip2vdh.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0jzisgh.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0yi9xvd.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1jyhd0o.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1kn59-i.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1q2jkza.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1vpm1sk.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1x6p_31.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_1zc5q0a._.js +158 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0mocm6d._.js → [root-of-the-server]__0an6blh._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m0255u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0bipr5s._.js → [root-of-the-server]__1z1j3ek._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_07u8byv._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_08r_mlf._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_0ggabjc._.js → _0942v8n._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1djpk8t._.js → _0hl_t7r._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0tb83dw._.js +132 -0
- package/.next/standalone/.next/server/chunks/ssr/_1-87bs1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_17gui6a._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_settings_page_actions_11x4dq5.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +4 -4
- package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +5 -5
- package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/lib_0i8v-s3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1f8t_rp._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1nkgb45._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_01xbj_9._.js → node_modules_1wax83z._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_00nap8h._.js → node_modules_next_dist_1bunoni._.js} +2 -2
- package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +2 -2
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +15 -7
- package/.next/standalone/.next/server/next-font-manifest.js +1 -1
- package/.next/standalone/.next/server/next-font-manifest.json +4 -0
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/prefetch-hints.json +14 -0
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/06x3jiiz96m5t.js +1 -0
- package/.next/standalone/.next/static/chunks/{34at5d2ifl62i.js → 0ngx9s6-zgshe.js} +5 -5
- package/.next/standalone/.next/static/chunks/0q-_khndfxubv.js +2 -0
- package/.next/standalone/.next/static/chunks/1c79veqedvubt.js +1 -0
- package/.next/standalone/.next/static/chunks/1chp3nx45meg5.js +44 -0
- package/.next/standalone/.next/static/chunks/1irqj0lf-fu3d.js +1 -0
- package/.next/standalone/.next/static/chunks/1uadqylrod5_v.js +1 -0
- package/.next/standalone/.next/static/chunks/23u0zclgwpc4d.js +1 -0
- package/.next/standalone/.next/static/chunks/289ktj97di6zg.js +1 -0
- package/.next/standalone/.next/static/chunks/2b3lmf8e6uj8m.js +16 -0
- package/.next/standalone/.next/static/chunks/2jz311xl1pp_8.js +1 -0
- package/.next/standalone/.next/static/chunks/3npq5yd7c4dmn.js +2 -0
- package/.next/standalone/.next/static/qqqcxvzBUizkECrT4swyK/_clientMiddlewareManifest.js +14 -0
- package/.next/standalone/CHANGELOG.md +298 -0
- package/.next/standalone/CONTRIBUTING.md +5 -2
- package/.next/standalone/README.md +138 -30
- package/.next/standalone/SECURITY.md +117 -10
- package/.next/standalone/app/api/company-scores/legacy/route.js +32 -0
- package/.next/standalone/app/api/company-scores/route.js +20 -11
- package/.next/standalone/app/api/data/export/route.js +49 -0
- package/.next/standalone/app/api/data/import/route.js +83 -0
- package/.next/standalone/app/api/data/restart/route.js +37 -0
- package/.next/standalone/app/api/data/reveal/route.js +14 -0
- package/.next/standalone/app/api/data/route.js +39 -0
- package/.next/standalone/app/api/ingest/route.js +15 -47
- package/.next/standalone/app/api/scraper/route.js +264 -125
- package/.next/standalone/app/api/settings/route.js +58 -0
- package/.next/standalone/app/api/settings/sector-preview/route.js +38 -0
- package/.next/standalone/app/api/settings/sector-suggestions/route.js +20 -0
- package/.next/standalone/app/api/update/route.js +188 -23
- package/.next/standalone/app/avatars/[file]/route.js +4 -2
- package/.next/standalone/app/components/CompanyScores.js +28 -7
- package/.next/standalone/app/components/EmptyState.js +8 -0
- package/.next/standalone/app/components/ForceGraph.js +39 -35
- package/.next/standalone/app/components/LegacyScoresCard.js +129 -0
- package/.next/standalone/app/components/Sidebar.js +11 -10
- package/.next/standalone/app/components/UpdatePanel.js +306 -119
- package/.next/standalone/app/components/UserProvider.js +4 -3
- package/.next/standalone/app/components/settings/DataSection.js +437 -0
- package/.next/standalone/app/components/settings/SectorSection.js +445 -0
- package/.next/standalone/app/components/ui.js +62 -0
- package/.next/standalone/app/launch/page.js +30 -20
- package/.next/standalone/app/page.js +13 -0
- package/.next/standalone/app/paths/page.js +12 -4
- package/.next/standalone/app/profile/page.js +41 -8
- package/.next/standalone/app/queue/page.js +8 -2
- package/.next/standalone/app/settings/page.js +96 -0
- package/.next/standalone/app/setup/page.js +32 -16
- package/.next/standalone/bin/args.mjs +44 -0
- package/.next/standalone/bin/six-degrees.mjs +9 -15
- package/.next/standalone/lib/companies.js +44 -119
- package/.next/standalone/lib/csv.js +8 -0
- package/.next/standalone/lib/data-export.js +170 -0
- package/.next/standalone/lib/data-folder.js +238 -0
- package/.next/standalone/lib/data-import.js +878 -0
- package/.next/standalone/lib/db-client.js +48 -3
- package/.next/standalone/lib/durable.js +73 -0
- package/.next/standalone/lib/gate.js +90 -1
- package/.next/standalone/lib/ingest.js +40 -0
- package/.next/standalone/lib/legacy-offer.js +185 -0
- package/.next/standalone/lib/legacy-scores.js +77 -0
- package/.next/standalone/lib/linkedin-limits.js +124 -1
- package/.next/standalone/lib/rpc.js +121 -13
- package/.next/standalone/lib/sample-stats.js +16 -0
- package/.next/standalone/lib/scan-progress.js +13 -0
- package/.next/standalone/lib/scan-state.js +53 -0
- package/.next/standalone/lib/scanner-python.js +685 -0
- package/.next/standalone/lib/scanner-setup.js +104 -0
- package/.next/standalone/lib/scoring.js +747 -138
- package/.next/standalone/lib/scraper-client.js +9 -5
- package/.next/standalone/lib/sector-directory.js +1532 -0
- package/.next/standalone/lib/sector-focus.js +163 -0
- package/.next/standalone/lib/sector-labels.js +81 -0
- package/.next/standalone/lib/settings-effects.js +59 -0
- package/.next/standalone/lib/settings.js +83 -0
- package/.next/standalone/lib/updater-job.js +838 -0
- package/.next/standalone/lib/updater.js +494 -0
- package/.next/standalone/middleware.js +25 -28
- package/.next/standalone/next.config.mjs +19 -3
- package/.next/standalone/package-lock.json +2 -2
- package/.next/standalone/package.json +1 -2
- package/.next/standalone/scripts/apply-update.sh +482 -0
- package/.next/standalone/scripts/build-app.mjs +251 -9
- package/.next/standalone/scripts/requirements.txt +106 -4
- package/.next/standalone/scripts/test-release-server.mjs +143 -0
- package/.next/standalone/server.js +1 -1
- package/.next/static/chunks/06x3jiiz96m5t.js +1 -0
- package/.next/static/chunks/{34at5d2ifl62i.js → 0ngx9s6-zgshe.js} +5 -5
- package/.next/static/chunks/0q-_khndfxubv.js +2 -0
- package/.next/static/chunks/1c79veqedvubt.js +1 -0
- package/.next/static/chunks/1chp3nx45meg5.js +44 -0
- package/.next/static/chunks/1irqj0lf-fu3d.js +1 -0
- package/.next/static/chunks/1uadqylrod5_v.js +1 -0
- package/.next/static/chunks/23u0zclgwpc4d.js +1 -0
- package/.next/static/chunks/289ktj97di6zg.js +1 -0
- package/.next/static/chunks/2b3lmf8e6uj8m.js +16 -0
- package/.next/static/chunks/2jz311xl1pp_8.js +1 -0
- package/.next/static/chunks/3npq5yd7c4dmn.js +2 -0
- package/.next/static/qqqcxvzBUizkECrT4swyK/_clientMiddlewareManifest.js +14 -0
- package/CHANGELOG.md +298 -0
- package/README.md +138 -30
- package/SECURITY.md +117 -10
- package/bin/args.mjs +44 -0
- package/bin/six-degrees.mjs +9 -15
- package/lib/companies.js +44 -119
- package/lib/csv.js +8 -0
- package/lib/data-export.js +170 -0
- package/lib/data-folder.js +238 -0
- package/lib/data-import.js +878 -0
- package/lib/db-client.js +48 -3
- package/lib/durable.js +73 -0
- package/lib/gate.js +90 -1
- package/lib/ingest.js +40 -0
- package/lib/legacy-offer.js +185 -0
- package/lib/legacy-scores.js +77 -0
- package/lib/linkedin-limits.js +124 -1
- package/lib/rpc.js +121 -13
- package/lib/sample-stats.js +16 -0
- package/lib/scan-progress.js +13 -0
- package/lib/scan-state.js +53 -0
- package/lib/scanner-python.js +685 -0
- package/lib/scanner-setup.js +104 -0
- package/lib/scoring.js +747 -138
- package/lib/scraper-client.js +9 -5
- package/lib/sector-directory.js +1532 -0
- package/lib/sector-focus.js +163 -0
- package/lib/sector-labels.js +81 -0
- package/lib/settings-effects.js +59 -0
- package/lib/settings.js +83 -0
- package/lib/updater-job.js +838 -0
- package/lib/updater.js +494 -0
- package/package.json +1 -2
- package/scripts/requirements.txt +106 -4
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jrmmj-._.js +0 -150
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qx548g._.js +0 -151
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an3leo._.js +0 -150
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1m8zedk._.js +0 -155
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1zor0ys._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0_rp-01._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0hzdk79._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0ow7u5r._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0t0zc2d._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0wa631d._.js +0 -3
- package/.next/standalone/.next/server/chunks/_13ccnao._.js +0 -3
- package/.next/standalone/.next/server/chunks/_13es063._.js +0 -3
- package/.next/standalone/.next/server/chunks/_142872j._.js +0 -3
- package/.next/standalone/.next/server/chunks/_18wsb_a._.js +0 -8
- package/.next/standalone/.next/server/chunks/_1e-4h5h._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1gvvd7n._.js +0 -158
- package/.next/standalone/.next/server/chunks/_1moda66._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1p6ghzv._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1xmmi_v._.js +0 -3
- package/.next/standalone/.next/server/chunks/_1z-yrlf._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0bf3x4q._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +0 -4
- package/.next/standalone/.next/static/ZGTiDrZ5NHGETgGdlhssu/_clientMiddlewareManifest.js +0 -6
- package/.next/standalone/.next/static/chunks/0jk64vo17avsb.js +0 -1
- package/.next/standalone/.next/static/chunks/0s65dsrthylo6.js +0 -2
- package/.next/standalone/.next/static/chunks/0uyfdhi8dek85.js +0 -16
- package/.next/standalone/.next/static/chunks/220-ne82aus0c.js +0 -44
- package/.next/standalone/.next/static/chunks/229haorf0f19b.js +0 -2
- package/.next/standalone/.next/static/chunks/2g54uafnwuakc.js +0 -1
- package/.next/standalone/.next/static/chunks/2spwqs6b6dx13.js +0 -1
- package/.next/standalone/.next/static/chunks/38dlepuubiox0.js +0 -1
- package/.next/standalone/scripts/score-connections.sql +0 -80
- package/.next/standalone/scripts/score_new_connections.sql +0 -77
- package/.next/standalone/site/app.js +0 -84
- package/.next/standalone/site/index.html +0 -221
- package/.next/standalone/site/style.css +0 -155
- package/.next/standalone/site/video/install-mac-poster.jpg +0 -0
- package/.next/standalone/site/video/install-mac.mp4 +0 -0
- package/.next/standalone/site/video/linux-poster.jpg +0 -0
- package/.next/standalone/site/video/linux.mp4 +0 -0
- package/.next/standalone/site/video/scan-poster.jpg +0 -0
- package/.next/standalone/site/video/scan.mp4 +0 -0
- package/.next/static/ZGTiDrZ5NHGETgGdlhssu/_clientMiddlewareManifest.js +0 -6
- package/.next/static/chunks/0jk64vo17avsb.js +0 -1
- package/.next/static/chunks/0s65dsrthylo6.js +0 -2
- package/.next/static/chunks/0uyfdhi8dek85.js +0 -16
- package/.next/static/chunks/220-ne82aus0c.js +0 -44
- package/.next/static/chunks/229haorf0f19b.js +0 -2
- package/.next/static/chunks/2g54uafnwuakc.js +0 -1
- package/.next/static/chunks/2spwqs6b6dx13.js +0 -1
- package/.next/static/chunks/38dlepuubiox0.js +0 -1
- package/scripts/score_new_connections.sql +0 -77
- /package/.next/standalone/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_ssgManifest.js +0 -0
- /package/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_buildManifest.js +0 -0
- /package/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// Settings → Your sector. Up to three sectors you work in: one of the twelve
|
|
4
|
+
// broad industries, or a narrower sector from the app's directory (Dental,
|
|
5
|
+
// Real Estate, Software & SaaS…). Companies in them count for more when your
|
|
6
|
+
// scanned network is scored, like setting their scores by hand on Paths →
|
|
7
|
+
// Scores, but for a whole sector at once. The model is lib/scoring.js, the
|
|
8
|
+
// setting lib/sector-focus.js, the directory lib/sector-directory.js.
|
|
9
|
+
//
|
|
10
|
+
// Before you save, the page asks the app what would change (a dry run that
|
|
11
|
+
// writes nothing). Saving stores the choice with your network and rescores
|
|
12
|
+
// everyone, the way a company score change does. Suggestions come from the
|
|
13
|
+
// people you've scanned (/api/settings/sector-suggestions).
|
|
14
|
+
|
|
15
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
16
|
+
import Link from 'next/link';
|
|
17
|
+
import { Section, Body, Status, Btn, LINE } from '../ui';
|
|
18
|
+
import { INDUSTRIES } from '../../../lib/companies';
|
|
19
|
+
import { MAX_SECTORS, sameFocus, focusFingerprint } from '../../../lib/sector-focus';
|
|
20
|
+
import { DIRECTORY, SECTOR_KEYS, sectorByKey } from '../../../lib/sector-directory';
|
|
21
|
+
import { SECTOR_BONUS } from '../../../lib/scoring';
|
|
22
|
+
import { TIER_COLORS_CLASSIC } from '../../../lib/tiers';
|
|
23
|
+
import { csvNetworkSource } from '../../../lib/csv';
|
|
24
|
+
|
|
25
|
+
const STRENGTH_LABEL = { lean: 'Lean', strong: 'Strong' };
|
|
26
|
+
// What says the reader has taken over the page (see the jump to #sector).
|
|
27
|
+
const READER_INPUT = ['wheel', 'touchstart', 'keydown', 'pointerdown'];
|
|
28
|
+
const DEGREE = { 1: '1st', 2: '2nd', 3: '3rd' };
|
|
29
|
+
const plural = (n, one, many = `${one}s`) => `${n.toLocaleString()} ${n === 1 ? one : many}`;
|
|
30
|
+
|
|
31
|
+
// Each industry's narrower sectors, in the directory's order.
|
|
32
|
+
const SECTORS_OF = new Map(INDUSTRIES.map((g) => [g.key, DIRECTORY.filter((s) => s.group === g.key)]));
|
|
33
|
+
const GROUP_OF = new Map(DIRECTORY.map((s) => [s.key, s.group]));
|
|
34
|
+
// What the search box looks through: each sector's name, its words, jobs and
|
|
35
|
+
// companies, as they read (without the list's "(s)" and "$" marks), so
|
|
36
|
+
// "recruiter" finds HR & Recruiting.
|
|
37
|
+
const SEARCHABLE = DIRECTORY.map((s) => ({
|
|
38
|
+
sector: s,
|
|
39
|
+
label: s.label.toLowerCase(),
|
|
40
|
+
words: [...s.words, ...(s.roles || []), ...(s.names || []), ...s.companies].map((w) => ` ${w.replace(/\(s\)$|\$$/, '').toLowerCase()}`),
|
|
41
|
+
}));
|
|
42
|
+
// A sector of work every company has (HR & Recruiting, Legal…) counts firms in
|
|
43
|
+
// that line, not every company that employs someone doing it.
|
|
44
|
+
const FUNCTION_TITLE = 'Counts firms in this line of work, not every company with someone in the job';
|
|
45
|
+
const FUNCTIONS = DIRECTORY.filter((s) => s.kind === 'function').map((s) => s.label);
|
|
46
|
+
const listed = (labels) => (labels.length > 1 ? `${labels.slice(0, -1).join(', ')} and ${labels.at(-1)}` : labels.join(''));
|
|
47
|
+
|
|
48
|
+
/** Sectors (and whole industries) whose name has the query, or a word or company that starts with it. */
|
|
49
|
+
function searchSectors(query) {
|
|
50
|
+
const q = query.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
51
|
+
if (!q) return null;
|
|
52
|
+
return {
|
|
53
|
+
industries: INDUSTRIES.filter((g) => g.label.toLowerCase().includes(q)),
|
|
54
|
+
sectors: SEARCHABLE.filter((s) => s.label.includes(q) || s.words.some((w) => w.includes(` ${q}`))).map((s) => s.sector),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** "120 people move up a tier and 4 move down." (or "moved", after a save) */
|
|
59
|
+
function tierLine(up, down, past) {
|
|
60
|
+
const [goes, go] = past ? ['moved', 'moved'] : ['moves', 'move'];
|
|
61
|
+
if (!up && !down) return past ? 'No one changed tier.' : 'No one changes tier.';
|
|
62
|
+
const verb = (n) => (n === 1 ? goes : go);
|
|
63
|
+
if (up && down) return `${plural(up, 'person', 'people')} ${verb(up)} up a tier and ${down.toLocaleString()} ${verb(down)} down.`;
|
|
64
|
+
return up ? `${plural(up, 'person', 'people')} ${verb(up)} up a tier.` : `${plural(down, 'person', 'people')} ${verb(down)} down a tier.`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default function SectorSection() {
|
|
68
|
+
const [saved, setSaved] = useState(null);
|
|
69
|
+
const [draft, setDraft] = useState(null);
|
|
70
|
+
const [preview, setPreview] = useState(null);
|
|
71
|
+
const [saving, setSaving] = useState(false);
|
|
72
|
+
const [result, setResult] = useState(null);
|
|
73
|
+
const [loadError, setLoadError] = useState(null);
|
|
74
|
+
const [suggest, setSuggest] = useState({ loading: true });
|
|
75
|
+
const [query, setQuery] = useState('');
|
|
76
|
+
// Industries shown open; those holding a saved pick start open.
|
|
77
|
+
const [open, setOpen] = useState(() => new Set());
|
|
78
|
+
// A CSV import or the sample network held in this window. This section only
|
|
79
|
+
// renders in the browser (the page waits in OnboardingGate), so reading
|
|
80
|
+
// sessionStorage here can't disagree with a server render.
|
|
81
|
+
const [onScreen] = useState(() => (typeof window === 'undefined' ? null : csvNetworkSource()));
|
|
82
|
+
const timer = useRef(null);
|
|
83
|
+
const ticket = useRef(0);
|
|
84
|
+
const jumped = useRef(false);
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
let off = false;
|
|
88
|
+
fetch('/api/settings')
|
|
89
|
+
.then((r) => r.json().then((d) => (r.ok ? d : Promise.reject(new Error(d.error || 'Could not load your sector.')))))
|
|
90
|
+
.then((d) => {
|
|
91
|
+
if (off) return;
|
|
92
|
+
const focus = d.settings?.sectorFocus || { sectors: [], strength: 'lean' };
|
|
93
|
+
setSaved(focus);
|
|
94
|
+
setDraft(focus);
|
|
95
|
+
setOpen(new Set(focus.sectors.map((k) => GROUP_OF.get(k) || k)));
|
|
96
|
+
})
|
|
97
|
+
.catch((e) => { if (!off) setLoadError(e.message); });
|
|
98
|
+
// Suggestions read every scanned row, so they load on their own and never hold up the rest.
|
|
99
|
+
fetch('/api/settings/sector-suggestions')
|
|
100
|
+
.then((r) => r.json().then((d) => (r.ok ? d : Promise.reject(new Error(d.error || 'Could not load suggestions.')))))
|
|
101
|
+
.then((d) => { if (!off) setSuggest({ scored: d.scored, list: d.suggestions || [] }); })
|
|
102
|
+
.catch((e) => { if (!off) setSuggest({ error: e.message }); });
|
|
103
|
+
return () => { off = true; clearTimeout(timer.current); };
|
|
104
|
+
}, []);
|
|
105
|
+
|
|
106
|
+
// Links to /settings#sector (the profile's card, Paths → Scores) arrive
|
|
107
|
+
// before this section has loaded, so the browser's own jump to it finds
|
|
108
|
+
// nothing. Jump once it's here, then keep it in place while what loads above
|
|
109
|
+
// it (Updates) pushes it down: the browser only holds steady what's already
|
|
110
|
+
// on screen, and that is the page's header. Following stops as soon as the
|
|
111
|
+
// reader scrolls, clicks or types, and after two seconds regardless.
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
if (jumped.current || (!draft && !loadError)) return;
|
|
114
|
+
jumped.current = true;
|
|
115
|
+
const el = document.getElementById('sector');
|
|
116
|
+
if (window.location.hash !== '#sector' || !el) return;
|
|
117
|
+
const jump = () => el.scrollIntoView({ block: 'start' });
|
|
118
|
+
jump();
|
|
119
|
+
const follow = new ResizeObserver(jump);
|
|
120
|
+
follow.observe(document.body);
|
|
121
|
+
const stop = () => {
|
|
122
|
+
follow.disconnect();
|
|
123
|
+
clearTimeout(done);
|
|
124
|
+
for (const e of READER_INPUT) window.removeEventListener(e, stop, true);
|
|
125
|
+
};
|
|
126
|
+
const done = setTimeout(stop, 2000);
|
|
127
|
+
for (const e of READER_INPUT) window.addEventListener(e, stop, { capture: true, passive: true });
|
|
128
|
+
return stop;
|
|
129
|
+
}, [draft, loadError]);
|
|
130
|
+
|
|
131
|
+
const results = useMemo(() => searchSectors(query), [query]);
|
|
132
|
+
|
|
133
|
+
// Every change asks for a fresh dry run, a moment after the last click.
|
|
134
|
+
// Only the newest answer is kept.
|
|
135
|
+
function change(next) {
|
|
136
|
+
setDraft(next);
|
|
137
|
+
setResult(null);
|
|
138
|
+
clearTimeout(timer.current);
|
|
139
|
+
const mine = ++ticket.current;
|
|
140
|
+
if (sameFocus(next, saved)) { setPreview(null); return; }
|
|
141
|
+
const key = focusFingerprint(next);
|
|
142
|
+
setPreview({ key, loading: true });
|
|
143
|
+
timer.current = setTimeout(async () => {
|
|
144
|
+
try {
|
|
145
|
+
const r = await fetch('/api/settings/sector-preview', {
|
|
146
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sectorFocus: next }),
|
|
147
|
+
});
|
|
148
|
+
const d = await r.json();
|
|
149
|
+
if (mine !== ticket.current) return;
|
|
150
|
+
setPreview(r.ok ? { key, ...d } : { key, error: d.error || 'Could not work out what would change.' });
|
|
151
|
+
} catch {
|
|
152
|
+
if (mine === ticket.current) setPreview({ key, error: 'Could not reach the app to work out what would change.' });
|
|
153
|
+
}
|
|
154
|
+
}, 250);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function toggle(key) {
|
|
158
|
+
const on = draft.sectors.includes(key);
|
|
159
|
+
if (!on && draft.sectors.length >= MAX_SECTORS) return;
|
|
160
|
+
const sectors = on ? draft.sectors.filter((k) => k !== key) : SECTOR_KEYS.filter((k) => k === key || draft.sectors.includes(k));
|
|
161
|
+
// A sector picked from the suggestions or a search shows up in its industry too.
|
|
162
|
+
if (!on && GROUP_OF.has(key)) setOpen((was) => new Set(was).add(GROUP_OF.get(key)));
|
|
163
|
+
change({ ...draft, sectors });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function flip(group) {
|
|
167
|
+
setOpen((was) => {
|
|
168
|
+
const next = new Set(was);
|
|
169
|
+
if (next.has(group)) next.delete(group); else next.add(group);
|
|
170
|
+
return next;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function save() {
|
|
175
|
+
setSaving(true);
|
|
176
|
+
setResult(null);
|
|
177
|
+
clearTimeout(timer.current);
|
|
178
|
+
ticket.current++;
|
|
179
|
+
try {
|
|
180
|
+
const r = await fetch('/api/settings', {
|
|
181
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ settings: { sectorFocus: draft } }),
|
|
182
|
+
});
|
|
183
|
+
const d = await r.json();
|
|
184
|
+
if (d.settings) { setSaved(d.settings.sectorFocus); setDraft(d.settings.sectorFocus); setPreview(null); }
|
|
185
|
+
if (!r.ok) { setResult({ tone: 'bad', text: d.error || 'Could not save.' }); return; }
|
|
186
|
+
setResult({ tone: 'ok', text: savedLine(d.settings.sectorFocus, d.effects?.sectorFocus) });
|
|
187
|
+
} catch {
|
|
188
|
+
setResult({ tone: 'bad', text: 'Could not reach the app. Reload this page to see what is saved.' });
|
|
189
|
+
} finally {
|
|
190
|
+
setSaving(false);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const changed = draft && saved && !sameFocus(draft, saved);
|
|
195
|
+
const full = draft && draft.sectors.length >= MAX_SECTORS;
|
|
196
|
+
// One chip for any pick: an industry or a sector, wherever it's shown.
|
|
197
|
+
const chip = (key, label, { note, title } = {}) => {
|
|
198
|
+
const on = draft.sectors.includes(key);
|
|
199
|
+
return (
|
|
200
|
+
<Chip key={key} color={sectorByKey(key).color} on={on} blocked={!on && full} disabled={saving} title={title}
|
|
201
|
+
onClick={() => toggle(key)}>
|
|
202
|
+
{label}{note && <span style={{ fontWeight: 400, color: on ? '#dfe7e7' : '#8b9a9a' }}>{note}</span>}
|
|
203
|
+
</Chip>
|
|
204
|
+
);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<Section id="sector" title="Your sector"
|
|
209
|
+
intro="Pick up to three sectors you work in. Companies in them count for more when your network is scored, so the people there rank higher.">
|
|
210
|
+
{loadError && <Status tone="bad">{loadError}</Status>}
|
|
211
|
+
{!draft && !loadError && <Body>Loading…</Body>}
|
|
212
|
+
|
|
213
|
+
{draft && (
|
|
214
|
+
<>
|
|
215
|
+
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 6 }}>
|
|
216
|
+
<span style={{ fontSize: 13, color: '#8b9a9a' }}>Your picks ({draft.sectors.length} of {MAX_SECTORS}):</span>
|
|
217
|
+
{!draft.sectors.length && <span style={{ fontSize: 13, color: '#667' }}>none yet</span>}
|
|
218
|
+
{draft.sectors.map((k) => {
|
|
219
|
+
const s = sectorByKey(k);
|
|
220
|
+
return (
|
|
221
|
+
<button key={k} type="button" disabled={saving} onClick={() => toggle(k)} aria-label={`Remove ${s.label}`}
|
|
222
|
+
style={{
|
|
223
|
+
display: 'flex', alignItems: 'center', gap: 6, padding: '4px 10px', borderRadius: 999, fontSize: 12.5,
|
|
224
|
+
fontWeight: 600, color: '#fff', background: `${s.color}33`, border: `1px solid ${s.color}`, cursor: 'pointer',
|
|
225
|
+
}}>
|
|
226
|
+
{s.label} <span aria-hidden="true" style={{ color: '#cfd8d8' }}>×</span>
|
|
227
|
+
</button>
|
|
228
|
+
);
|
|
229
|
+
})}
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
<Suggestions state={suggest} chip={chip} />
|
|
233
|
+
|
|
234
|
+
<label htmlFor="sector-search" style={{ display: 'block', fontSize: 13, color: '#8b9a9a', margin: '16px 0 6px' }}>
|
|
235
|
+
Find a sector
|
|
236
|
+
</label>
|
|
237
|
+
<div style={{ display: 'flex', gap: 8 }}>
|
|
238
|
+
<input id="sector-search" type="search" value={query} onChange={(e) => setQuery(e.target.value)}
|
|
239
|
+
placeholder="Try dentist, bakery or Stripe"
|
|
240
|
+
autoComplete="off" spellCheck={false}
|
|
241
|
+
style={{
|
|
242
|
+
flex: 1, minWidth: 0, padding: '8px 12px', borderRadius: 7, fontSize: 14, color: '#fff',
|
|
243
|
+
background: 'rgba(255,255,255,0.05)', border: LINE, outline: 'none',
|
|
244
|
+
}} />
|
|
245
|
+
{query && <Btn onClick={() => setQuery('')}>Clear</Btn>}
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
{results ? (
|
|
249
|
+
<div style={{ marginTop: 10 }} aria-live="polite">
|
|
250
|
+
{results.industries.length + results.sectors.length === 0 ? (
|
|
251
|
+
<Body style={{ fontSize: 12.5 }}>
|
|
252
|
+
Nothing in the list matches “{query.trim()}”. Try a job title, a kind of business or a company, or clear
|
|
253
|
+
the search and pick one of the twelve broad industries.
|
|
254
|
+
</Body>
|
|
255
|
+
) : (
|
|
256
|
+
<div role="group" aria-label="Sectors that match your search" style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
|
|
257
|
+
{results.industries.map((g) => chip(g.key, g.label, { note: ' · the whole industry' }))}
|
|
258
|
+
{results.sectors.map((s) => chip(s.key, s.label, { title: s.kind === 'function' ? FUNCTION_TITLE : `In ${sectorByKey(s.group).label}` }))}
|
|
259
|
+
</div>
|
|
260
|
+
)}
|
|
261
|
+
</div>
|
|
262
|
+
) : (
|
|
263
|
+
<div style={{ marginTop: 10 }}>
|
|
264
|
+
{INDUSTRIES.map((g) => {
|
|
265
|
+
const sectors = SECTORS_OF.get(g.key);
|
|
266
|
+
const isOpen = open.has(g.key);
|
|
267
|
+
const inside = sectors.filter((s) => draft.sectors.includes(s.key)).length;
|
|
268
|
+
return (
|
|
269
|
+
<div key={g.key} style={{ borderTop: LINE, padding: '8px 0' }}>
|
|
270
|
+
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 8 }}>
|
|
271
|
+
{chip(g.key, g.label, { title: 'The whole industry: companies its sectors place, or whose name or the well-known list says so' })}
|
|
272
|
+
<button type="button" aria-expanded={isOpen} aria-controls={`sectors-${g.key}`} onClick={() => flip(g.key)}
|
|
273
|
+
style={{
|
|
274
|
+
padding: '4px 6px', fontSize: 12.5, color: inside ? '#9fd3ff' : '#8b9a9a', background: 'none', border: 'none',
|
|
275
|
+
cursor: 'pointer',
|
|
276
|
+
}}>
|
|
277
|
+
{isOpen ? '▾' : '▸'} {plural(sectors.length, 'sector')}{inside ? ` · ${inside} picked` : ''}
|
|
278
|
+
</button>
|
|
279
|
+
</div>
|
|
280
|
+
{isOpen && (
|
|
281
|
+
<div id={`sectors-${g.key}`} role="group" aria-label={`Sectors in ${g.label}`}
|
|
282
|
+
style={{ display: 'flex', flexWrap: 'wrap', gap: 8, margin: '8px 0 2px 14px' }}>
|
|
283
|
+
{sectors.map((s) => chip(s.key, s.label, s.kind === 'function' ? { title: FUNCTION_TITLE } : undefined))}
|
|
284
|
+
</div>
|
|
285
|
+
)}
|
|
286
|
+
</div>
|
|
287
|
+
);
|
|
288
|
+
})}
|
|
289
|
+
</div>
|
|
290
|
+
)}
|
|
291
|
+
|
|
292
|
+
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 8, marginTop: 14 }}>
|
|
293
|
+
<span style={{ fontSize: 13, color: '#8b9a9a' }}>How much:</span>
|
|
294
|
+
{Object.keys(SECTOR_BONUS).map((s) => (
|
|
295
|
+
<button key={s} type="button" aria-pressed={draft.strength === s} disabled={saving}
|
|
296
|
+
onClick={() => change({ ...draft, strength: s })}
|
|
297
|
+
style={{
|
|
298
|
+
padding: '5px 12px', borderRadius: 7, fontSize: 12.5, fontWeight: 600, cursor: 'pointer',
|
|
299
|
+
color: draft.strength === s ? '#fff' : '#8b9a9a',
|
|
300
|
+
background: draft.strength === s ? 'rgba(52,152,219,0.25)' : 'transparent', border: LINE,
|
|
301
|
+
}}>
|
|
302
|
+
{STRENGTH_LABEL[s]} · +{SECTOR_BONUS[s]}
|
|
303
|
+
</button>
|
|
304
|
+
))}
|
|
305
|
+
</div>
|
|
306
|
+
<Body style={{ fontSize: 12.5 }}>
|
|
307
|
+
Each company in your sectors gets +1 (lean) or +2 (strong) on its score out of 10, never above 10. A company in
|
|
308
|
+
more than one of your picks still gets it once.
|
|
309
|
+
</Body>
|
|
310
|
+
|
|
311
|
+
<Preview preview={changed ? preview : null} draft={draft} />
|
|
312
|
+
|
|
313
|
+
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 14 }}>
|
|
314
|
+
<Btn primary onClick={save} disabled={!changed || saving}>{saving ? 'Saving and rescoring…' : 'Save'}</Btn>
|
|
315
|
+
{changed && !saving && <Btn onClick={() => change(saved)}>Cancel</Btn>}
|
|
316
|
+
{!changed && draft.sectors.length > 0 && !saving && (
|
|
317
|
+
<Btn onClick={() => change({ ...draft, sectors: [] })}>Turn off</Btn>
|
|
318
|
+
)}
|
|
319
|
+
</div>
|
|
320
|
+
{result && <Status tone={result.tone}>{result.text}</Status>}
|
|
321
|
+
|
|
322
|
+
<ul style={{ margin: '16px 0 0', paddingLeft: 18, fontSize: 12.5, color: '#778', lineHeight: 1.7 }}>
|
|
323
|
+
<li>Tiers rank how reachable someone is through your network, not the people themselves.</li>
|
|
324
|
+
<li>A company score you set on <Link href="/paths?tab=scores" style={{ color: '#3498DB' }}>Paths → Scores</Link> always wins. Your sector never changes it.</li>
|
|
325
|
+
<li>If you scan highest tier first, people in your sectors come up sooner. Scanning newest first, the default, doesn’t go by tier.</li>
|
|
326
|
+
<li>
|
|
327
|
+
An industry includes its sectors. It counts a company in any of its sectors (Healthcare & Biotech counts a
|
|
328
|
+
practice that is only in Dental), and a company whose industry the app’s list of well-known companies or
|
|
329
|
+
the company’s own name gives (Meridian Health). Not one known only from its people’s job titles: a
|
|
330
|
+
recruiter at Acme Widgets doesn’t make Acme a consulting firm.
|
|
331
|
+
</li>
|
|
332
|
+
<li>
|
|
333
|
+
A narrower sector counts a company when its name says so (Smith Family Dental), it’s a well-known company in
|
|
334
|
+
that sector, or at least half of the people you know there say so in their headlines (dentist, DDS, orthodontist).
|
|
335
|
+
The words are a fixed list that comes with the app, the same on every computer. Nothing is sent anywhere.
|
|
336
|
+
</li>
|
|
337
|
+
<li>
|
|
338
|
+
Some sectors are work every kind of company has: {listed(FUNCTIONS)}. For those a job title doesn’t count,
|
|
339
|
+
since a recruiter at Acme Widgets doesn’t make it a recruiting firm. The company’s name does (Acme
|
|
340
|
+
Staffing, Smith CPA), and so does a kind of firm in a headline (staffing agency, law firm, SaaS).
|
|
341
|
+
</li>
|
|
342
|
+
{onScreen && (
|
|
343
|
+
<li style={{ color: '#FFD700' }}>
|
|
344
|
+
{onScreen === 'sample' ? 'The sample network' : 'The CSV import'} open in this window isn’t changed by this, and
|
|
345
|
+
isn’t counted in the suggestions. Your sector applies to networks you’ve scanned.
|
|
346
|
+
</li>
|
|
347
|
+
)}
|
|
348
|
+
</ul>
|
|
349
|
+
</>
|
|
350
|
+
)}
|
|
351
|
+
</Section>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** A pick you can turn on and off: an industry or a sector, with its industry's colour. */
|
|
356
|
+
function Chip({ color, on, blocked, disabled, title, onClick, children }) {
|
|
357
|
+
return (
|
|
358
|
+
<button type="button" aria-pressed={on} disabled={blocked || disabled} onClick={onClick}
|
|
359
|
+
title={blocked ? `Up to ${MAX_SECTORS} sectors. Turn one off first.` : title}
|
|
360
|
+
style={{
|
|
361
|
+
display: 'flex', alignItems: 'center', gap: 7, padding: '6px 12px', borderRadius: 999, maxWidth: '100%',
|
|
362
|
+
fontSize: 12.5, fontWeight: 600, textAlign: 'left', cursor: blocked ? 'not-allowed' : 'pointer',
|
|
363
|
+
color: on ? '#fff' : blocked ? '#556' : '#b8c4c4',
|
|
364
|
+
background: on ? `${color}33` : 'rgba(255,255,255,0.04)',
|
|
365
|
+
border: on ? `1px solid ${color}` : LINE,
|
|
366
|
+
}}>
|
|
367
|
+
<span style={{ width: 8, height: 8, borderRadius: '50%', background: color, opacity: blocked ? 0.4 : 1, flexShrink: 0 }} />
|
|
368
|
+
<span>{children}</span>
|
|
369
|
+
</button>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** "Suggested from your network": the directory's sectors most of your scanned people work in. */
|
|
374
|
+
function Suggestions({ state, chip }) {
|
|
375
|
+
const note = { fontSize: 12.5, marginTop: 10 };
|
|
376
|
+
if (state.loading) return <Body style={note}>Looking through your network for suggestions…</Body>;
|
|
377
|
+
if (state.error) return <Body style={note}>Couldn’t load suggestions ({state.error}). You can still pick below.</Body>;
|
|
378
|
+
if (!state.scored) return <Body style={note}>Suggestions appear here once you’ve scanned your network.</Body>;
|
|
379
|
+
if (!state.list.length) return <Body style={note}>None of the list’s sectors stands out among the people you’ve scanned yet.</Body>;
|
|
380
|
+
return (
|
|
381
|
+
<div style={{ marginTop: 14 }}>
|
|
382
|
+
<div style={{ fontSize: 13, color: '#8b9a9a', marginBottom: 6 }}>Suggested from your network</div>
|
|
383
|
+
<div role="group" aria-label="Suggested from your network" style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
|
|
384
|
+
{state.list.map((s) => chip(s.key, s.label, {
|
|
385
|
+
note: `: ${plural(s.people, 'person', 'people')} at ${plural(s.companies, 'company', 'companies')}`,
|
|
386
|
+
title: `In ${sectorByKey(s.group).label}`,
|
|
387
|
+
}))}
|
|
388
|
+
</div>
|
|
389
|
+
</div>
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/** "Saved: …. Rescored your network (N people). …" */
|
|
394
|
+
function savedLine(focus, effect) {
|
|
395
|
+
// The labels have commas of their own ("Tech, Software & AI"), so a dot
|
|
396
|
+
// separates them.
|
|
397
|
+
const what = focus.sectors.length
|
|
398
|
+
? `Saved: ${focus.sectors.map((k) => sectorByKey(k).label).join(' · ')} (${STRENGTH_LABEL[focus.strength].toLowerCase()}).`
|
|
399
|
+
: 'Saved: no sector.';
|
|
400
|
+
if (!effect) return what;
|
|
401
|
+
if (!effect.scored) return `${what} There's no scanned network yet; it will apply when you scan.`;
|
|
402
|
+
// People, once each, as the tier moves count them: someone in two circles is
|
|
403
|
+
// two rows but one person.
|
|
404
|
+
return `${what} Rescored your network (${plural(effect.people ?? effect.scored, 'person', 'people')}). ${tierLine(effect.up, effect.down, true)}`;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function Preview({ preview, draft }) {
|
|
408
|
+
if (!preview) return null;
|
|
409
|
+
if (preview.key !== focusFingerprint(draft)) return null;
|
|
410
|
+
const box = { marginTop: 12, padding: '10px 14px', borderRadius: 8, fontSize: 13, lineHeight: 1.6, border: LINE, background: 'rgba(255,255,255,0.03)', color: '#cfd8d8' };
|
|
411
|
+
if (preview.loading) return <div style={box} aria-live="polite">Working out what would change…</div>;
|
|
412
|
+
if (preview.error) return <Status tone="bad">{preview.error}</Status>;
|
|
413
|
+
if (!preview.scored) {
|
|
414
|
+
return <div style={box} aria-live="polite">There’s no scanned network yet, so nothing changes now. Your choice applies once you scan.</div>;
|
|
415
|
+
}
|
|
416
|
+
const scores = (n, way) => `${plural(n, 'company', 'companies')} ${n === 1 ? 'scores' : 'score'} ${way}`;
|
|
417
|
+
const cos = [
|
|
418
|
+
preview.companiesUp && scores(preview.companiesUp, 'higher'),
|
|
419
|
+
preview.companiesDown && scores(preview.companiesDown, 'lower'),
|
|
420
|
+
].filter(Boolean).join(' and ');
|
|
421
|
+
return (
|
|
422
|
+
<div style={box} aria-live="polite">
|
|
423
|
+
<div>
|
|
424
|
+
<b style={{ color: '#fff' }}>If you save:</b> {cos ? `${cos}.` : 'No company changes score.'} {tierLine(preview.up, preview.down, false)}
|
|
425
|
+
</div>
|
|
426
|
+
{preview.examples?.length > 0 && (
|
|
427
|
+
<div style={{ marginTop: 6, display: 'flex', flexWrap: 'wrap', gap: '4px 12px', fontSize: 12.5 }}>
|
|
428
|
+
{preview.examples.map((e, n) => (
|
|
429
|
+
<span key={n} title={e.company || undefined}>
|
|
430
|
+
{e.name}{e.degree ? <span style={{ color: '#667' }}> ({DEGREE[e.degree] || `${e.degree}th`})</span> : null}{' '}
|
|
431
|
+
<b style={{ color: TIER_COLORS_CLASSIC[e.from] || '#889' }}>{e.from || '–'}</b>
|
|
432
|
+
{' → '}
|
|
433
|
+
<b style={{ color: TIER_COLORS_CLASSIC[e.to] || '#889' }}>{e.to}</b>
|
|
434
|
+
</span>
|
|
435
|
+
))}
|
|
436
|
+
</div>
|
|
437
|
+
)}
|
|
438
|
+
{preview.companyExamples?.length > 0 && (
|
|
439
|
+
<div style={{ marginTop: 4, fontSize: 12, color: '#8b9a9a' }}>
|
|
440
|
+
{preview.companyExamples.slice(0, 3).map((c) => `${c.name} ${c.from} → ${c.to}`).join(' · ')}
|
|
441
|
+
</div>
|
|
442
|
+
)}
|
|
443
|
+
</div>
|
|
444
|
+
);
|
|
445
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// Small shared pieces for the Settings page and anything that joins it later
|
|
4
|
+
// (UpdatePanel uses them). The Scan page still keeps its own private copies;
|
|
5
|
+
// new screens should use these rather than adding another.
|
|
6
|
+
|
|
7
|
+
export const LINE = '1px solid rgba(255,255,255,0.1)';
|
|
8
|
+
export const FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
9
|
+
|
|
10
|
+
/** One titled block of settings. `id` makes it linkable (/settings#id). */
|
|
11
|
+
export function Section({ id, title, intro, children }) {
|
|
12
|
+
return (
|
|
13
|
+
<section id={id} style={{ padding: '24px 0', borderBottom: LINE, scrollMarginTop: 16 }}>
|
|
14
|
+
<h2 style={{ fontSize: 16, fontWeight: 650, margin: '0 0 6px' }}>{title}</h2>
|
|
15
|
+
{intro && <Body style={{ marginTop: 0, marginBottom: 12 }}>{intro}</Body>}
|
|
16
|
+
{children}
|
|
17
|
+
</section>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function Body({ children, style }) {
|
|
22
|
+
return (
|
|
23
|
+
<div style={{ fontSize: 13.5, color: '#8b9a9a', lineHeight: 1.6, marginTop: 4, ...style }}>
|
|
24
|
+
{children}
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function Mono({ children }) {
|
|
30
|
+
return (
|
|
31
|
+
<code style={{ background: 'rgba(255,255,255,0.08)', padding: '1px 5px', borderRadius: 4, wordBreak: 'break-all' }}>
|
|
32
|
+
{children}
|
|
33
|
+
</code>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The answer to an action, where it can't be missed. tone: 'ok' | 'bad' | undefined. */
|
|
38
|
+
export function Status({ children, tone }) {
|
|
39
|
+
const color = tone === 'ok' ? '#00ff88' : tone === 'bad' ? '#ff7676' : '#e8e8ee';
|
|
40
|
+
const bg = tone === 'ok' ? 'rgba(0,255,136,0.08)' : tone === 'bad' ? 'rgba(255,80,80,0.08)' : 'rgba(255,255,255,0.05)';
|
|
41
|
+
const border = tone === 'ok' ? 'rgba(0,255,136,0.3)' : tone === 'bad' ? 'rgba(255,80,80,0.3)' : 'rgba(255,255,255,0.12)';
|
|
42
|
+
return (
|
|
43
|
+
<div role="status" style={{
|
|
44
|
+
marginTop: 10, padding: '10px 14px', borderRadius: 8, fontSize: 13.5, lineHeight: 1.6,
|
|
45
|
+
color, background: bg, border: `1px solid ${border}`,
|
|
46
|
+
}}>{tone === 'ok' && '✓ '}{children}</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function Btn({ children, onClick, disabled, primary, tone, type = 'button' }) {
|
|
51
|
+
const bg = tone === 'bad' ? 'rgba(255,80,80,0.15)'
|
|
52
|
+
: primary ? 'linear-gradient(135deg, #9B59B6, #3498DB)'
|
|
53
|
+
: 'rgba(255,255,255,0.08)';
|
|
54
|
+
return (
|
|
55
|
+
<button type={type} onClick={onClick} disabled={disabled} style={{
|
|
56
|
+
padding: '9px 18px', borderRadius: 7, fontSize: 13.5, fontWeight: 650,
|
|
57
|
+
color: disabled ? '#667' : '#fff', border: LINE,
|
|
58
|
+
background: disabled ? 'rgba(255,255,255,0.05)' : bg,
|
|
59
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
60
|
+
}}>{children}</button>
|
|
61
|
+
);
|
|
62
|
+
}
|