Skip to content

Commit

Permalink
refactor(activities): rewrite spheres model
Browse files Browse the repository at this point in the history
  • Loading branch information
Bricks666 committed Nov 24, 2024
1 parent 8dde23a commit 42e6fea
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/entities/activities/lib/use-activity-actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useAtom } from '@reatom/npm-react';

import { ActivityActions, activityActionsModel } from '../model';
import { ActivityActions, activityActionsModel } from '../models';

export interface UseActivityActionsResult {
readonly data: ActivityActions;
Expand Down
21 changes: 14 additions & 7 deletions src/entities/activities/lib/use-activity-spheres.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { useUnit } from 'effector-react';
import { useAtom } from '@reatom/npm-react';

import { activitySpheresModel } from '../model';
import { ActivitySpheres, activitySpheresModel } from '../models';

/**
* @deprecated
*/
export const useActivitySpheres = () => {
return useUnit(activitySpheresModel.query);
export interface UseActivitySpheresResult {
readonly data: ActivitySpheres;
readonly pending: boolean;
}

export const useActivitySpheres = (): UseActivitySpheresResult => {
const model = activitySpheresModel.create();

const [data] = useAtom(model.spheresAtom);
const [pending] = useAtom(model.pendingAtom);

return { data, pending, };
};
27 changes: 0 additions & 27 deletions src/entities/activities/models/activity-spheres.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/entities/activities/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './actions';
export * from './spheres';
export * as activitiesInRoomModel from './activities-in-room';
export * as activitySpheresModel from './activity-spheres';
2 changes: 2 additions & 0 deletions src/entities/activities/models/spheres/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './types';
export * as activitySpheresModel from './model';
57 changes: 57 additions & 0 deletions src/entities/activities/models/spheres/model.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { beforeEach, describe, expect, test } from 'vitest';

import { create } from './model';
import { ActivitySpheresModel } from './types';

import { TestCtx, spheres, createTestCtx, waitNextTick } from '~/test-utils';

describe('src/entities/activitites/models/spheres/model', () => {
let ctx: TestCtx;
let model: ActivitySpheresModel;

const createModel = () => {
model = create();
};

beforeEach(() => {
ctx = createTestCtx();
});

test('should create signleton model', () => {
createModel();

const anotherModel = create();

expect(model).toBe(anotherModel);
});

test('should stale model only after last susbcriber unsubscribe', () => {
createModel();
const anotherModel = create();

const track = ctx.subscribeTrack(model.spheresAtom);
const anotherTrack = ctx.subscribeTrack(anotherModel.spheresAtom);

expect(model).toBe(anotherModel);

anotherTrack.unsubscribe();

expect(model).toBe(create());

track.unsubscribe();

expect(model).not.toBe(create());
});

test('should load all spheres', async () => {
createModel();

const track = ctx.subscribeTrack(model.spheresAtom);

await waitNextTick();

expect(track.lastInput()).toStrictEqual(spheres);

track.unsubscribe();
});
});
45 changes: 45 additions & 0 deletions src/entities/activities/models/spheres/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
atom,
onDisconnect,
reatomResource,
withCache,
withDataAtom
} from '@reatom/framework';

import { activitiesApi } from '@/shared/api';
import {
constructName,
createSingletonFactory,
mapStandardResponse
} from '@/shared/lib';

import { ActivitySpheres, ActivitySpheresModel } from './types';

const modelName = constructName('activitites', 'spheres');

export const create = createSingletonFactory(
(): ActivitySpheresModel => {
const getSpheres = reatomResource(async (ctx) => {
return ctx.schedule(() => activitiesApi.getSpheres());
}, constructName(modelName, 'getSpheres')).pipe(
withDataAtom([] as ActivitySpheres, mapStandardResponse),
withCache()
);

const pendingAtom = atom(
(ctx) => !!ctx.spy(getSpheres.pendingAtom),
constructName(modelName, 'pendingAtom')
);

return {
spheresAtom: getSpheres.dataAtom,
pendingAtom,
};
},
{
key: modelName,
hooks: {
staleOn: (result, stale) => onDisconnect(result.spheresAtom, stale),
},
}
);
15 changes: 15 additions & 0 deletions src/entities/activities/models/spheres/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Atom } from '@reatom/framework';
import { Number, Record, Static, String } from 'runtypes';

export const activitySphereRT = Record({
id: Number,
name: String,
}).asReadonly();

export interface ActivitySphere extends Static<typeof activitySphereRT> {}
export type ActivitySpheres = ActivitySphere[];

export interface ActivitySpheresModel {
readonly spheresAtom: Atom<ActivitySpheres>;
readonly pendingAtom: Atom<boolean>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { Autocomplete, Chip, ListItem, ListItemText } from '@mui/material';
import * as React from 'react';
import { useTranslation } from 'react-i18next';

import { ActivitySphere } from '@/shared/api';
import { preparePickerHandler, preparePickerSelectedValue } from '@/shared/lib';
import { CommonProps, PickerProps } from '@/shared/types';
import { Field, FieldProps } from '@/shared/ui';

import { useActivitySpheres } from '../../lib';
import { ActivitySphere } from '../../models';

export type ActivitiesSpheresPickerProps = CommonProps &
PickerProps<number> &
Expand Down
8 changes: 2 additions & 6 deletions src/pages/room-activities/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { createEvent, sample } from 'effector';

import { activitiesFiltersModel } from '@/features/activities';

import {
activitiesInRoomModel,
activitySpheresModel
} from '@/entities/activities';
import { activitiesInRoomModel } from '@/entities/activities';
import { roomModel, roomsModel } from '@/entities/rooms';
import { usersInRoomModel } from '@/entities/users';

Expand Down Expand Up @@ -35,8 +32,7 @@ const formApplied = createEvent<void>();
const queries = [
activitiesInRoomModel.query,
usersInRoomModel.query,
roomsModel.query,
activitySpheresModel.query
roomsModel.query
];
const sorting = {
by: 'createdAt',
Expand Down
4 changes: 2 additions & 2 deletions src/shared/api/activities/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { instance, normalizeQuery } from '../request';
import {
Activity,
ActivityActionDto,
ActivitySphere,
ActivitySphereDto,
GetActivitiesInRoomParams
} from './types';

Expand All @@ -29,5 +29,5 @@ export const getActions = async () => {
export const getSpheres = async () => {
return instance
.get('activities/spheres/all')
.json<StandardResponse<ActivitySphere[]>>();
.json<StandardResponse<ActivitySphereDto[]>>();
};
4 changes: 2 additions & 2 deletions src/shared/api/activities/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ export interface ActivityActionDto {
readonly name: string;
}

export const activitySphere = Record({
const activitySphere = Record({
id: Number,
name: String,
}).asReadonly();

export interface ActivitySphere extends Static<typeof activitySphere> {}
export interface ActivitySphereDto extends Static<typeof activitySphere> {}

export const activity = Record({
id: Number,
Expand Down
8 changes: 3 additions & 5 deletions test-utils/fixtures/activities.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { ActivityActions } from '@/entities/activities';
import { ActivityActionDto, ActivitySphereDto } from '@/shared/api';

import { ActivitySphere } from '@/shared/api';

export const actions: ActivityActions = [
export const actions: ActivityActionDto[] = [
{
id: 1,
name: 'created',
Expand All @@ -17,7 +15,7 @@ export const actions: ActivityActions = [
}
];

export const spheres: ActivitySphere[] = [
export const spheres: ActivitySphereDto[] = [
{
id: 1,
name: 'task',
Expand Down

0 comments on commit 42e6fea

Please sign in to comment.